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

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';
                   1237: __HALT_COMPILER();-G&install-pear-nozlib.pharArchive/Tar.php 4N ;
                   1238: m&Archive_Tar-1.3.7.tarp&4Np&簳續&Console/Getopt.php44N4杼l1m&Console_Getopt-1.3.0.tarR4NRt鋮辪&    index.phpO&4NO&'赲m&OS/Guess.php)4N)Lm&PEAR-1.9.4.tar4N﹛/鬽&PEAR.php縿4N縿髾盌m&PEAR/ChannelFile.php羟4N羟=^窆m&PEAR/ChannelFile/Parser.phpB4NB綤,&m&PEAR/Command.php24N29m&PEAR/Command/Common.php 4N 8>m&PEAR/Command/Install.php84N8鐄嶴m&PEAR/Command/Install.xml~!4N~!2m&PEAR/Common.php%f4N%f,
                   1239: m&PEAR/Config.php3
                   1240: &4N3
                   1241: &#襇?m&PEAR/Dependency2.php4N毵媘&PEAR/DependencyDB.php⺗4N⺗蓓錌m&PEAR/Downloader.phpG&4NG&玬&PEAR/Downloader/Package.php*&4N*&&m&PEAR/ErrorStack.php詣4N詣q)峬&PEAR/Exception.php64N6w4m&PEAR/Frontend.phpj4Nj乎弟m&PEAR/Frontend/CLI.php筪4N筪lF
                   1242: 緈&PEAR/Installer.php &4N &傡!m&PEAR/Installer/Role.php4Ncom&PEAR/Installer/Role/Common.php?4N?Р勝m&PEAR/Installer/Role/Data.phpY4NY錦6m&PEAR/Installer/Role/Data.xml&4N&f峴zm&PEAR/Installer/Role/Doc.phpV4NVOx曹m&PEAR/Installer/Role/Doc.xml&4N&h&P*m&PEAR/Installer/Role/Php.phpV4NVr海m&PEAR/Installer/Role/Php.xml&4N&z漲峬&PEAR/Installer/Role/Script.php_4N_Vm&PEAR/Installer/Role/Script.xml&4N&@vm&PEAR/Installer/Role/Test.phpY4NY       浱)m&PEAR/Installer/Role/Test.xml&4N&B] m&PEAR/PackageFile.php>4N>宝圸m&!PEAR/PackageFile/Generator/v1.php埮4N埮铹m&!PEAR/PackageFile/Generator/v2.phpq4Nq瓓4╩&PEAR/PackageFile/Parser/v1.php駺4N駺]&m&PEAR/PackageFile/Parser/v2.php4N甤苖&PEAR/PackageFile/v1.phpa4Na譐茺m&PEAR/PackageFile/v2.php&4N&]skm&!PEAR/PackageFile/v2/Validator.phpP&4NP&栁刴&PEAR/Registry.php>+&4N>+&'策*m&
PEAR/REST.php4N/8m&PEAR/REST/10.phpI4NI俶"蕀&PEAR/Start.php74N7 鴠#m&PEAR/Start/CLI.phpnR4NnR:砿&PEAR/Task/Common.php  4N 3鍠觤&PEAR/Task/Postinstallscript.php84N8,晢m&"PEAR/Task/Postinstallscript/rw.php4N杀Fm&PEAR/Task/Replace.php4N,手僲&PEAR/Task/Replace/rw.phpx4Nx钘om&PEAR/Task/Unixeol.php 4N :簲m&PEAR/Task/Unixeol/rw.php4N龚3鴐&PEAR/Task/Windowseol.php 4N 踿笻m&PEAR/Task/Windowseol/rw.php4NM"緈&PEAR/Validate.php}V4N}V濪m&PEAR/Validator/PECL.php4N帗S刴&PEAR/XMLParser.phpQ4NQ 眒&     PEAR5.php?4N?選蕀&Structures/Graph.php4Nr*m&,Structures/Graph/Manipulator/AcyclicTest.php4N1s蟤&2Structures/Graph/Manipulator/TopologicalSorter.php4N崶E鹠&Structures/Graph/Node.phpr+4Nr+鸇_m&Structures_Graph-1.0.4.tar,4N,墧f憁&
                   1243: System.php郠4N郠淫帺m&XML/Util.php膙4N膙瞫3m&XML_Util-1.2.1.tar&4N&7l燶m&<?php
                   1244: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   1245: 
                   1246: /**
                   1247:  * File::CSV
                   1248:  *
                   1249:  * PHP versions 4 and 5
                   1250:  *
                   1251:  * Copyright (c) 1997-2008,
                   1252:  * Vincent Blavet <vincent@phpconcept.net>
                   1253:  * All rights reserved.
                   1254:  *
                   1255:  * Redistribution and use in source and binary forms, with or without
                   1256:  * modification, are permitted provided that the following conditions are met:
                   1257:  *
                   1258:  *     * Redistributions of source code must retain the above copyright notice,
                   1259:  *       this list of conditions and the following disclaimer.
                   1260:  *     * Redistributions in binary form must reproduce the above copyright
                   1261:  *       notice, this list of conditions and the following disclaimer in the
                   1262:  *       documentation and/or other materials provided with the distribution.
                   1263:  *
                   1264:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   1265:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   1266:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   1267:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   1268:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   1269:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   1270:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   1271:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   1272:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   1273:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   1274:  *
                   1275:  * @category  File_Formats
                   1276:  * @package   Archive_Tar
                   1277:  * @author    Vincent Blavet <vincent@phpconcept.net>
                   1278:  * @copyright 1997-2010 The Authors
                   1279:  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
                   1280:  * @version   CVS: $Id: Tar.php 311709 2011-06-01 12:16:57Z mrook $
                   1281:  * @link      http://pear.php.net/package/Archive_Tar
                   1282:  */
                   1283: 
                   1284: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   1285: 
                   1286: define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
                   1287: define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
                   1288: 
                   1289: /**
                   1290: * Creates a (compressed) Tar archive
                   1291: *
                   1292: * @package Archive_Tar
                   1293: * @author  Vincent Blavet <vincent@phpconcept.net>
                   1294: * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
                   1295: * @version $Revision: 311709 $
                   1296: */
                   1297: class Archive_Tar extends PEAR
                   1298: {
                   1299:     /**
                   1300:     * @var string Name of the Tar
                   1301:     */
                   1302:     var $_tarname='';
                   1303: 
                   1304:     /**
                   1305:     * @var boolean if true, the Tar file will be gzipped
                   1306:     */
                   1307:     var $_compress=false;
                   1308: 
                   1309:     /**
                   1310:     * @var string Type of compression : 'none', 'gz' or 'bz2'
                   1311:     */
                   1312:     var $_compress_type='none';
                   1313: 
                   1314:     /**
                   1315:     * @var string Explode separator
                   1316:     */
                   1317:     var $_separator=' ';
                   1318: 
                   1319:     /**
                   1320:     * @var file descriptor
                   1321:     */
                   1322:     var $_file=0;
                   1323: 
                   1324:     /**
                   1325:     * @var string Local Tar name of a remote Tar (http:// or ftp://)
                   1326:     */
                   1327:     var $_temp_tarname='';
                   1328: 
                   1329:     /**
                   1330:     * @var string regular expression for ignoring files or directories
                   1331:     */
                   1332:     var $_ignore_regexp='';
                   1333: 
                   1334:     /**
                   1335:      * @var object PEAR_Error object
                   1336:      */
                   1337:     var $error_object=null; 
                   1338: 
                   1339:     // {{{ constructor
                   1340:     /**
                   1341:     * Archive_Tar Class constructor. This flavour of the constructor only
                   1342:     * declare a new Archive_Tar object, identifying it by the name of the
                   1343:     * tar file.
                   1344:     * If the compress argument is set the tar will be read or created as a
                   1345:     * gzip or bz2 compressed TAR file.
                   1346:     *
                   1347:     * @param string $p_tarname  The name of the tar archive to create
                   1348:     * @param string $p_compress can be null, 'gz' or 'bz2'. This
                   1349:     *               parameter indicates if gzip or bz2 compression
                   1350:     *               is required.  For compatibility reason the
                   1351:     *               boolean value 'true' means 'gz'.
                   1352:     *
                   1353:     * @access public
                   1354:     */
                   1355:     function Archive_Tar($p_tarname, $p_compress = null)
                   1356:     {
                   1357:         $this->PEAR();
                   1358:         $this->_compress = false;
                   1359:         $this->_compress_type = 'none';
                   1360:         if (($p_compress === null) || ($p_compress == '')) {
                   1361:             if (@file_exists($p_tarname)) {
                   1362:                 if ($fp = @fopen($p_tarname, "rb")) {
                   1363:                     // look for gzip magic cookie
                   1364:                     $data = fread($fp, 2);
                   1365:                     fclose($fp);
                   1366:                     if ($data == "\37\213") {
                   1367:                         $this->_compress = true;
                   1368:                         $this->_compress_type = 'gz';
                   1369:                         // No sure it's enought for a magic code ....
                   1370:                     } elseif ($data == "BZ") {
                   1371:                         $this->_compress = true;
                   1372:                         $this->_compress_type = 'bz2';
                   1373:                     }
                   1374:                 }
                   1375:             } else {
                   1376:                 // probably a remote file or some file accessible
                   1377:                 // through a stream interface
                   1378:                 if (substr($p_tarname, -2) == 'gz') {
                   1379:                     $this->_compress = true;
                   1380:                     $this->_compress_type = 'gz';
                   1381:                 } elseif ((substr($p_tarname, -3) == 'bz2') ||
                   1382:                           (substr($p_tarname, -2) == 'bz')) {
                   1383:                     $this->_compress = true;
                   1384:                     $this->_compress_type = 'bz2';
                   1385:                 }
                   1386:             }
                   1387:         } else {
                   1388:             if (($p_compress === true) || ($p_compress == 'gz')) {
                   1389:                 $this->_compress = true;
                   1390:                 $this->_compress_type = 'gz';
                   1391:             } else if ($p_compress == 'bz2') {
                   1392:                 $this->_compress = true;
                   1393:                 $this->_compress_type = 'bz2';
                   1394:             } else {
                   1395:                 $this->_error("Unsupported compression type '$p_compress'\n".
                   1396:                     "Supported types are 'gz' and 'bz2'.\n");
                   1397:                 return false;
                   1398:             }
                   1399:         }
                   1400:         $this->_tarname = $p_tarname;
                   1401:         if ($this->_compress) { // assert zlib or bz2 extension support
                   1402:             if ($this->_compress_type == 'gz')
                   1403:                 $extname = 'zlib';
                   1404:             else if ($this->_compress_type == 'bz2')
                   1405:                 $extname = 'bz2';
                   1406: 
                   1407:             if (!extension_loaded($extname)) {
                   1408:                 PEAR::loadExtension($extname);
                   1409:             }
                   1410:             if (!extension_loaded($extname)) {
                   1411:                 $this->_error("The extension '$extname' couldn't be found.\n".
                   1412:                     "Please make sure your version of PHP was built ".
                   1413:                     "with '$extname' support.\n");
                   1414:                 return false;
                   1415:             }
                   1416:         }
                   1417:     }
                   1418:     // }}}
                   1419: 
                   1420:     // {{{ destructor
                   1421:     function _Archive_Tar()
                   1422:     {
                   1423:         $this->_close();
                   1424:         // ----- Look for a local copy to delete
                   1425:         if ($this->_temp_tarname != '')
                   1426:             @unlink($this->_temp_tarname);
                   1427:         $this->_PEAR();
                   1428:     }
                   1429:     // }}}
                   1430: 
                   1431:     // {{{ create()
                   1432:     /**
                   1433:     * This method creates the archive file and add the files / directories
                   1434:     * that are listed in $p_filelist.
                   1435:     * If a file with the same name exist and is writable, it is replaced
                   1436:     * by the new tar.
                   1437:     * The method return false and a PEAR error text.
                   1438:     * The $p_filelist parameter can be an array of string, each string
                   1439:     * representing a filename or a directory name with their path if
                   1440:     * needed. It can also be a single string with names separated by a
                   1441:     * single blank.
                   1442:     * For each directory added in the archive, the files and
                   1443:     * sub-directories are also added.
                   1444:     * See also createModify() method for more details.
                   1445:     *
                   1446:     * @param array $p_filelist An array of filenames and directory names, or a
                   1447:     *              single string with names separated by a single
                   1448:     *              blank space.
                   1449:     *
                   1450:     * @return true on success, false on error.
                   1451:     * @see    createModify()
                   1452:     * @access public
                   1453:     */
                   1454:     function create($p_filelist)
                   1455:     {
                   1456:         return $this->createModify($p_filelist, '', '');
                   1457:     }
                   1458:     // }}}
                   1459: 
                   1460:     // {{{ add()
                   1461:     /**
                   1462:     * This method add the files / directories that are listed in $p_filelist in
                   1463:     * the archive. If the archive does not exist it is created.
                   1464:     * The method return false and a PEAR error text.
                   1465:     * The files and directories listed are only added at the end of the archive,
                   1466:     * even if a file with the same name is already archived.
                   1467:     * See also createModify() method for more details.
                   1468:     *
                   1469:     * @param array $p_filelist An array of filenames and directory names, or a
                   1470:     *              single string with names separated by a single
                   1471:     *              blank space.
                   1472:     *
                   1473:     * @return true on success, false on error.
                   1474:     * @see    createModify()
                   1475:     * @access public
                   1476:     */
                   1477:     function add($p_filelist)
                   1478:     {
                   1479:         return $this->addModify($p_filelist, '', '');
                   1480:     }
                   1481:     // }}}
                   1482: 
                   1483:     // {{{ extract()
                   1484:     function extract($p_path='')
                   1485:     {
                   1486:         return $this->extractModify($p_path, '');
                   1487:     }
                   1488:     // }}}
                   1489: 
                   1490:     // {{{ listContent()
                   1491:     function listContent()
                   1492:     {
                   1493:         $v_list_detail = array();
                   1494: 
                   1495:         if ($this->_openRead()) {
                   1496:             if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                   1497:                 unset($v_list_detail);
                   1498:                 $v_list_detail = 0;
                   1499:             }
                   1500:             $this->_close();
                   1501:         }
                   1502: 
                   1503:         return $v_list_detail;
                   1504:     }
                   1505:     // }}}
                   1506: 
                   1507:     // {{{ createModify()
                   1508:     /**
                   1509:     * This method creates the archive file and add the files / directories
                   1510:     * that are listed in $p_filelist.
                   1511:     * If the file already exists and is writable, it is replaced by the
                   1512:     * new tar. It is a create and not an add. If the file exists and is
                   1513:     * read-only or is a directory it is not replaced. The method return
                   1514:     * false and a PEAR error text.
                   1515:     * The $p_filelist parameter can be an array of string, each string
                   1516:     * representing a filename or a directory name with their path if
                   1517:     * needed. It can also be a single string with names separated by a
                   1518:     * single blank.
                   1519:     * The path indicated in $p_remove_dir will be removed from the
                   1520:     * memorized path of each file / directory listed when this path
                   1521:     * exists. By default nothing is removed (empty path '')
                   1522:     * The path indicated in $p_add_dir will be added at the beginning of
                   1523:     * the memorized path of each file / directory listed. However it can
                   1524:     * be set to empty ''. The adding of a path is done after the removing
                   1525:     * of path.
                   1526:     * The path add/remove ability enables the user to prepare an archive
                   1527:     * for extraction in a different path than the origin files are.
                   1528:     * See also addModify() method for file adding properties.
                   1529:     *
                   1530:     * @param array  $p_filelist   An array of filenames and directory names,
                   1531:     *                             or a single string with names separated by
                   1532:     *                             a single blank space.
                   1533:     * @param string $p_add_dir    A string which contains a path to be added
                   1534:     *                             to the memorized path of each element in
                   1535:     *                             the list.
                   1536:     * @param string $p_remove_dir A string which contains a path to be
                   1537:     *                             removed from the memorized path of each
                   1538:     *                             element in the list, when relevant.
                   1539:     *
                   1540:     * @return boolean true on success, false on error.
                   1541:     * @access public
                   1542:     * @see addModify()
                   1543:     */
                   1544:     function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   1545:     {
                   1546:         $v_result = true;
                   1547: 
                   1548:         if (!$this->_openWrite())
                   1549:             return false;
                   1550: 
                   1551:         if ($p_filelist != '') {
                   1552:             if (is_array($p_filelist))
                   1553:                 $v_list = $p_filelist;
                   1554:             elseif (is_string($p_filelist))
                   1555:                 $v_list = explode($this->_separator, $p_filelist);
                   1556:             else {
                   1557:                 $this->_cleanFile();
                   1558:                 $this->_error('Invalid file list');
                   1559:                 return false;
                   1560:             }
                   1561: 
                   1562:             $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
                   1563:         }
                   1564: 
                   1565:         if ($v_result) {
                   1566:             $this->_writeFooter();
                   1567:             $this->_close();
                   1568:         } else
                   1569:             $this->_cleanFile();
                   1570: 
                   1571:         return $v_result;
                   1572:     }
                   1573:     // }}}
                   1574: 
                   1575:     // {{{ addModify()
                   1576:     /**
                   1577:     * This method add the files / directories listed in $p_filelist at the
                   1578:     * end of the existing archive. If the archive does not yet exists it
                   1579:     * is created.
                   1580:     * The $p_filelist parameter can be an array of string, each string
                   1581:     * representing a filename or a directory name with their path if
                   1582:     * needed. It can also be a single string with names separated by a
                   1583:     * single blank.
                   1584:     * The path indicated in $p_remove_dir will be removed from the
                   1585:     * memorized path of each file / directory listed when this path
                   1586:     * exists. By default nothing is removed (empty path '')
                   1587:     * The path indicated in $p_add_dir will be added at the beginning of
                   1588:     * the memorized path of each file / directory listed. However it can
                   1589:     * be set to empty ''. The adding of a path is done after the removing
                   1590:     * of path.
                   1591:     * The path add/remove ability enables the user to prepare an archive
                   1592:     * for extraction in a different path than the origin files are.
                   1593:     * If a file/dir is already in the archive it will only be added at the
                   1594:     * end of the archive. There is no update of the existing archived
                   1595:     * file/dir. However while extracting the archive, the last file will
                   1596:     * replace the first one. This results in a none optimization of the
                   1597:     * archive size.
                   1598:     * If a file/dir does not exist the file/dir is ignored. However an
                   1599:     * error text is send to PEAR error.
                   1600:     * If a file/dir is not readable the file/dir is ignored. However an
                   1601:     * error text is send to PEAR error.
                   1602:     *
                   1603:     * @param array  $p_filelist   An array of filenames and directory
                   1604:     *                             names, or a single string with names
                   1605:     *                             separated by a single blank space.
                   1606:     * @param string $p_add_dir    A string which contains a path to be
                   1607:     *                             added to the memorized path of each
                   1608:     *                             element in the list.
                   1609:     * @param string $p_remove_dir A string which contains a path to be
                   1610:     *                             removed from the memorized path of
                   1611:     *                             each element in the list, when
                   1612:     *                             relevant.
                   1613:     *
                   1614:     * @return true on success, false on error.
                   1615:     * @access public
                   1616:     */
                   1617:     function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   1618:     {
                   1619:         $v_result = true;
                   1620: 
                   1621:         if (!$this->_isArchive())
                   1622:             $v_result = $this->createModify($p_filelist, $p_add_dir,
                   1623:                                             $p_remove_dir);
                   1624:         else {
                   1625:             if (is_array($p_filelist))
                   1626:                 $v_list = $p_filelist;
                   1627:             elseif (is_string($p_filelist))
                   1628:                 $v_list = explode($this->_separator, $p_filelist);
                   1629:             else {
                   1630:                 $this->_error('Invalid file list');
                   1631:                 return false;
                   1632:             }
                   1633: 
                   1634:             $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
                   1635:         }
                   1636: 
                   1637:         return $v_result;
                   1638:     }
                   1639:     // }}}
                   1640: 
                   1641:     // {{{ addString()
                   1642:     /**
                   1643:     * This method add a single string as a file at the
                   1644:     * end of the existing archive. If the archive does not yet exists it
                   1645:     * is created.
                   1646:     *
                   1647:     * @param string $p_filename A string which contains the full
                   1648:     *                           filename path that will be associated
                   1649:     *                           with the string.
                   1650:     * @param string $p_string   The content of the file added in
                   1651:     *                           the archive.
                   1652:     *
                   1653:     * @return true on success, false on error.
                   1654:     * @access public
                   1655:     */
                   1656:     function addString($p_filename, $p_string)
                   1657:     {
                   1658:         $v_result = true;
                   1659: 
                   1660:         if (!$this->_isArchive()) {
                   1661:             if (!$this->_openWrite()) {
                   1662:                 return false;
                   1663:             }
                   1664:             $this->_close();
                   1665:         }
                   1666: 
                   1667:         if (!$this->_openAppend())
                   1668:             return false;
                   1669: 
                   1670:         // Need to check the get back to the temporary file ? ....
                   1671:         $v_result = $this->_addString($p_filename, $p_string);
                   1672: 
                   1673:         $this->_writeFooter();
                   1674: 
                   1675:         $this->_close();
                   1676: 
                   1677:         return $v_result;
                   1678:     }
                   1679:     // }}}
                   1680: 
                   1681:     // {{{ extractModify()
                   1682:     /**
                   1683:     * This method extract all the content of the archive in the directory
                   1684:     * indicated by $p_path. When relevant the memorized path of the
                   1685:     * files/dir can be modified by removing the $p_remove_path path at the
                   1686:     * beginning of the file/dir path.
                   1687:     * While extracting a file, if the directory path does not exists it is
                   1688:     * created.
                   1689:     * While extracting a file, if the file already exists it is replaced
                   1690:     * without looking for last modification date.
                   1691:     * While extracting a file, if the file already exists and is write
                   1692:     * protected, the extraction is aborted.
                   1693:     * While extracting a file, if a directory with the same name already
                   1694:     * exists, the extraction is aborted.
                   1695:     * While extracting a directory, if a file with the same name already
                   1696:     * exists, the extraction is aborted.
                   1697:     * While extracting a file/directory if the destination directory exist
                   1698:     * and is write protected, or does not exist but can not be created,
                   1699:     * the extraction is aborted.
                   1700:     * If after extraction an extracted file does not show the correct
                   1701:     * stored file size, the extraction is aborted.
                   1702:     * When the extraction is aborted, a PEAR error text is set and false
                   1703:     * is returned. However the result can be a partial extraction that may
                   1704:     * need to be manually cleaned.
                   1705:     *
                   1706:     * @param string $p_path        The path of the directory where the
                   1707:     *                              files/dir need to by extracted.
                   1708:     * @param string $p_remove_path Part of the memorized path that can be
                   1709:     *                              removed if present at the beginning of
                   1710:     *                              the file/dir path.
                   1711:     *
                   1712:     * @return boolean true on success, false on error.
                   1713:     * @access public
                   1714:     * @see    extractList()
                   1715:     */
                   1716:     function extractModify($p_path, $p_remove_path)
                   1717:     {
                   1718:         $v_result = true;
                   1719:         $v_list_detail = array();
                   1720: 
                   1721:         if ($v_result = $this->_openRead()) {
                   1722:             $v_result = $this->_extractList($p_path, $v_list_detail,
                   1723:                                                        "complete", 0, $p_remove_path);
                   1724:             $this->_close();
                   1725:         }
                   1726: 
                   1727:         return $v_result;
                   1728:     }
                   1729:     // }}}
                   1730: 
                   1731:     // {{{ extractInString()
                   1732:     /**
                   1733:     * This method extract from the archive one file identified by $p_filename.
                   1734:     * The return value is a string with the file content, or NULL on error.
                   1735:     *
                   1736:     * @param string $p_filename The path of the file to extract in a string.
                   1737:     *
                   1738:     * @return a string with the file content or NULL.
                   1739:     * @access public
                   1740:     */
                   1741:     function extractInString($p_filename)
                   1742:     {
                   1743:         if ($this->_openRead()) {
                   1744:             $v_result = $this->_extractInString($p_filename);
                   1745:             $this->_close();
                   1746:         } else {
                   1747:             $v_result = null;
                   1748:         }
                   1749: 
                   1750:         return $v_result;
                   1751:     }
                   1752:     // }}}
                   1753: 
                   1754:     // {{{ extractList()
                   1755:     /**
                   1756:     * This method extract from the archive only the files indicated in the
                   1757:     * $p_filelist. These files are extracted in the current directory or
                   1758:     * in the directory indicated by the optional $p_path parameter.
                   1759:     * If indicated the $p_remove_path can be used in the same way as it is
                   1760:     * used in extractModify() method.
                   1761:     *
                   1762:     * @param array  $p_filelist    An array of filenames and directory names,
                   1763:     *                              or a single string with names separated
                   1764:     *                              by a single blank space.
                   1765:     * @param string $p_path        The path of the directory where the
                   1766:     *                              files/dir need to by extracted.
                   1767:     * @param string $p_remove_path Part of the memorized path that can be
                   1768:     *                              removed if present at the beginning of
                   1769:     *                              the file/dir path.
                   1770:     *
                   1771:     * @return true on success, false on error.
                   1772:     * @access public
                   1773:     * @see    extractModify()
                   1774:     */
                   1775:     function extractList($p_filelist, $p_path='', $p_remove_path='')
                   1776:     {
                   1777:         $v_result = true;
                   1778:         $v_list_detail = array();
                   1779: 
                   1780:         if (is_array($p_filelist))
                   1781:             $v_list = $p_filelist;
                   1782:         elseif (is_string($p_filelist))
                   1783:             $v_list = explode($this->_separator, $p_filelist);
                   1784:         else {
                   1785:             $this->_error('Invalid string list');
                   1786:             return false;
                   1787:         }
                   1788: 
                   1789:         if ($v_result = $this->_openRead()) {
                   1790:             $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
                   1791:                                                        $v_list, $p_remove_path);
                   1792:             $this->_close();
                   1793:         }
                   1794: 
                   1795:         return $v_result;
                   1796:     }
                   1797:     // }}}
                   1798: 
                   1799:     // {{{ setAttribute()
                   1800:     /**
                   1801:     * This method set specific attributes of the archive. It uses a variable
                   1802:     * list of parameters, in the format attribute code + attribute values :
                   1803:     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
                   1804:     *
                   1805:     * @param mixed $argv variable list of attributes and values
                   1806:     *
                   1807:     * @return true on success, false on error.
                   1808:     * @access public
                   1809:     */
                   1810:     function setAttribute()
                   1811:     {
                   1812:         $v_result = true;
                   1813: 
                   1814:         // ----- Get the number of variable list of arguments
                   1815:         if (($v_size = func_num_args()) == 0) {
                   1816:             return true;
                   1817:         }
                   1818: 
                   1819:         // ----- Get the arguments
                   1820:         $v_att_list = &func_get_args();
                   1821: 
                   1822:         // ----- Read the attributes
                   1823:         $i=0;
                   1824:         while ($i<$v_size) {
                   1825: 
                   1826:             // ----- Look for next option
                   1827:             switch ($v_att_list[$i]) {
                   1828:                 // ----- Look for options that request a string value
                   1829:                 case ARCHIVE_TAR_ATT_SEPARATOR :
                   1830:                     // ----- Check the number of parameters
                   1831:                     if (($i+1) >= $v_size) {
                   1832:                         $this->_error('Invalid number of parameters for '
                   1833:                                                              .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
                   1834:                         return false;
                   1835:                     }
                   1836: 
                   1837:                     // ----- Get the value
                   1838:                     $this->_separator = $v_att_list[$i+1];
                   1839:                     $i++;
                   1840:                 break;
                   1841: 
                   1842:                 default :
                   1843:                     $this->_error('Unknow attribute code '.$v_att_list[$i].'');
                   1844:                     return false;
                   1845:             }
                   1846: 
                   1847:             // ----- Next attribute
                   1848:             $i++;
                   1849:         }
                   1850: 
                   1851:         return $v_result;
                   1852:     }
                   1853:     // }}}
                   1854: 
                   1855:     // {{{ setIgnoreRegexp()
                   1856:     /**
                   1857:     * This method sets the regular expression for ignoring files and directories
                   1858:     * at import, for example:
                   1859:     * $arch->setIgnoreRegexp("#CVS|\.svn#");
                   1860:     *
                   1861:     * @param string $regexp regular expression defining which files or directories to ignore
                   1862:     *
                   1863:     * @access public
                   1864:     */
                   1865:     function setIgnoreRegexp($regexp)
                   1866:     {
                   1867:        $this->_ignore_regexp = $regexp;
                   1868:     }
                   1869:     // }}}
                   1870: 
                   1871:     // {{{ setIgnoreList()
                   1872:     /**
                   1873:     * This method sets the regular expression for ignoring all files and directories
                   1874:     * matching the filenames in the array list at import, for example:
                   1875:     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
                   1876:     *
                   1877:     * @param array $list a list of file or directory names to ignore
                   1878:     *
                   1879:     * @access public
                   1880:     */
                   1881:     function setIgnoreList($list)
                   1882:     {
                   1883:        $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
                   1884:        $regexp = '#/'.join('$|/', $list).'#';
                   1885:        $this->setIgnoreRegexp($regexp);
                   1886:     }
                   1887:     // }}}
                   1888: 
                   1889:     // {{{ _error()
                   1890:     function _error($p_message)
                   1891:     {
                   1892:         $this->error_object = &$this->raiseError($p_message); 
                   1893:     }
                   1894:     // }}}
                   1895: 
                   1896:     // {{{ _warning()
                   1897:     function _warning($p_message)
                   1898:     {
                   1899:         $this->error_object = &$this->raiseError($p_message); 
                   1900:     }
                   1901:     // }}}
                   1902: 
                   1903:     // {{{ _isArchive()
                   1904:     function _isArchive($p_filename=null)
                   1905:     {
                   1906:         if ($p_filename == null) {
                   1907:             $p_filename = $this->_tarname;
                   1908:         }
                   1909:         clearstatcache();
                   1910:         return @is_file($p_filename) && !@is_link($p_filename);
                   1911:     }
                   1912:     // }}}
                   1913: 
                   1914:     // {{{ _openWrite()
                   1915:     function _openWrite()
                   1916:     {
                   1917:         if ($this->_compress_type == 'gz')
                   1918:             $this->_file = @gzopen($this->_tarname, "wb9");
                   1919:         else if ($this->_compress_type == 'bz2')
                   1920:             $this->_file = @bzopen($this->_tarname, "w");
                   1921:         else if ($this->_compress_type == 'none')
                   1922:             $this->_file = @fopen($this->_tarname, "wb");
                   1923:         else
                   1924:             $this->_error('Unknown or missing compression type ('
                   1925:                                      .$this->_compress_type.')');
                   1926: 
                   1927:         if ($this->_file == 0) {
                   1928:             $this->_error('Unable to open in write mode \''
                   1929:                                      .$this->_tarname.'\'');
                   1930:             return false;
                   1931:         }
                   1932: 
                   1933:         return true;
                   1934:     }
                   1935:     // }}}
                   1936: 
                   1937:     // {{{ _openRead()
                   1938:     function _openRead()
                   1939:     {
                   1940:         if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
                   1941: 
                   1942:           // ----- Look if a local copy need to be done
                   1943:           if ($this->_temp_tarname == '') {
                   1944:               $this->_temp_tarname = uniqid('tar').'.tmp';
                   1945:               if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
                   1946:                 $this->_error('Unable to open in read mode \''
                   1947:                                              .$this->_tarname.'\'');
                   1948:                 $this->_temp_tarname = '';
                   1949:                 return false;
                   1950:               }
                   1951:               if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
                   1952:                 $this->_error('Unable to open in write mode \''
                   1953:                                              .$this->_temp_tarname.'\'');
                   1954:                 $this->_temp_tarname = '';
                   1955:                 return false;
                   1956:               }
                   1957:               while ($v_data = @fread($v_file_from, 1024))
                   1958:                   @fwrite($v_file_to, $v_data);
                   1959:               @fclose($v_file_from);
                   1960:               @fclose($v_file_to);
                   1961:           }
                   1962: 
                   1963:           // ----- File to open if the local copy
                   1964:           $v_filename = $this->_temp_tarname;
                   1965: 
                   1966:         } else
                   1967:           // ----- File to open if the normal Tar file
                   1968:           $v_filename = $this->_tarname;
                   1969: 
                   1970:         if ($this->_compress_type == 'gz')
                   1971:             $this->_file = @gzopen($v_filename, "rb");
                   1972:         else if ($this->_compress_type == 'bz2')
                   1973:             $this->_file = @bzopen($v_filename, "r");
                   1974:         else if ($this->_compress_type == 'none')
                   1975:             $this->_file = @fopen($v_filename, "rb");
                   1976:         else
                   1977:             $this->_error('Unknown or missing compression type ('
                   1978:                                      .$this->_compress_type.')');
                   1979: 
                   1980:         if ($this->_file == 0) {
                   1981:             $this->_error('Unable to open in read mode \''.$v_filename.'\'');
                   1982:             return false;
                   1983:         }
                   1984: 
                   1985:         return true;
                   1986:     }
                   1987:     // }}}
                   1988: 
                   1989:     // {{{ _openReadWrite()
                   1990:     function _openReadWrite()
                   1991:     {
                   1992:         if ($this->_compress_type == 'gz')
                   1993:             $this->_file = @gzopen($this->_tarname, "r+b");
                   1994:         else if ($this->_compress_type == 'bz2') {
                   1995:             $this->_error('Unable to open bz2 in read/write mode \''
                   1996:                                      .$this->_tarname.'\' (limitation of bz2 extension)');
                   1997:             return false;
                   1998:         } else if ($this->_compress_type == 'none')
                   1999:             $this->_file = @fopen($this->_tarname, "r+b");
                   2000:         else
                   2001:             $this->_error('Unknown or missing compression type ('
                   2002:                                      .$this->_compress_type.')');
                   2003: 
                   2004:         if ($this->_file == 0) {
                   2005:             $this->_error('Unable to open in read/write mode \''
                   2006:                                      .$this->_tarname.'\'');
                   2007:             return false;
                   2008:         }
                   2009: 
                   2010:         return true;
                   2011:     }
                   2012:     // }}}
                   2013: 
                   2014:     // {{{ _close()
                   2015:     function _close()
                   2016:     {
                   2017:         //if (isset($this->_file)) {
                   2018:         if (is_resource($this->_file)) {
                   2019:             if ($this->_compress_type == 'gz')
                   2020:                 @gzclose($this->_file);
                   2021:             else if ($this->_compress_type == 'bz2')
                   2022:                 @bzclose($this->_file);
                   2023:             else if ($this->_compress_type == 'none')
                   2024:                 @fclose($this->_file);
                   2025:             else
                   2026:                 $this->_error('Unknown or missing compression type ('
                   2027:                                              .$this->_compress_type.')');
                   2028: 
                   2029:             $this->_file = 0;
                   2030:         }
                   2031: 
                   2032:         // ----- Look if a local copy need to be erase
                   2033:         // Note that it might be interesting to keep the url for a time : ToDo
                   2034:         if ($this->_temp_tarname != '') {
                   2035:             @unlink($this->_temp_tarname);
                   2036:             $this->_temp_tarname = '';
                   2037:         }
                   2038: 
                   2039:         return true;
                   2040:     }
                   2041:     // }}}
                   2042: 
                   2043:     // {{{ _cleanFile()
                   2044:     function _cleanFile()
                   2045:     {
                   2046:         $this->_close();
                   2047: 
                   2048:         // ----- Look for a local copy
                   2049:         if ($this->_temp_tarname != '') {
                   2050:             // ----- Remove the local copy but not the remote tarname
                   2051:             @unlink($this->_temp_tarname);
                   2052:             $this->_temp_tarname = '';
                   2053:         } else {
                   2054:             // ----- Remove the local tarname file
                   2055:             @unlink($this->_tarname);
                   2056:         }
                   2057:         $this->_tarname = '';
                   2058: 
                   2059:         return true;
                   2060:     }
                   2061:     // }}}
                   2062: 
                   2063:     // {{{ _writeBlock()
                   2064:     function _writeBlock($p_binary_data, $p_len=null)
                   2065:     {
                   2066:       if (is_resource($this->_file)) {
                   2067:           if ($p_len === null) {
                   2068:               if ($this->_compress_type == 'gz')
                   2069:                   @gzputs($this->_file, $p_binary_data);
                   2070:               else if ($this->_compress_type == 'bz2')
                   2071:                   @bzwrite($this->_file, $p_binary_data);
                   2072:               else if ($this->_compress_type == 'none')
                   2073:                   @fputs($this->_file, $p_binary_data);
                   2074:               else
                   2075:                   $this->_error('Unknown or missing compression type ('
                   2076:                                                .$this->_compress_type.')');
                   2077:           } else {
                   2078:               if ($this->_compress_type == 'gz')
                   2079:                   @gzputs($this->_file, $p_binary_data, $p_len);
                   2080:               else if ($this->_compress_type == 'bz2')
                   2081:                   @bzwrite($this->_file, $p_binary_data, $p_len);
                   2082:               else if ($this->_compress_type == 'none')
                   2083:                   @fputs($this->_file, $p_binary_data, $p_len);
                   2084:               else
                   2085:                   $this->_error('Unknown or missing compression type ('
                   2086:                                                .$this->_compress_type.')');
                   2087: 
                   2088:           }
                   2089:       }
                   2090:       return true;
                   2091:     }
                   2092:     // }}}
                   2093: 
                   2094:     // {{{ _readBlock()
                   2095:     function _readBlock()
                   2096:     {
                   2097:       $v_block = null;
                   2098:       if (is_resource($this->_file)) {
                   2099:           if ($this->_compress_type == 'gz')
                   2100:               $v_block = @gzread($this->_file, 512);
                   2101:           else if ($this->_compress_type == 'bz2')
                   2102:               $v_block = @bzread($this->_file, 512);
                   2103:           else if ($this->_compress_type == 'none')
                   2104:               $v_block = @fread($this->_file, 512);
                   2105:           else
                   2106:               $this->_error('Unknown or missing compression type ('
                   2107:                                        .$this->_compress_type.')');
                   2108:       }
                   2109:       return $v_block;
                   2110:     }
                   2111:     // }}}
                   2112: 
                   2113:     // {{{ _jumpBlock()
                   2114:     function _jumpBlock($p_len=null)
                   2115:     {
                   2116:       if (is_resource($this->_file)) {
                   2117:           if ($p_len === null)
                   2118:               $p_len = 1;
                   2119: 
                   2120:           if ($this->_compress_type == 'gz') {
                   2121:               @gzseek($this->_file, gztell($this->_file)+($p_len*512));
                   2122:           }
                   2123:           else if ($this->_compress_type == 'bz2') {
                   2124:               // ----- Replace missing bztell() and bzseek()
                   2125:               for ($i=0; $i<$p_len; $i++)
                   2126:                   $this->_readBlock();
                   2127:           } else if ($this->_compress_type == 'none')
                   2128:               @fseek($this->_file, $p_len*512, SEEK_CUR);
                   2129:           else
                   2130:               $this->_error('Unknown or missing compression type ('
                   2131:                                        .$this->_compress_type.')');
                   2132: 
                   2133:       }
                   2134:       return true;
                   2135:     }
                   2136:     // }}}
                   2137: 
                   2138:     // {{{ _writeFooter()
                   2139:     function _writeFooter()
                   2140:     {
                   2141:       if (is_resource($this->_file)) {
                   2142:           // ----- Write the last 0 filled block for end of archive
                   2143:           $v_binary_data = pack('a1024', '');
                   2144:           $this->_writeBlock($v_binary_data);
                   2145:       }
                   2146:       return true;
                   2147:     }
                   2148:     // }}}
                   2149: 
                   2150:     // {{{ _addList()
                   2151:     function _addList($p_list, $p_add_dir, $p_remove_dir)
                   2152:     {
                   2153:       $v_result=true;
                   2154:       $v_header = array();
                   2155: 
                   2156:       // ----- Remove potential windows directory separator
                   2157:       $p_add_dir = $this->_translateWinPath($p_add_dir);
                   2158:       $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
                   2159: 
                   2160:       if (!$this->_file) {
                   2161:           $this->_error('Invalid file descriptor');
                   2162:           return false;
                   2163:       }
                   2164: 
                   2165:       if (sizeof($p_list) == 0)
                   2166:           return true;
                   2167: 
                   2168:       foreach ($p_list as $v_filename) {
                   2169:           if (!$v_result) {
                   2170:               break;
                   2171:           }
                   2172: 
                   2173:         // ----- Skip the current tar name
                   2174:         if ($v_filename == $this->_tarname)
                   2175:             continue;
                   2176: 
                   2177:         if ($v_filename == '')
                   2178:             continue;
                   2179: 
                   2180:                // ----- ignore files and directories matching the ignore regular expression
                   2181:                if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
                   2182:             $this->_warning("File '$v_filename' ignored");
                   2183:                    continue;
                   2184:                }
                   2185: 
                   2186:         if (!file_exists($v_filename) && !is_link($v_filename)) {
                   2187:             $this->_warning("File '$v_filename' does not exist");
                   2188:             continue;
                   2189:         }
                   2190: 
                   2191:         // ----- Add the file or directory header
                   2192:         if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
                   2193:             return false;
                   2194: 
                   2195:         if (@is_dir($v_filename) && !@is_link($v_filename)) {
                   2196:             if (!($p_hdir = opendir($v_filename))) {
                   2197:                 $this->_warning("Directory '$v_filename' can not be read");
                   2198:                 continue;
                   2199:             }
                   2200:             while (false !== ($p_hitem = readdir($p_hdir))) {
                   2201:                 if (($p_hitem != '.') && ($p_hitem != '..')) {
                   2202:                     if ($v_filename != ".")
                   2203:                         $p_temp_list[0] = $v_filename.'/'.$p_hitem;
                   2204:                     else
                   2205:                         $p_temp_list[0] = $p_hitem;
                   2206: 
                   2207:                     $v_result = $this->_addList($p_temp_list,
                   2208:                                                                    $p_add_dir,
                   2209:                                                                                                $p_remove_dir);
                   2210:                 }
                   2211:             }
                   2212: 
                   2213:             unset($p_temp_list);
                   2214:             unset($p_hdir);
                   2215:             unset($p_hitem);
                   2216:         }
                   2217:       }
                   2218: 
                   2219:       return $v_result;
                   2220:     }
                   2221:     // }}}
                   2222: 
                   2223:     // {{{ _addFile()
                   2224:     function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
                   2225:     {
                   2226:       if (!$this->_file) {
                   2227:           $this->_error('Invalid file descriptor');
                   2228:           return false;
                   2229:       }
                   2230: 
                   2231:       if ($p_filename == '') {
                   2232:           $this->_error('Invalid file name');
                   2233:           return false;
                   2234:       }
                   2235: 
                   2236:       // ----- Calculate the stored filename
                   2237:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   2238:       $v_stored_filename = $p_filename;
                   2239:       if (strcmp($p_filename, $p_remove_dir) == 0) {
                   2240:           return true;
                   2241:       }
                   2242:       if ($p_remove_dir != '') {
                   2243:           if (substr($p_remove_dir, -1) != '/')
                   2244:               $p_remove_dir .= '/';
                   2245: 
                   2246:           if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
                   2247:               $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
                   2248:       }
                   2249:       $v_stored_filename = $this->_translateWinPath($v_stored_filename);
                   2250:       if ($p_add_dir != '') {
                   2251:           if (substr($p_add_dir, -1) == '/')
                   2252:               $v_stored_filename = $p_add_dir.$v_stored_filename;
                   2253:           else
                   2254:               $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
                   2255:       }
                   2256: 
                   2257:       $v_stored_filename = $this->_pathReduction($v_stored_filename);
                   2258: 
                   2259:       if ($this->_isArchive($p_filename)) {
                   2260:           if (($v_file = @fopen($p_filename, "rb")) == 0) {
                   2261:               $this->_warning("Unable to open file '".$p_filename
                   2262:                                          ."' in binary read mode");
                   2263:               return true;
                   2264:           }
                   2265: 
                   2266:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   2267:               return false;
                   2268: 
                   2269:           while (($v_buffer = fread($v_file, 512)) != '') {
                   2270:               $v_binary_data = pack("a512", "$v_buffer");
                   2271:               $this->_writeBlock($v_binary_data);
                   2272:           }
                   2273: 
                   2274:           fclose($v_file);
                   2275: 
                   2276:       } else {
                   2277:           // ----- Only header for dir
                   2278:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   2279:               return false;
                   2280:       }
                   2281: 
                   2282:       return true;
                   2283:     }
                   2284:     // }}}
                   2285: 
                   2286:     // {{{ _addString()
                   2287:     function _addString($p_filename, $p_string)
                   2288:     {
                   2289:       if (!$this->_file) {
                   2290:           $this->_error('Invalid file descriptor');
                   2291:           return false;
                   2292:       }
                   2293: 
                   2294:       if ($p_filename == '') {
                   2295:           $this->_error('Invalid file name');
                   2296:           return false;
                   2297:       }
                   2298: 
                   2299:       // ----- Calculate the stored filename
                   2300:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   2301: 
                   2302:       if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
                   2303:                                          time(), 384, "", 0, 0))
                   2304:           return false;
                   2305: 
                   2306:       $i=0;
                   2307:       while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
                   2308:           $v_binary_data = pack("a512", $v_buffer);
                   2309:           $this->_writeBlock($v_binary_data);
                   2310:       }
                   2311: 
                   2312:       return true;
                   2313:     }
                   2314:     // }}}
                   2315: 
                   2316:     // {{{ _writeHeader()
                   2317:     function _writeHeader($p_filename, $p_stored_filename)
                   2318:     {
                   2319:         if ($p_stored_filename == '')
                   2320:             $p_stored_filename = $p_filename;
                   2321:         $v_reduce_filename = $this->_pathReduction($p_stored_filename);
                   2322: 
                   2323:         if (strlen($v_reduce_filename) > 99) {
                   2324:           if (!$this->_writeLongHeader($v_reduce_filename))
                   2325:             return false;
                   2326:         }
                   2327: 
                   2328:         $v_info = lstat($p_filename);
                   2329:         $v_uid = sprintf("%07s", DecOct($v_info[4]));
                   2330:         $v_gid = sprintf("%07s", DecOct($v_info[5]));
                   2331:         $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
                   2332: 
                   2333:         $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
                   2334: 
                   2335:         $v_linkname = '';
                   2336: 
                   2337:         if (@is_link($p_filename)) {
                   2338:           $v_typeflag = '2';
                   2339:           $v_linkname = readlink($p_filename);
                   2340:           $v_size = sprintf("%011s", DecOct(0));
                   2341:         } elseif (@is_dir($p_filename)) {
                   2342:           $v_typeflag = "5";
                   2343:           $v_size = sprintf("%011s", DecOct(0));
                   2344:         } else {
                   2345:           $v_typeflag = '0';
                   2346:           clearstatcache();
                   2347:           $v_size = sprintf("%011s", DecOct($v_info['size']));
                   2348:         }
                   2349: 
                   2350:         $v_magic = 'ustar ';
                   2351: 
                   2352:         $v_version = ' ';
                   2353:         
                   2354:         if (function_exists('posix_getpwuid'))
                   2355:         {
                   2356:           $userinfo = posix_getpwuid($v_info[4]);
                   2357:           $groupinfo = posix_getgrgid($v_info[5]);
                   2358:           
                   2359:           $v_uname = $userinfo['name'];
                   2360:           $v_gname = $groupinfo['name'];
                   2361:         }
                   2362:         else
                   2363:         {
                   2364:           $v_uname = '';
                   2365:           $v_gname = '';
                   2366:         }
                   2367: 
                   2368:         $v_devmajor = '';
                   2369: 
                   2370:         $v_devminor = '';
                   2371: 
                   2372:         $v_prefix = '';
                   2373: 
                   2374:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   2375:                                            $v_reduce_filename, $v_perms, $v_uid,
                   2376:                                                                        $v_gid, $v_size, $v_mtime);
                   2377:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2378:                                           $v_typeflag, $v_linkname, $v_magic,
                   2379:                                                                   $v_version, $v_uname, $v_gname,
                   2380:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2381: 
                   2382:         // ----- Calculate the checksum
                   2383:         $v_checksum = 0;
                   2384:         // ..... First part of the header
                   2385:         for ($i=0; $i<148; $i++)
                   2386:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2387:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2388:         for ($i=148; $i<156; $i++)
                   2389:             $v_checksum += ord(' ');
                   2390:         // ..... Last part of the header
                   2391:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2392:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2393: 
                   2394:         // ----- Write the first 148 bytes of the header in the archive
                   2395:         $this->_writeBlock($v_binary_data_first, 148);
                   2396: 
                   2397:         // ----- Write the calculated checksum
                   2398:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2399:         $v_binary_data = pack("a8", $v_checksum);
                   2400:         $this->_writeBlock($v_binary_data, 8);
                   2401: 
                   2402:         // ----- Write the last 356 bytes of the header in the archive
                   2403:         $this->_writeBlock($v_binary_data_last, 356);
                   2404: 
                   2405:         return true;
                   2406:     }
                   2407:     // }}}
                   2408: 
                   2409:     // {{{ _writeHeaderBlock()
                   2410:     function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
                   2411:                                   $p_type='', $p_uid=0, $p_gid=0)
                   2412:     {
                   2413:         $p_filename = $this->_pathReduction($p_filename);
                   2414: 
                   2415:         if (strlen($p_filename) > 99) {
                   2416:           if (!$this->_writeLongHeader($p_filename))
                   2417:             return false;
                   2418:         }
                   2419: 
                   2420:         if ($p_type == "5") {
                   2421:           $v_size = sprintf("%011s", DecOct(0));
                   2422:         } else {
                   2423:           $v_size = sprintf("%011s", DecOct($p_size));
                   2424:         }
                   2425: 
                   2426:         $v_uid = sprintf("%07s", DecOct($p_uid));
                   2427:         $v_gid = sprintf("%07s", DecOct($p_gid));
                   2428:         $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
                   2429: 
                   2430:         $v_mtime = sprintf("%11s", DecOct($p_mtime));
                   2431: 
                   2432:         $v_linkname = '';
                   2433: 
                   2434:         $v_magic = 'ustar ';
                   2435: 
                   2436:         $v_version = ' ';
                   2437: 
                   2438:         if (function_exists('posix_getpwuid'))
                   2439:         {
                   2440:           $userinfo = posix_getpwuid($p_uid);
                   2441:           $groupinfo = posix_getgrgid($p_gid);
                   2442:           
                   2443:           $v_uname = $userinfo['name'];
                   2444:           $v_gname = $groupinfo['name'];
                   2445:         }
                   2446:         else
                   2447:         {
                   2448:           $v_uname = '';
                   2449:           $v_gname = '';
                   2450:         }
                   2451:         
                   2452:         $v_devmajor = '';
                   2453: 
                   2454:         $v_devminor = '';
                   2455: 
                   2456:         $v_prefix = '';
                   2457: 
                   2458:         $v_binary_data_first = pack("a100a8a8a8a12A12",
                   2459:                                            $p_filename, $v_perms, $v_uid, $v_gid,
                   2460:                                                                        $v_size, $v_mtime);
                   2461:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2462:                                           $p_type, $v_linkname, $v_magic,
                   2463:                                                                   $v_version, $v_uname, $v_gname,
                   2464:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2465: 
                   2466:         // ----- Calculate the checksum
                   2467:         $v_checksum = 0;
                   2468:         // ..... First part of the header
                   2469:         for ($i=0; $i<148; $i++)
                   2470:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2471:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2472:         for ($i=148; $i<156; $i++)
                   2473:             $v_checksum += ord(' ');
                   2474:         // ..... Last part of the header
                   2475:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2476:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2477: 
                   2478:         // ----- Write the first 148 bytes of the header in the archive
                   2479:         $this->_writeBlock($v_binary_data_first, 148);
                   2480: 
                   2481:         // ----- Write the calculated checksum
                   2482:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2483:         $v_binary_data = pack("a8", $v_checksum);
                   2484:         $this->_writeBlock($v_binary_data, 8);
                   2485: 
                   2486:         // ----- Write the last 356 bytes of the header in the archive
                   2487:         $this->_writeBlock($v_binary_data_last, 356);
                   2488: 
                   2489:         return true;
                   2490:     }
                   2491:     // }}}
                   2492: 
                   2493:     // {{{ _writeLongHeader()
                   2494:     function _writeLongHeader($p_filename)
                   2495:     {
                   2496:         $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
                   2497: 
                   2498:         $v_typeflag = 'L';
                   2499: 
                   2500:         $v_linkname = '';
                   2501: 
                   2502:         $v_magic = '';
                   2503: 
                   2504:         $v_version = '';
                   2505: 
                   2506:         $v_uname = '';
                   2507: 
                   2508:         $v_gname = '';
                   2509: 
                   2510:         $v_devmajor = '';
                   2511: 
                   2512:         $v_devminor = '';
                   2513: 
                   2514:         $v_prefix = '';
                   2515: 
                   2516:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   2517:                                            '././@LongLink', 0, 0, 0, $v_size, 0);
                   2518:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2519:                                           $v_typeflag, $v_linkname, $v_magic,
                   2520:                                                                   $v_version, $v_uname, $v_gname,
                   2521:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2522: 
                   2523:         // ----- Calculate the checksum
                   2524:         $v_checksum = 0;
                   2525:         // ..... First part of the header
                   2526:         for ($i=0; $i<148; $i++)
                   2527:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2528:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2529:         for ($i=148; $i<156; $i++)
                   2530:             $v_checksum += ord(' ');
                   2531:         // ..... Last part of the header
                   2532:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2533:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2534: 
                   2535:         // ----- Write the first 148 bytes of the header in the archive
                   2536:         $this->_writeBlock($v_binary_data_first, 148);
                   2537: 
                   2538:         // ----- Write the calculated checksum
                   2539:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2540:         $v_binary_data = pack("a8", $v_checksum);
                   2541:         $this->_writeBlock($v_binary_data, 8);
                   2542: 
                   2543:         // ----- Write the last 356 bytes of the header in the archive
                   2544:         $this->_writeBlock($v_binary_data_last, 356);
                   2545: 
                   2546:         // ----- Write the filename as content of the block
                   2547:         $i=0;
                   2548:         while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
                   2549:             $v_binary_data = pack("a512", "$v_buffer");
                   2550:             $this->_writeBlock($v_binary_data);
                   2551:         }
                   2552: 
                   2553:         return true;
                   2554:     }
                   2555:     // }}}
                   2556: 
                   2557:     // {{{ _readHeader()
                   2558:     function _readHeader($v_binary_data, &$v_header)
                   2559:     {
                   2560:         if (strlen($v_binary_data)==0) {
                   2561:             $v_header['filename'] = '';
                   2562:             return true;
                   2563:         }
                   2564: 
                   2565:         if (strlen($v_binary_data) != 512) {
                   2566:             $v_header['filename'] = '';
                   2567:             $this->_error('Invalid block size : '.strlen($v_binary_data));
                   2568:             return false;
                   2569:         }
                   2570: 
                   2571:         if (!is_array($v_header)) {
                   2572:             $v_header = array();
                   2573:         }
                   2574:         // ----- Calculate the checksum
                   2575:         $v_checksum = 0;
                   2576:         // ..... First part of the header
                   2577:         for ($i=0; $i<148; $i++)
                   2578:             $v_checksum+=ord(substr($v_binary_data,$i,1));
                   2579:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2580:         for ($i=148; $i<156; $i++)
                   2581:             $v_checksum += ord(' ');
                   2582:         // ..... Last part of the header
                   2583:         for ($i=156; $i<512; $i++)
                   2584:            $v_checksum+=ord(substr($v_binary_data,$i,1));
                   2585: 
                   2586:         $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
                   2587:                                 ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
                   2588:                                                 ."a32uname/a32gname/a8devmajor/a8devminor",
                   2589:                                                 $v_binary_data);
                   2590: 
                   2591:         // ----- Extract the checksum
                   2592:         $v_header['checksum'] = OctDec(trim($v_data['checksum']));
                   2593:         if ($v_header['checksum'] != $v_checksum) {
                   2594:             $v_header['filename'] = '';
                   2595: 
                   2596:             // ----- Look for last block (empty block)
                   2597:             if (($v_checksum == 256) && ($v_header['checksum'] == 0))
                   2598:                 return true;
                   2599: 
                   2600:             $this->_error('Invalid checksum for file "'.$v_data['filename']
                   2601:                                      .'" : '.$v_checksum.' calculated, '
                   2602:                                                  .$v_header['checksum'].' expected');
                   2603:             return false;
                   2604:         }
                   2605: 
                   2606:         // ----- Extract the properties
                   2607:         $v_header['filename'] = $v_data['filename'];
                   2608:         if ($this->_maliciousFilename($v_header['filename'])) {
                   2609:             $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
                   2610:                 '" will not install in desired directory tree');
                   2611:             return false;
                   2612:         }
                   2613:         $v_header['mode'] = OctDec(trim($v_data['mode']));
                   2614:         $v_header['uid'] = OctDec(trim($v_data['uid']));
                   2615:         $v_header['gid'] = OctDec(trim($v_data['gid']));
                   2616:         $v_header['size'] = OctDec(trim($v_data['size']));
                   2617:         $v_header['mtime'] = OctDec(trim($v_data['mtime']));
                   2618:         if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
                   2619:           $v_header['size'] = 0;
                   2620:         }
                   2621:         $v_header['link'] = trim($v_data['link']);
                   2622:         /* ----- All these fields are removed form the header because
                   2623:                they do not carry interesting info
                   2624:         $v_header[magic] = trim($v_data[magic]);
                   2625:         $v_header[version] = trim($v_data[version]);
                   2626:         $v_header[uname] = trim($v_data[uname]);
                   2627:         $v_header[gname] = trim($v_data[gname]);
                   2628:         $v_header[devmajor] = trim($v_data[devmajor]);
                   2629:         $v_header[devminor] = trim($v_data[devminor]);
                   2630:         */
                   2631: 
                   2632:         return true;
                   2633:     }
                   2634:     // }}}
                   2635: 
                   2636:     // {{{ _maliciousFilename()
                   2637:     /**
                   2638:      * Detect and report a malicious file name
                   2639:      *
                   2640:      * @param string $file
                   2641:      *
                   2642:      * @return bool
                   2643:      * @access private
                   2644:      */
                   2645:     function _maliciousFilename($file)
                   2646:     {
                   2647:         if (strpos($file, '/../') !== false) {
                   2648:             return true;
                   2649:         }
                   2650:         if (strpos($file, '../') === 0) {
                   2651:             return true;
                   2652:         }
                   2653:         return false;
                   2654:     }
                   2655:     // }}}
                   2656: 
                   2657:     // {{{ _readLongHeader()
                   2658:     function _readLongHeader(&$v_header)
                   2659:     {
                   2660:       $v_filename = '';
                   2661:       $n = floor($v_header['size']/512);
                   2662:       for ($i=0; $i<$n; $i++) {
                   2663:         $v_content = $this->_readBlock();
                   2664:         $v_filename .= $v_content;
                   2665:       }
                   2666:       if (($v_header['size'] % 512) != 0) {
                   2667:         $v_content = $this->_readBlock();
                   2668:         $v_filename .= trim($v_content);
                   2669:       }
                   2670: 
                   2671:       // ----- Read the next header
                   2672:       $v_binary_data = $this->_readBlock();
                   2673: 
                   2674:       if (!$this->_readHeader($v_binary_data, $v_header))
                   2675:         return false;
                   2676: 
                   2677:       $v_filename = trim($v_filename);
                   2678:       $v_header['filename'] = $v_filename;
                   2679:         if ($this->_maliciousFilename($v_filename)) {
                   2680:             $this->_error('Malicious .tar detected, file "' . $v_filename .
                   2681:                 '" will not install in desired directory tree');
                   2682:             return false;
                   2683:       }
                   2684: 
                   2685:       return true;
                   2686:     }
                   2687:     // }}}
                   2688: 
                   2689:     // {{{ _extractInString()
                   2690:     /**
                   2691:     * This method extract from the archive one file identified by $p_filename.
                   2692:     * The return value is a string with the file content, or null on error.
                   2693:     *
                   2694:     * @param string $p_filename The path of the file to extract in a string.
                   2695:     *
                   2696:     * @return a string with the file content or null.
                   2697:     * @access private
                   2698:     */
                   2699:     function _extractInString($p_filename)
                   2700:     {
                   2701:         $v_result_str = "";
                   2702: 
                   2703:         While (strlen($v_binary_data = $this->_readBlock()) != 0)
                   2704:         {
                   2705:           if (!$this->_readHeader($v_binary_data, $v_header))
                   2706:             return null;
                   2707: 
                   2708:           if ($v_header['filename'] == '')
                   2709:             continue;
                   2710: 
                   2711:           // ----- Look for long filename
                   2712:           if ($v_header['typeflag'] == 'L') {
                   2713:             if (!$this->_readLongHeader($v_header))
                   2714:               return null;
                   2715:           }
                   2716: 
                   2717:           if ($v_header['filename'] == $p_filename) {
                   2718:               if ($v_header['typeflag'] == "5") {
                   2719:                   $this->_error('Unable to extract in string a directory '
                   2720:                                                .'entry {'.$v_header['filename'].'}');
                   2721:                   return null;
                   2722:               } else {
                   2723:                   $n = floor($v_header['size']/512);
                   2724:                   for ($i=0; $i<$n; $i++) {
                   2725:                       $v_result_str .= $this->_readBlock();
                   2726:                   }
                   2727:                   if (($v_header['size'] % 512) != 0) {
                   2728:                       $v_content = $this->_readBlock();
                   2729:                       $v_result_str .= substr($v_content, 0,
                   2730:                                                                  ($v_header['size'] % 512));
                   2731:                   }
                   2732:                   return $v_result_str;
                   2733:               }
                   2734:           } else {
                   2735:               $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2736:           }
                   2737:         }
                   2738: 
                   2739:         return null;
                   2740:     }
                   2741:     // }}}
                   2742: 
                   2743:     // {{{ _extractList()
                   2744:     function _extractList($p_path, &$p_list_detail, $p_mode,
                   2745:                              $p_file_list, $p_remove_path)
                   2746:     {
                   2747:     $v_result=true;
                   2748:     $v_nb = 0;
                   2749:     $v_extract_all = true;
                   2750:     $v_listing = false;
                   2751: 
                   2752:     $p_path = $this->_translateWinPath($p_path, false);
                   2753:     if ($p_path == '' || (substr($p_path, 0, 1) != '/'
                   2754:            && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
                   2755:       $p_path = "./".$p_path;
                   2756:     }
                   2757:     $p_remove_path = $this->_translateWinPath($p_remove_path);
                   2758: 
                   2759:     // ----- Look for path to remove format (should end by /)
                   2760:     if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
                   2761:       $p_remove_path .= '/';
                   2762:     $p_remove_path_size = strlen($p_remove_path);
                   2763: 
                   2764:     switch ($p_mode) {
                   2765:       case "complete" :
                   2766:         $v_extract_all = true;
                   2767:         $v_listing = false;
                   2768:       break;
                   2769:       case "partial" :
                   2770:           $v_extract_all = false;
                   2771:           $v_listing = false;
                   2772:       break;
                   2773:       case "list" :
                   2774:           $v_extract_all = false;
                   2775:           $v_listing = true;
                   2776:       break;
                   2777:       default :
                   2778:         $this->_error('Invalid extract mode ('.$p_mode.')');
                   2779:         return false;
                   2780:     }
                   2781: 
                   2782:     clearstatcache();
                   2783: 
                   2784:     while (strlen($v_binary_data = $this->_readBlock()) != 0)
                   2785:     {
                   2786:       $v_extract_file = FALSE;
                   2787:       $v_extraction_stopped = 0;
                   2788: 
                   2789:       if (!$this->_readHeader($v_binary_data, $v_header))
                   2790:         return false;
                   2791: 
                   2792:       if ($v_header['filename'] == '') {
                   2793:         continue;
                   2794:       }
                   2795: 
                   2796:       // ----- Look for long filename
                   2797:       if ($v_header['typeflag'] == 'L') {
                   2798:         if (!$this->_readLongHeader($v_header))
                   2799:           return false;
                   2800:       }
                   2801: 
                   2802:       if ((!$v_extract_all) && (is_array($p_file_list))) {
                   2803:         // ----- By default no unzip if the file is not found
                   2804:         $v_extract_file = false;
                   2805: 
                   2806:         for ($i=0; $i<sizeof($p_file_list); $i++) {
                   2807:           // ----- Look if it is a directory
                   2808:           if (substr($p_file_list[$i], -1) == '/') {
                   2809:             // ----- Look if the directory is in the filename path
                   2810:             if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
                   2811:                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
                   2812:                                    == $p_file_list[$i])) {
                   2813:               $v_extract_file = true;
                   2814:               break;
                   2815:             }
                   2816:           }
                   2817: 
                   2818:           // ----- It is a file, so compare the file names
                   2819:           elseif ($p_file_list[$i] == $v_header['filename']) {
                   2820:             $v_extract_file = true;
                   2821:             break;
                   2822:           }
                   2823:         }
                   2824:       } else {
                   2825:         $v_extract_file = true;
                   2826:       }
                   2827: 
                   2828:       // ----- Look if this file need to be extracted
                   2829:       if (($v_extract_file) && (!$v_listing))
                   2830:       {
                   2831:         if (($p_remove_path != '')
                   2832:             && (substr($v_header['filename'], 0, $p_remove_path_size)
                   2833:                            == $p_remove_path))
                   2834:           $v_header['filename'] = substr($v_header['filename'],
                   2835:                                                 $p_remove_path_size);
                   2836:         if (($p_path != './') && ($p_path != '/')) {
                   2837:           while (substr($p_path, -1) == '/')
                   2838:             $p_path = substr($p_path, 0, strlen($p_path)-1);
                   2839: 
                   2840:           if (substr($v_header['filename'], 0, 1) == '/')
                   2841:               $v_header['filename'] = $p_path.$v_header['filename'];
                   2842:           else
                   2843:             $v_header['filename'] = $p_path.'/'.$v_header['filename'];
                   2844:         }
                   2845:         if (file_exists($v_header['filename'])) {
                   2846:           if (   (@is_dir($v_header['filename']))
                   2847:                      && ($v_header['typeflag'] == '')) {
                   2848:             $this->_error('File '.$v_header['filename']
                   2849:                                      .' already exists as a directory');
                   2850:             return false;
                   2851:           }
                   2852:           if (   ($this->_isArchive($v_header['filename']))
                   2853:                      && ($v_header['typeflag'] == "5")) {
                   2854:             $this->_error('Directory '.$v_header['filename']
                   2855:                                      .' already exists as a file');
                   2856:             return false;
                   2857:           }
                   2858:           if (!is_writeable($v_header['filename'])) {
                   2859:             $this->_error('File '.$v_header['filename']
                   2860:                                      .' already exists and is write protected');
                   2861:             return false;
                   2862:           }
                   2863:           if (filemtime($v_header['filename']) > $v_header['mtime']) {
                   2864:             // To be completed : An error or silent no replace ?
                   2865:           }
                   2866:         }
                   2867: 
                   2868:         // ----- Check the directory availability and create it if necessary
                   2869:         elseif (($v_result
                   2870:                         = $this->_dirCheck(($v_header['typeflag'] == "5"
                   2871:                                                    ?$v_header['filename']
                   2872:                                                                        :dirname($v_header['filename'])))) != 1) {
                   2873:             $this->_error('Unable to create path for '.$v_header['filename']);
                   2874:             return false;
                   2875:         }
                   2876: 
                   2877:         if ($v_extract_file) {
                   2878:           if ($v_header['typeflag'] == "5") {
                   2879:             if (!@file_exists($v_header['filename'])) {
                   2880:                 if (!@mkdir($v_header['filename'], 0777)) {
                   2881:                     $this->_error('Unable to create directory {'
                   2882:                                                      .$v_header['filename'].'}');
                   2883:                     return false;
                   2884:                 }
                   2885:             }
                   2886:           } elseif ($v_header['typeflag'] == "2") {
                   2887:               if (@file_exists($v_header['filename'])) {
                   2888:                   @unlink($v_header['filename']);
                   2889:               }
                   2890:               if (!@symlink($v_header['link'], $v_header['filename'])) {
                   2891:                   $this->_error('Unable to extract symbolic link {'
                   2892:                                 .$v_header['filename'].'}');
                   2893:                   return false;
                   2894:               }
                   2895:           } else {
                   2896:               if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                   2897:                   $this->_error('Error while opening {'.$v_header['filename']
                   2898:                                                .'} in write binary mode');
                   2899:                   return false;
                   2900:               } else {
                   2901:                   $n = floor($v_header['size']/512);
                   2902:                   for ($i=0; $i<$n; $i++) {
                   2903:                       $v_content = $this->_readBlock();
                   2904:                       fwrite($v_dest_file, $v_content, 512);
                   2905:                   }
                   2906:             if (($v_header['size'] % 512) != 0) {
                   2907:               $v_content = $this->_readBlock();
                   2908:               fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
                   2909:             }
                   2910: 
                   2911:             @fclose($v_dest_file);
                   2912: 
                   2913:             // ----- Change the file mode, mtime
                   2914:             @touch($v_header['filename'], $v_header['mtime']);
                   2915:             if ($v_header['mode'] & 0111) {
                   2916:                 // make file executable, obey umask
                   2917:                 $mode = fileperms($v_header['filename']) | (~umask() & 0111);
                   2918:                 @chmod($v_header['filename'], $mode);
                   2919:             }
                   2920:           }
                   2921: 
                   2922:           // ----- Check the file size
                   2923:           clearstatcache();
                   2924:           if (!is_file($v_header['filename'])) {
                   2925:               $this->_error('Extracted file '.$v_header['filename']
                   2926:                             .'does not exist. Archive may be corrupted.');
                   2927:               return false;
                   2928:           }
                   2929:           
                   2930:           $filesize = filesize($v_header['filename']);
                   2931:           if ($filesize != $v_header['size']) {
                   2932:               $this->_error('Extracted file '.$v_header['filename']
                   2933:                             .' does not have the correct file size \''
                   2934:                             .$filesize
                   2935:                             .'\' ('.$v_header['size']
                   2936:                             .' expected). Archive may be corrupted.');
                   2937:               return false;
                   2938:           }
                   2939:           }
                   2940:         } else {
                   2941:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2942:         }
                   2943:       } else {
                   2944:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2945:       }
                   2946: 
                   2947:       /* TBC : Seems to be unused ...
                   2948:       if ($this->_compress)
                   2949:         $v_end_of_file = @gzeof($this->_file);
                   2950:       else
                   2951:         $v_end_of_file = @feof($this->_file);
                   2952:         */
                   2953: 
                   2954:       if ($v_listing || $v_extract_file || $v_extraction_stopped) {
                   2955:         // ----- Log extracted files
                   2956:         if (($v_file_dir = dirname($v_header['filename']))
                   2957:                    == $v_header['filename'])
                   2958:           $v_file_dir = '';
                   2959:         if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
                   2960:           $v_file_dir = '/';
                   2961: 
                   2962:         $p_list_detail[$v_nb++] = $v_header;
                   2963:         if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
                   2964:             return true;
                   2965:         }
                   2966:       }
                   2967:     }
                   2968: 
                   2969:         return true;
                   2970:     }
                   2971:     // }}}
                   2972: 
                   2973:     // {{{ _openAppend()
                   2974:     function _openAppend()
                   2975:     {
                   2976:         if (filesize($this->_tarname) == 0)
                   2977:           return $this->_openWrite();
                   2978: 
                   2979:         if ($this->_compress) {
                   2980:             $this->_close();
                   2981: 
                   2982:             if (!@rename($this->_tarname, $this->_tarname.".tmp")) {
                   2983:                 $this->_error('Error while renaming \''.$this->_tarname
                   2984:                                              .'\' to temporary file \''.$this->_tarname
                   2985:                                                          .'.tmp\'');
                   2986:                 return false;
                   2987:             }
                   2988: 
                   2989:             if ($this->_compress_type == 'gz')
                   2990:                 $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
                   2991:             elseif ($this->_compress_type == 'bz2')
                   2992:                 $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
                   2993: 
                   2994:             if ($v_temp_tar == 0) {
                   2995:                 $this->_error('Unable to open file \''.$this->_tarname
                   2996:                                              .'.tmp\' in binary read mode');
                   2997:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   2998:                 return false;
                   2999:             }
                   3000: 
                   3001:             if (!$this->_openWrite()) {
                   3002:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   3003:                 return false;
                   3004:             }
                   3005: 
                   3006:             if ($this->_compress_type == 'gz') {
                   3007:                 while (!@gzeof($v_temp_tar)) {
                   3008:                     $v_buffer = @gzread($v_temp_tar, 512);
                   3009:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
                   3010:                         // do not copy end blocks, we will re-make them
                   3011:                         // after appending
                   3012:                         continue;
                   3013:                     }
                   3014:                     $v_binary_data = pack("a512", $v_buffer);
                   3015:                     $this->_writeBlock($v_binary_data);
                   3016:                 }
                   3017: 
                   3018:                 @gzclose($v_temp_tar);
                   3019:             }
                   3020:             elseif ($this->_compress_type == 'bz2') {
                   3021:                 while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
                   3022:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
                   3023:                         continue;
                   3024:                     }
                   3025:                     $v_binary_data = pack("a512", $v_buffer);
                   3026:                     $this->_writeBlock($v_binary_data);
                   3027:                 }
                   3028: 
                   3029:                 @bzclose($v_temp_tar);
                   3030:             }
                   3031: 
                   3032:             if (!@unlink($this->_tarname.".tmp")) {
                   3033:                 $this->_error('Error while deleting temporary file \''
                   3034:                                              .$this->_tarname.'.tmp\'');
                   3035:             }
                   3036: 
                   3037:         } else {
                   3038:             // ----- For not compressed tar, just add files before the last
                   3039:                        //       one or two 512 bytes block
                   3040:             if (!$this->_openReadWrite())
                   3041:                return false;
                   3042: 
                   3043:             clearstatcache();
                   3044:             $v_size = filesize($this->_tarname);
                   3045: 
                   3046:             // We might have zero, one or two end blocks.
                   3047:             // The standard is two, but we should try to handle
                   3048:             // other cases.
                   3049:             fseek($this->_file, $v_size - 1024);
                   3050:             if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   3051:                 fseek($this->_file, $v_size - 1024);
                   3052:             }
                   3053:             elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   3054:                 fseek($this->_file, $v_size - 512);
                   3055:             }
                   3056:         }
                   3057: 
                   3058:         return true;
                   3059:     }
                   3060:     // }}}
                   3061: 
                   3062:     // {{{ _append()
                   3063:     function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
                   3064:     {
                   3065:         if (!$this->_openAppend())
                   3066:             return false;
                   3067: 
                   3068:         if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
                   3069:            $this->_writeFooter();
                   3070: 
                   3071:         $this->_close();
                   3072: 
                   3073:         return true;
                   3074:     }
                   3075:     // }}}
                   3076: 
                   3077:     // {{{ _dirCheck()
                   3078: 
                   3079:     /**
                   3080:      * Check if a directory exists and create it (including parent
                   3081:      * dirs) if not.
                   3082:      *
                   3083:      * @param string $p_dir directory to check
                   3084:      *
                   3085:      * @return bool true if the directory exists or was created
                   3086:      */
                   3087:     function _dirCheck($p_dir)
                   3088:     {
                   3089:         clearstatcache();
                   3090:         if ((@is_dir($p_dir)) || ($p_dir == ''))
                   3091:             return true;
                   3092: 
                   3093:         $p_parent_dir = dirname($p_dir);
                   3094: 
                   3095:         if (($p_parent_dir != $p_dir) &&
                   3096:             ($p_parent_dir != '') &&
                   3097:             (!$this->_dirCheck($p_parent_dir)))
                   3098:              return false;
                   3099: 
                   3100:         if (!@mkdir($p_dir, 0777)) {
                   3101:             $this->_error("Unable to create directory '$p_dir'");
                   3102:             return false;
                   3103:         }
                   3104: 
                   3105:         return true;
                   3106:     }
                   3107: 
                   3108:     // }}}
                   3109: 
                   3110:     // {{{ _pathReduction()
                   3111: 
                   3112:     /**
                   3113:      * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
                   3114:      * rand emove double slashes.
                   3115:      *
                   3116:      * @param string $p_dir path to reduce
                   3117:      *
                   3118:      * @return string reduced path
                   3119:      *
                   3120:      * @access private
                   3121:      *
                   3122:      */
                   3123:     function _pathReduction($p_dir)
                   3124:     {
                   3125:         $v_result = '';
                   3126: 
                   3127:         // ----- Look for not empty path
                   3128:         if ($p_dir != '') {
                   3129:             // ----- Explode path by directory names
                   3130:             $v_list = explode('/', $p_dir);
                   3131: 
                   3132:             // ----- Study directories from last to first
                   3133:             for ($i=sizeof($v_list)-1; $i>=0; $i--) {
                   3134:                 // ----- Look for current path
                   3135:                 if ($v_list[$i] == ".") {
                   3136:                     // ----- Ignore this directory
                   3137:                     // Should be the first $i=0, but no check is done
                   3138:                 }
                   3139:                 else if ($v_list[$i] == "..") {
                   3140:                     // ----- Ignore it and ignore the $i-1
                   3141:                     $i--;
                   3142:                 }
                   3143:                 else if (   ($v_list[$i] == '')
                   3144:                                         && ($i!=(sizeof($v_list)-1))
                   3145:                                                 && ($i!=0)) {
                   3146:                     // ----- Ignore only the double '//' in path,
                   3147:                     // but not the first and last /
                   3148:                 } else {
                   3149:                     $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
                   3150:                                                    .$v_result:'');
                   3151:                 }
                   3152:             }
                   3153:         }
                   3154:         $v_result = strtr($v_result, '\\', '/');
                   3155:         return $v_result;
                   3156:     }
                   3157: 
                   3158:     // }}}
                   3159: 
                   3160:     // {{{ _translateWinPath()
                   3161:     function _translateWinPath($p_path, $p_remove_disk_letter=true)
                   3162:     {
                   3163:       if (defined('OS_WINDOWS') && OS_WINDOWS) {
                   3164:           // ----- Look for potential disk letter
                   3165:           if (   ($p_remove_disk_letter)
                   3166:                      && (($v_position = strpos($p_path, ':')) != false)) {
                   3167:               $p_path = substr($p_path, $v_position+1);
                   3168:           }
                   3169:           // ----- Change potential windows directory separator
                   3170:           if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
                   3171:               $p_path = strtr($p_path, '\\', '/');
                   3172:           }
                   3173:       }
                   3174:       return $p_path;
                   3175:     }
                   3176:     // }}}
                   3177: 
                   3178: }
                   3179: ?>
                   3180: package.xml100644   1750   1750       20777      100644   6312 <?xml version="1.0" encoding="UTF-8"?>
                   3181: <package packagerversion="1.9.0" 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">
                   3182:  <name>Archive_Tar</name>
                   3183:  <channel>pear.php.net</channel>
                   3184:  <summary>Tar file management class</summary>
                   3185:  <description>This class provides handling of tar files in PHP.
                   3186: It supports creating, listing, extracting and adding to tar files.
                   3187: Gzip support is available if PHP has the zlib extension built-in or
                   3188: loaded. Bz2 compression is also supported with the bz2 extension loaded.</description>
                   3189:  <lead>
                   3190:   <name>Vincent Blavet</name>
                   3191:   <user>vblavet</user>
                   3192:   <email>vincent@phpconcept.net</email>
                   3193:   <active>no</active>
                   3194:  </lead>
                   3195:  <lead>
                   3196:   <name>Greg Beaver</name>
                   3197:   <user>cellog</user>
                   3198:   <email>greg@chiaraquartet.net</email>
                   3199:   <active>no</active>
                   3200:  </lead>
                   3201:  <lead>
                   3202:   <name>Michiel Rook</name>
                   3203:   <user>mrook</user>
                   3204:   <email>mrook@php.net</email>
                   3205:   <active>yes</active>
                   3206:  </lead>
                   3207:  <helper>
                   3208:   <name>Stig Bakken</name>
                   3209:   <user>ssb</user>
                   3210:   <email>stig@php.net</email>
                   3211:   <active>no</active>
                   3212:  </helper>
                   3213:  <date>2010-04-26</date>
                   3214:  <time>09:22:35</time>
                   3215:  <version>
                   3216:   <release>1.3.7</release>
                   3217:   <api>1.3.1</api>
                   3218:  </version>
                   3219:  <stability>
                   3220:   <release>stable</release>
                   3221:   <api>stable</api>
                   3222:  </stability>
                   3223:  <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3224:  <notes>
                   3225: PEAR compatibility update
                   3226:  </notes>
                   3227:  <contents>
                   3228:   <dir name="/">
                   3229:    <file baseinstalldir="/" md5sum="7406d6ed69f7c24506c93e02b0cdf839" name="Archive/Tar.php" role="php" />
                   3230:    <file baseinstalldir="/" md5sum="29b03715377b18b1fafcff98a99cc9a7" name="docs/Archive_Tar.txt" role="doc" />
                   3231:   </dir>
                   3232:  </contents>
                   3233:  <compatible>
                   3234:   <name>PEAR</name>
                   3235:   <channel>pear.php.net</channel>
                   3236:   <min>1.8.0</min>
                   3237:   <max>1.9.10</max>
                   3238:  </compatible>
                   3239:  <dependencies>
                   3240:   <required>
                   3241:    <php>
                   3242:     <min>4.3.0</min>
                   3243:    </php>
                   3244:    <pearinstaller>
                   3245:     <min>1.5.4</min>
                   3246:    </pearinstaller>
                   3247:   </required>
                   3248:  </dependencies>
                   3249:  <phprelease />
                   3250:  <changelog>
                   3251:   <release>
                   3252:    <version>
                   3253:     <release>1.3.6</release>
                   3254:     <api>1.3.1</api>
                   3255:    </version>
                   3256:    <stability>
                   3257:     <release>stable</release>
                   3258:     <api>stable</api>
                   3259:    </stability>
                   3260:    <date>2010-03-09</date>
                   3261:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3262:    <notes>
                   3263: * Fix Bug #16963: extractList can&apos;t extract zipped files from big tar [mrook]
                   3264:  * Implement Feature #4013: Ignoring files and directories on creating an archive. [mrook]
                   3265:    </notes>
                   3266:   </release>
                   3267:   <release>
                   3268:    <version>
                   3269:     <release>1.3.5</release>
                   3270:     <api>1.3.1</api>
                   3271:    </version>
                   3272:    <stability>
                   3273:     <release>stable</release>
                   3274:     <api>stable</api>
                   3275:    </stability>
                   3276:    <date>2009-12-31</date>
                   3277:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3278:    <notes>
                   3279: * Fix Bug #16958: Update &apos;compatible&apos; tag in package.xml [mrook]
                   3280:    </notes>
                   3281:   </release>
                   3282:   <release>
                   3283:    <version>
                   3284:     <release>1.3.4</release>
                   3285:     <api>1.3.1</api>
                   3286:    </version>
                   3287:    <stability>
                   3288:     <release>stable</release>
                   3289:     <api>stable</api>
                   3290:    </stability>
                   3291:    <date>2009-12-30</date>
                   3292:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3293:    <notes>
                   3294: * Fix Bug #11871: wrong result of ::listContent() if filename begins or ends with space [mrook]
                   3295:  * Fix Bug #12462: invalid tar magic [mrook]
                   3296:  * Fix Bug #13918: Long filenames may get up to 511 0x00 bytes appended on read [mrook]
                   3297:  * Fix Bug #16202: Bogus modification times [mrook]
                   3298:  * Implement Feature #16212: Die is not exception [mrook]
                   3299:    </notes>
                   3300:   </release>
                   3301:   <release>
                   3302:    <version>
                   3303:     <release>1.3.3</release>
                   3304:     <api>1.3.1</api>
                   3305:    </version>
                   3306:    <stability>
                   3307:     <release>stable</release>
                   3308:     <api>stable</api>
                   3309:    </stability>
                   3310:    <date>2009-03-27</date>
                   3311:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3312:    <notes>
                   3313: Change the license to New BSD license
                   3314: 
                   3315:    minor bugfix release
                   3316:    * fix Bug #9921 compression with bzip2 fails [cellog]
                   3317:    * fix Bug #11594 _readLongHeader leaves 0 bytes in filename [jamessas]
                   3318:    * fix Bug #11769 Incorrect symlink handing [fajar99]
                   3319:    </notes>
                   3320:   </release>
                   3321:   <release>
                   3322:    <version>
                   3323:     <release>1.3.2</release>
                   3324:     <api>1.3.1</api>
                   3325:    </version>
                   3326:    <stability>
                   3327:     <release>stable</release>
                   3328:     <api>stable</api>
                   3329:    </stability>
                   3330:    <date>2007-01-03</date>
                   3331:    <license uri="http://www.php.net/license">PHP License</license>
                   3332:    <notes>
                   3333: Correct Bug #4016
                   3334: Remove duplicate remove error display with &apos;@&apos;
                   3335: Correct Bug #3909 : Check existence of OS_WINDOWS constant
                   3336: Correct Bug #5452 fix for &quot;lone zero block&quot; when untarring packages
                   3337: Change filemode (from pear-core/Archive/Tar.php v.1.21)
                   3338: Correct Bug #6486 Can not extract symlinks
                   3339: Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal
                   3340: Correct Bug #8114 Files added on-the-fly not storing date
                   3341: Correct Bug #9352 Bug on _dirCheck function over nfs path
                   3342:    </notes>
                   3343:   </release>
                   3344:   <release>
                   3345:    <version>
                   3346:     <release>1.3.1</release>
                   3347:     <api>1.3.1</api>
                   3348:    </version>
                   3349:    <stability>
                   3350:     <release>stable</release>
                   3351:     <api>stable</api>
                   3352:    </stability>
                   3353:    <date>2005-03-17</date>
                   3354:    <license uri="http://www.php.net/license">PHP License</license>
                   3355:    <notes>
                   3356: Correct Bug #3855
                   3357:    </notes>
                   3358:   </release>
                   3359:   <release>
                   3360:    <version>
                   3361:     <release>1.3.0</release>
                   3362:     <api>1.3.0</api>
                   3363:    </version>
                   3364:    <stability>
                   3365:     <release>stable</release>
                   3366:     <api>stable</api>
                   3367:    </stability>
                   3368:    <date>2005-03-06</date>
                   3369:    <license uri="http://www.php.net/license">PHP License</license>
                   3370:    <notes>
                   3371: Bugs correction (2475, 2488, 2135, 2176)
                   3372:    </notes>
                   3373:   </release>
                   3374:   <release>
                   3375:    <version>
                   3376:     <release>1.2</release>
                   3377:     <api>1.2</api>
                   3378:    </version>
                   3379:    <stability>
                   3380:     <release>stable</release>
                   3381:     <api>stable</api>
                   3382:    </stability>
                   3383:    <date>2004-05-08</date>
                   3384:    <license uri="http://www.php.net/license">PHP License</license>
                   3385:    <notes>
                   3386: Add support for other separator than the space char and bug
                   3387:        correction
                   3388:    </notes>
                   3389:   </release>
                   3390:   <release>
                   3391:    <version>
                   3392:     <release>1.1</release>
                   3393:     <api>1.1</api>
                   3394:    </version>
                   3395:    <stability>
                   3396:     <release>stable</release>
                   3397:     <api>stable</api>
                   3398:    </stability>
                   3399:    <date>2003-05-28</date>
                   3400:    <license uri="http://www.php.net/license">PHP License</license>
                   3401:    <notes>
                   3402: * Add support for BZ2 compression
                   3403: * Add support for add and extract without using temporary files : methods addString() and extractInString()
                   3404:    </notes>
                   3405:   </release>
                   3406:   <release>
                   3407:    <version>
                   3408:     <release>1.0</release>
                   3409:     <api>1.0</api>
                   3410:    </version>
                   3411:    <stability>
                   3412:     <release>stable</release>
                   3413:     <api>stable</api>
                   3414:    </stability>
                   3415:    <date>2003-01-24</date>
                   3416:    <license uri="http://www.php.net/license">PHP License</license>
                   3417:    <notes>
                   3418: Change status to stable
                   3419:    </notes>
                   3420:   </release>
                   3421:   <release>
                   3422:    <version>
                   3423:     <release>0.10-b1</release>
                   3424:     <api>0.10-b1</api>
                   3425:    </version>
                   3426:    <stability>
                   3427:     <release>beta</release>
                   3428:     <api>beta</api>
                   3429:    </stability>
                   3430:    <date>2003-01-08</date>
                   3431:    <license uri="http://www.php.net/license">PHP License</license>
                   3432:    <notes>
                   3433: Add support for long filenames (greater than 99 characters)
                   3434:    </notes>
                   3435:   </release>
                   3436:   <release>
                   3437:    <version>
                   3438:     <release>0.9</release>
                   3439:     <api>0.9</api>
                   3440:    </version>
                   3441:    <stability>
                   3442:     <release>stable</release>
                   3443:     <api>stable</api>
                   3444:    </stability>
                   3445:    <date>2002-05-27</date>
                   3446:    <license uri="http://www.php.net/license">PHP License</license>
                   3447:    <notes>
                   3448: Auto-detect gzip&apos;ed files
                   3449:    </notes>
                   3450:   </release>
                   3451:   <release>
                   3452:    <version>
                   3453:     <release>0.4</release>
                   3454:     <api>0.4</api>
                   3455:    </version>
                   3456:    <stability>
                   3457:     <release>stable</release>
                   3458:     <api>stable</api>
                   3459:    </stability>
                   3460:    <date>2002-05-20</date>
                   3461:    <license uri="http://www.php.net/license">PHP License</license>
                   3462:    <notes>
                   3463: Windows bugfix: use forward slashes inside archives
                   3464:    </notes>
                   3465:   </release>
                   3466:   <release>
                   3467:    <version>
                   3468:     <release>0.2</release>
                   3469:     <api>0.2</api>
                   3470:    </version>
                   3471:    <stability>
                   3472:     <release>stable</release>
                   3473:     <api>stable</api>
                   3474:    </stability>
                   3475:    <date>2002-02-18</date>
                   3476:    <license uri="http://www.php.net/license">PHP License</license>
                   3477:    <notes>
                   3478: From initial commit to stable
                   3479:    </notes>
                   3480:   </release>
                   3481:   <release>
                   3482:    <version>
                   3483:     <release>0.3</release>
                   3484:     <api>0.3</api>
                   3485:    </version>
                   3486:    <stability>
                   3487:     <release>stable</release>
                   3488:     <api>stable</api>
                   3489:    </stability>
                   3490:    <date>2002-04-13</date>
                   3491:    <license uri="http://www.php.net/license">PHP License</license>
                   3492:    <notes>
                   3493: Windows bugfix: used wrong directory separators
                   3494:    </notes>
                   3495:   </release>
                   3496:  </changelog>
                   3497: </package>
                   3498: Archive_Tar-1.3.7/Archive/Tar.php100644   1750   1750      175514      100644  11670 <?php
                   3499: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   3500: 
                   3501: /**
                   3502:  * File::CSV
                   3503:  *
                   3504:  * PHP versions 4 and 5
                   3505:  *
                   3506:  * Copyright (c) 1997-2008,
                   3507:  * Vincent Blavet <vincent@phpconcept.net>
                   3508:  * All rights reserved.
                   3509:  *
                   3510:  * Redistribution and use in source and binary forms, with or without
                   3511:  * modification, are permitted provided that the following conditions are met:
                   3512:  *
                   3513:  *     * Redistributions of source code must retain the above copyright notice,
                   3514:  *       this list of conditions and the following disclaimer.
                   3515:  *     * Redistributions in binary form must reproduce the above copyright
                   3516:  *       notice, this list of conditions and the following disclaimer in the
                   3517:  *       documentation and/or other materials provided with the distribution.
                   3518:  *
                   3519:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   3520:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   3521:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   3522:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   3523:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   3524:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   3525:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   3526:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   3527:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   3528:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   3529:  *
                   3530:  *
                   3531:  * @category    File_Formats
                   3532:  * @package     Archive_Tar
                   3533:  * @author      Vincent Blavet <vincent@phpconcept.net>
                   3534:  * @copyright   1997-2008 The Authors
                   3535:  * @license     http://www.opensource.org/licenses/bsd-license.php New BSD License
                   3536:  * @version     CVS: $Id: Tar.php 295988 2010-03-09 08:39:37Z mrook $
                   3537:  * @link        http://pear.php.net/package/Archive_Tar
                   3538:  */
                   3539: 
                   3540: require_once 'PEAR.php';
                   3541: 
                   3542: 
                   3543: define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
                   3544: define ('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
                   3545: 
                   3546: /**
                   3547: * Creates a (compressed) Tar archive
                   3548: *
                   3549: * @author   Vincent Blavet <vincent@phpconcept.net>
                   3550: * @version  $Revision: 295988 $
                   3551: * @license  http://www.opensource.org/licenses/bsd-license.php New BSD License
                   3552: * @package  Archive_Tar
                   3553: */
                   3554: class Archive_Tar extends PEAR
                   3555: {
                   3556:     /**
                   3557:     * @var string Name of the Tar
                   3558:     */
                   3559:     var $_tarname='';
                   3560: 
                   3561:     /**
                   3562:     * @var boolean if true, the Tar file will be gzipped
                   3563:     */
                   3564:     var $_compress=false;
                   3565: 
                   3566:     /**
                   3567:     * @var string Type of compression : 'none', 'gz' or 'bz2'
                   3568:     */
                   3569:     var $_compress_type='none';
                   3570: 
                   3571:     /**
                   3572:     * @var string Explode separator
                   3573:     */
                   3574:     var $_separator=' ';
                   3575: 
                   3576:     /**
                   3577:     * @var file descriptor
                   3578:     */
                   3579:     var $_file=0;
                   3580: 
                   3581:     /**
                   3582:     * @var string Local Tar name of a remote Tar (http:// or ftp://)
                   3583:     */
                   3584:     var $_temp_tarname='';
                   3585: 
                   3586:     /**
                   3587:     * @var string regular expression for ignoring files or directories
                   3588:     */
                   3589:     var $_ignore_regexp='';
                   3590: 
                   3591:     // {{{ constructor
                   3592:     /**
                   3593:     * Archive_Tar Class constructor. This flavour of the constructor only
                   3594:     * declare a new Archive_Tar object, identifying it by the name of the
                   3595:     * tar file.
                   3596:     * If the compress argument is set the tar will be read or created as a
                   3597:     * gzip or bz2 compressed TAR file.
                   3598:     *
                   3599:     * @param    string  $p_tarname  The name of the tar archive to create
                   3600:     * @param    string  $p_compress can be null, 'gz' or 'bz2'. This
                   3601:     *                   parameter indicates if gzip or bz2 compression
                   3602:     *                   is required.  For compatibility reason the
                   3603:     *                   boolean value 'true' means 'gz'.
                   3604:     * @access public
                   3605:     */
                   3606:     function Archive_Tar($p_tarname, $p_compress = null)
                   3607:     {
                   3608:         $this->PEAR();
                   3609:         $this->_compress = false;
                   3610:         $this->_compress_type = 'none';
                   3611:         if (($p_compress === null) || ($p_compress == '')) {
                   3612:             if (@file_exists($p_tarname)) {
                   3613:                 if ($fp = @fopen($p_tarname, "rb")) {
                   3614:                     // look for gzip magic cookie
                   3615:                     $data = fread($fp, 2);
                   3616:                     fclose($fp);
                   3617:                     if ($data == "\37\213") {
                   3618:                         $this->_compress = true;
                   3619:                         $this->_compress_type = 'gz';
                   3620:                     // No sure it's enought for a magic code ....
                   3621:                     } elseif ($data == "BZ") {
                   3622:                         $this->_compress = true;
                   3623:                         $this->_compress_type = 'bz2';
                   3624:                     }
                   3625:                 }
                   3626:             } else {
                   3627:                 // probably a remote file or some file accessible
                   3628:                 // through a stream interface
                   3629:                 if (substr($p_tarname, -2) == 'gz') {
                   3630:                     $this->_compress = true;
                   3631:                     $this->_compress_type = 'gz';
                   3632:                 } elseif ((substr($p_tarname, -3) == 'bz2') ||
                   3633:                           (substr($p_tarname, -2) == 'bz')) {
                   3634:                     $this->_compress = true;
                   3635:                     $this->_compress_type = 'bz2';
                   3636:                 }
                   3637:             }
                   3638:         } else {
                   3639:             if (($p_compress === true) || ($p_compress == 'gz')) {
                   3640:                 $this->_compress = true;
                   3641:                 $this->_compress_type = 'gz';
                   3642:             } else if ($p_compress == 'bz2') {
                   3643:                 $this->_compress = true;
                   3644:                 $this->_compress_type = 'bz2';
                   3645:             } else {
                   3646:                 $this->_error("Unsupported compression type '$p_compress'\n".
                   3647:                     "Supported types are 'gz' and 'bz2'.\n");
                   3648:                 return false;
                   3649:             }
                   3650:         }
                   3651:         $this->_tarname = $p_tarname;
                   3652:         if ($this->_compress) { // assert zlib or bz2 extension support
                   3653:             if ($this->_compress_type == 'gz')
                   3654:                 $extname = 'zlib';
                   3655:             else if ($this->_compress_type == 'bz2')
                   3656:                 $extname = 'bz2';
                   3657: 
                   3658:             if (!extension_loaded($extname)) {
                   3659:                 PEAR::loadExtension($extname);
                   3660:             }
                   3661:             if (!extension_loaded($extname)) {
                   3662:                 $this->_error("The extension '$extname' couldn't be found.\n".
                   3663:                     "Please make sure your version of PHP was built ".
                   3664:                     "with '$extname' support.\n");
                   3665:                 return false;
                   3666:             }
                   3667:         }
                   3668:     }
                   3669:     // }}}
                   3670: 
                   3671:     // {{{ destructor
                   3672:     function _Archive_Tar()
                   3673:     {
                   3674:         $this->_close();
                   3675:         // ----- Look for a local copy to delete
                   3676:         if ($this->_temp_tarname != '')
                   3677:             @unlink($this->_temp_tarname);
                   3678:         $this->_PEAR();
                   3679:     }
                   3680:     // }}}
                   3681: 
                   3682:     // {{{ create()
                   3683:     /**
                   3684:     * This method creates the archive file and add the files / directories
                   3685:     * that are listed in $p_filelist.
                   3686:     * If a file with the same name exist and is writable, it is replaced
                   3687:     * by the new tar.
                   3688:     * The method return false and a PEAR error text.
                   3689:     * The $p_filelist parameter can be an array of string, each string
                   3690:     * representing a filename or a directory name with their path if
                   3691:     * needed. It can also be a single string with names separated by a
                   3692:     * single blank.
                   3693:     * For each directory added in the archive, the files and
                   3694:     * sub-directories are also added.
                   3695:     * See also createModify() method for more details.
                   3696:     *
                   3697:     * @param array  $p_filelist An array of filenames and directory names, or a
                   3698:        *                           single string with names separated by a single
                   3699:        *                           blank space.
                   3700:     * @return                   true on success, false on error.
                   3701:     * @see createModify()
                   3702:     * @access public
                   3703:     */
                   3704:     function create($p_filelist)
                   3705:     {
                   3706:         return $this->createModify($p_filelist, '', '');
                   3707:     }
                   3708:     // }}}
                   3709: 
                   3710:     // {{{ add()
                   3711:     /**
                   3712:     * This method add the files / directories that are listed in $p_filelist in
                   3713:     * the archive. If the archive does not exist it is created.
                   3714:     * The method return false and a PEAR error text.
                   3715:     * The files and directories listed are only added at the end of the archive,
                   3716:     * even if a file with the same name is already archived.
                   3717:     * See also createModify() method for more details.
                   3718:     *
                   3719:     * @param array  $p_filelist An array of filenames and directory names, or a
                   3720:        *                           single string with names separated by a single
                   3721:        *                           blank space.
                   3722:     * @return                   true on success, false on error.
                   3723:     * @see createModify()
                   3724:     * @access public
                   3725:     */
                   3726:     function add($p_filelist)
                   3727:     {
                   3728:         return $this->addModify($p_filelist, '', '');
                   3729:     }
                   3730:     // }}}
                   3731: 
                   3732:     // {{{ extract()
                   3733:     function extract($p_path='')
                   3734:     {
                   3735:         return $this->extractModify($p_path, '');
                   3736:     }
                   3737:     // }}}
                   3738: 
                   3739:     // {{{ listContent()
                   3740:     function listContent()
                   3741:     {
                   3742:         $v_list_detail = array();
                   3743: 
                   3744:         if ($this->_openRead()) {
                   3745:             if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                   3746:                 unset($v_list_detail);
                   3747:                 $v_list_detail = 0;
                   3748:             }
                   3749:             $this->_close();
                   3750:         }
                   3751: 
                   3752:         return $v_list_detail;
                   3753:     }
                   3754:     // }}}
                   3755: 
                   3756:     // {{{ createModify()
                   3757:     /**
                   3758:     * This method creates the archive file and add the files / directories
                   3759:     * that are listed in $p_filelist.
                   3760:     * If the file already exists and is writable, it is replaced by the
                   3761:     * new tar. It is a create and not an add. If the file exists and is
                   3762:     * read-only or is a directory it is not replaced. The method return
                   3763:     * false and a PEAR error text.
                   3764:     * The $p_filelist parameter can be an array of string, each string
                   3765:     * representing a filename or a directory name with their path if
                   3766:     * needed. It can also be a single string with names separated by a
                   3767:     * single blank.
                   3768:     * The path indicated in $p_remove_dir will be removed from the
                   3769:     * memorized path of each file / directory listed when this path
                   3770:     * exists. By default nothing is removed (empty path '')
                   3771:     * The path indicated in $p_add_dir will be added at the beginning of
                   3772:     * the memorized path of each file / directory listed. However it can
                   3773:     * be set to empty ''. The adding of a path is done after the removing
                   3774:     * of path.
                   3775:     * The path add/remove ability enables the user to prepare an archive
                   3776:     * for extraction in a different path than the origin files are.
                   3777:     * See also addModify() method for file adding properties.
                   3778:     *
                   3779:     * @param array  $p_filelist     An array of filenames and directory names,
                   3780:        *                               or a single string with names separated by
                   3781:        *                               a single blank space.
                   3782:     * @param string $p_add_dir      A string which contains a path to be added
                   3783:        *                               to the memorized path of each element in
                   3784:        *                               the list.
                   3785:     * @param string $p_remove_dir   A string which contains a path to be
                   3786:        *                               removed from the memorized path of each
                   3787:        *                               element in the list, when relevant.
                   3788:     * @return boolean               true on success, false on error.
                   3789:     * @access public
                   3790:     * @see addModify()
                   3791:     */
                   3792:     function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   3793:     {
                   3794:         $v_result = true;
                   3795: 
                   3796:         if (!$this->_openWrite())
                   3797:             return false;
                   3798: 
                   3799:         if ($p_filelist != '') {
                   3800:             if (is_array($p_filelist))
                   3801:                 $v_list = $p_filelist;
                   3802:             elseif (is_string($p_filelist))
                   3803:                 $v_list = explode($this->_separator, $p_filelist);
                   3804:             else {
                   3805:                 $this->_cleanFile();
                   3806:                 $this->_error('Invalid file list');
                   3807:                 return false;
                   3808:             }
                   3809: 
                   3810:             $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
                   3811:         }
                   3812: 
                   3813:         if ($v_result) {
                   3814:             $this->_writeFooter();
                   3815:             $this->_close();
                   3816:         } else
                   3817:             $this->_cleanFile();
                   3818: 
                   3819:         return $v_result;
                   3820:     }
                   3821:     // }}}
                   3822: 
                   3823:     // {{{ addModify()
                   3824:     /**
                   3825:     * This method add the files / directories listed in $p_filelist at the
                   3826:     * end of the existing archive. If the archive does not yet exists it
                   3827:     * is created.
                   3828:     * The $p_filelist parameter can be an array of string, each string
                   3829:     * representing a filename or a directory name with their path if
                   3830:     * needed. It can also be a single string with names separated by a
                   3831:     * single blank.
                   3832:     * The path indicated in $p_remove_dir will be removed from the
                   3833:     * memorized path of each file / directory listed when this path
                   3834:     * exists. By default nothing is removed (empty path '')
                   3835:     * The path indicated in $p_add_dir will be added at the beginning of
                   3836:     * the memorized path of each file / directory listed. However it can
                   3837:     * be set to empty ''. The adding of a path is done after the removing
                   3838:     * of path.
                   3839:     * The path add/remove ability enables the user to prepare an archive
                   3840:     * for extraction in a different path than the origin files are.
                   3841:     * If a file/dir is already in the archive it will only be added at the
                   3842:     * end of the archive. There is no update of the existing archived
                   3843:     * file/dir. However while extracting the archive, the last file will
                   3844:     * replace the first one. This results in a none optimization of the
                   3845:     * archive size.
                   3846:     * If a file/dir does not exist the file/dir is ignored. However an
                   3847:     * error text is send to PEAR error.
                   3848:     * If a file/dir is not readable the file/dir is ignored. However an
                   3849:     * error text is send to PEAR error.
                   3850:     *
                   3851:     * @param array      $p_filelist     An array of filenames and directory
                   3852:        *                                   names, or a single string with names
                   3853:        *                                   separated by a single blank space.
                   3854:     * @param string     $p_add_dir      A string which contains a path to be
                   3855:        *                                   added to the memorized path of each
                   3856:        *                                   element in the list.
                   3857:     * @param string     $p_remove_dir   A string which contains a path to be
                   3858:        *                                   removed from the memorized path of
                   3859:        *                                   each element in the list, when
                   3860:     *                                   relevant.
                   3861:     * @return                           true on success, false on error.
                   3862:     * @access public
                   3863:     */
                   3864:     function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   3865:     {
                   3866:         $v_result = true;
                   3867: 
                   3868:         if (!$this->_isArchive())
                   3869:             $v_result = $this->createModify($p_filelist, $p_add_dir,
                   3870:                                                        $p_remove_dir);
                   3871:         else {
                   3872:             if (is_array($p_filelist))
                   3873:                 $v_list = $p_filelist;
                   3874:             elseif (is_string($p_filelist))
                   3875:                 $v_list = explode($this->_separator, $p_filelist);
                   3876:             else {
                   3877:                 $this->_error('Invalid file list');
                   3878:                 return false;
                   3879:             }
                   3880: 
                   3881:             $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
                   3882:         }
                   3883: 
                   3884:         return $v_result;
                   3885:     }
                   3886:     // }}}
                   3887: 
                   3888:     // {{{ addString()
                   3889:     /**
                   3890:     * This method add a single string as a file at the
                   3891:     * end of the existing archive. If the archive does not yet exists it
                   3892:     * is created.
                   3893:     *
                   3894:     * @param string     $p_filename     A string which contains the full
                   3895:        *                                   filename path that will be associated
                   3896:        *                                   with the string.
                   3897:     * @param string     $p_string       The content of the file added in
                   3898:        *                                   the archive.
                   3899:     * @return                           true on success, false on error.
                   3900:     * @access public
                   3901:     */
                   3902:     function addString($p_filename, $p_string)
                   3903:     {
                   3904:         $v_result = true;
                   3905: 
                   3906:         if (!$this->_isArchive()) {
                   3907:             if (!$this->_openWrite()) {
                   3908:                 return false;
                   3909:             }
                   3910:             $this->_close();
                   3911:         }
                   3912: 
                   3913:         if (!$this->_openAppend())
                   3914:             return false;
                   3915: 
                   3916:         // Need to check the get back to the temporary file ? ....
                   3917:         $v_result = $this->_addString($p_filename, $p_string);
                   3918: 
                   3919:         $this->_writeFooter();
                   3920: 
                   3921:         $this->_close();
                   3922: 
                   3923:         return $v_result;
                   3924:     }
                   3925:     // }}}
                   3926: 
                   3927:     // {{{ extractModify()
                   3928:     /**
                   3929:     * This method extract all the content of the archive in the directory
                   3930:     * indicated by $p_path. When relevant the memorized path of the
                   3931:     * files/dir can be modified by removing the $p_remove_path path at the
                   3932:     * beginning of the file/dir path.
                   3933:     * While extracting a file, if the directory path does not exists it is
                   3934:     * created.
                   3935:     * While extracting a file, if the file already exists it is replaced
                   3936:     * without looking for last modification date.
                   3937:     * While extracting a file, if the file already exists and is write
                   3938:     * protected, the extraction is aborted.
                   3939:     * While extracting a file, if a directory with the same name already
                   3940:     * exists, the extraction is aborted.
                   3941:     * While extracting a directory, if a file with the same name already
                   3942:     * exists, the extraction is aborted.
                   3943:     * While extracting a file/directory if the destination directory exist
                   3944:     * and is write protected, or does not exist but can not be created,
                   3945:     * the extraction is aborted.
                   3946:     * If after extraction an extracted file does not show the correct
                   3947:     * stored file size, the extraction is aborted.
                   3948:     * When the extraction is aborted, a PEAR error text is set and false
                   3949:     * is returned. However the result can be a partial extraction that may
                   3950:     * need to be manually cleaned.
                   3951:     *
                   3952:     * @param string $p_path         The path of the directory where the
                   3953:        *                               files/dir need to by extracted.
                   3954:     * @param string $p_remove_path  Part of the memorized path that can be
                   3955:        *                               removed if present at the beginning of
                   3956:        *                               the file/dir path.
                   3957:     * @return boolean               true on success, false on error.
                   3958:     * @access public
                   3959:     * @see extractList()
                   3960:     */
                   3961:     function extractModify($p_path, $p_remove_path)
                   3962:     {
                   3963:         $v_result = true;
                   3964:         $v_list_detail = array();
                   3965: 
                   3966:         if ($v_result = $this->_openRead()) {
                   3967:             $v_result = $this->_extractList($p_path, $v_list_detail,
                   3968:                                                        "complete", 0, $p_remove_path);
                   3969:             $this->_close();
                   3970:         }
                   3971: 
                   3972:         return $v_result;
                   3973:     }
                   3974:     // }}}
                   3975: 
                   3976:     // {{{ extractInString()
                   3977:     /**
                   3978:     * This method extract from the archive one file identified by $p_filename.
                   3979:     * The return value is a string with the file content, or NULL on error.
                   3980:     * @param string $p_filename     The path of the file to extract in a string.
                   3981:     * @return                       a string with the file content or NULL.
                   3982:     * @access public
                   3983:     */
                   3984:     function extractInString($p_filename)
                   3985:     {
                   3986:         if ($this->_openRead()) {
                   3987:             $v_result = $this->_extractInString($p_filename);
                   3988:             $this->_close();
                   3989:         } else {
                   3990:             $v_result = NULL;
                   3991:         }
                   3992: 
                   3993:         return $v_result;
                   3994:     }
                   3995:     // }}}
                   3996: 
                   3997:     // {{{ extractList()
                   3998:     /**
                   3999:     * This method extract from the archive only the files indicated in the
                   4000:     * $p_filelist. These files are extracted in the current directory or
                   4001:     * in the directory indicated by the optional $p_path parameter.
                   4002:     * If indicated the $p_remove_path can be used in the same way as it is
                   4003:     * used in extractModify() method.
                   4004:     * @param array  $p_filelist     An array of filenames and directory names,
                   4005:        *                               or a single string with names separated
                   4006:        *                               by a single blank space.
                   4007:     * @param string $p_path         The path of the directory where the
                   4008:        *                               files/dir need to by extracted.
                   4009:     * @param string $p_remove_path  Part of the memorized path that can be
                   4010:        *                               removed if present at the beginning of
                   4011:        *                               the file/dir path.
                   4012:     * @return                       true on success, false on error.
                   4013:     * @access public
                   4014:     * @see extractModify()
                   4015:     */
                   4016:     function extractList($p_filelist, $p_path='', $p_remove_path='')
                   4017:     {
                   4018:         $v_result = true;
                   4019:         $v_list_detail = array();
                   4020: 
                   4021:         if (is_array($p_filelist))
                   4022:             $v_list = $p_filelist;
                   4023:         elseif (is_string($p_filelist))
                   4024:             $v_list = explode($this->_separator, $p_filelist);
                   4025:         else {
                   4026:             $this->_error('Invalid string list');
                   4027:             return false;
                   4028:         }
                   4029: 
                   4030:         if ($v_result = $this->_openRead()) {
                   4031:             $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
                   4032:                                                        $v_list, $p_remove_path);
                   4033:             $this->_close();
                   4034:         }
                   4035: 
                   4036:         return $v_result;
                   4037:     }
                   4038:     // }}}
                   4039: 
                   4040:     // {{{ setAttribute()
                   4041:     /**
                   4042:     * This method set specific attributes of the archive. It uses a variable
                   4043:     * list of parameters, in the format attribute code + attribute values :
                   4044:     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
                   4045:     * @param mixed $argv            variable list of attributes and values
                   4046:     * @return                       true on success, false on error.
                   4047:     * @access public
                   4048:     */
                   4049:     function setAttribute()
                   4050:     {
                   4051:         $v_result = true;
                   4052: 
                   4053:         // ----- Get the number of variable list of arguments
                   4054:         if (($v_size = func_num_args()) == 0) {
                   4055:             return true;
                   4056:         }
                   4057: 
                   4058:         // ----- Get the arguments
                   4059:         $v_att_list = &func_get_args();
                   4060: 
                   4061:         // ----- Read the attributes
                   4062:         $i=0;
                   4063:         while ($i<$v_size) {
                   4064: 
                   4065:             // ----- Look for next option
                   4066:             switch ($v_att_list[$i]) {
                   4067:                 // ----- Look for options that request a string value
                   4068:                 case ARCHIVE_TAR_ATT_SEPARATOR :
                   4069:                     // ----- Check the number of parameters
                   4070:                     if (($i+1) >= $v_size) {
                   4071:                         $this->_error('Invalid number of parameters for '
                   4072:                                                              .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
                   4073:                         return false;
                   4074:                     }
                   4075: 
                   4076:                     // ----- Get the value
                   4077:                     $this->_separator = $v_att_list[$i+1];
                   4078:                     $i++;
                   4079:                 break;
                   4080: 
                   4081:                 default :
                   4082:                     $this->_error('Unknow attribute code '.$v_att_list[$i].'');
                   4083:                     return false;
                   4084:             }
                   4085: 
                   4086:             // ----- Next attribute
                   4087:             $i++;
                   4088:         }
                   4089: 
                   4090:         return $v_result;
                   4091:     }
                   4092:     // }}}
                   4093: 
                   4094:     // {{{ setIgnoreRegexp()
                   4095:     /**
                   4096:     * This method sets the regular expression for ignoring files and directories
                   4097:     * at import, for example:
                   4098:     * $arch->setIgnoreRegexp("#CVS|\.svn#");
                   4099:     * @param string $regexp         regular expression defining which files or directories to ignore
                   4100:     * @access public
                   4101:     */
                   4102:     function setIgnoreRegexp($regexp)
                   4103:     {
                   4104:        $this->_ignore_regexp = $regexp;
                   4105:     }
                   4106:     // }}}
                   4107: 
                   4108:     // {{{ setIgnoreList()
                   4109:     /**
                   4110:     * This method sets the regular expression for ignoring all files and directories
                   4111:     * matching the filenames in the array list at import, for example:
                   4112:     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
                   4113:     * @param array $list         a list of file or directory names to ignore
                   4114:     * @access public
                   4115:     */
                   4116:     function setIgnoreList($list)
                   4117:     {
                   4118:        $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
                   4119:        $regexp = '#/'.join('$|/', $list).'#';
                   4120:        $this->setIgnoreRegexp($regexp);
                   4121:     }
                   4122:     // }}}
                   4123: 
                   4124:     // {{{ _error()
                   4125:     function _error($p_message)
                   4126:     {
                   4127:         // ----- To be completed
                   4128:         $this->raiseError($p_message);
                   4129:     }
                   4130:     // }}}
                   4131: 
                   4132:     // {{{ _warning()
                   4133:     function _warning($p_message)
                   4134:     {
                   4135:         // ----- To be completed
                   4136:         $this->raiseError($p_message);
                   4137:     }
                   4138:     // }}}
                   4139: 
                   4140:     // {{{ _isArchive()
                   4141:     function _isArchive($p_filename=NULL)
                   4142:     {
                   4143:         if ($p_filename == NULL) {
                   4144:             $p_filename = $this->_tarname;
                   4145:         }
                   4146:         clearstatcache();
                   4147:         return @is_file($p_filename) && !@is_link($p_filename);
                   4148:     }
                   4149:     // }}}
                   4150: 
                   4151:     // {{{ _openWrite()
                   4152:     function _openWrite()
                   4153:     {
                   4154:         if ($this->_compress_type == 'gz')
                   4155:             $this->_file = @gzopen($this->_tarname, "wb9");
                   4156:         else if ($this->_compress_type == 'bz2')
                   4157:             $this->_file = @bzopen($this->_tarname, "w");
                   4158:         else if ($this->_compress_type == 'none')
                   4159:             $this->_file = @fopen($this->_tarname, "wb");
                   4160:         else
                   4161:             $this->_error('Unknown or missing compression type ('
                   4162:                                      .$this->_compress_type.')');
                   4163: 
                   4164:         if ($this->_file == 0) {
                   4165:             $this->_error('Unable to open in write mode \''
                   4166:                                      .$this->_tarname.'\'');
                   4167:             return false;
                   4168:         }
                   4169: 
                   4170:         return true;
                   4171:     }
                   4172:     // }}}
                   4173: 
                   4174:     // {{{ _openRead()
                   4175:     function _openRead()
                   4176:     {
                   4177:         if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
                   4178: 
                   4179:           // ----- Look if a local copy need to be done
                   4180:           if ($this->_temp_tarname == '') {
                   4181:               $this->_temp_tarname = uniqid('tar').'.tmp';
                   4182:               if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
                   4183:                 $this->_error('Unable to open in read mode \''
                   4184:                                              .$this->_tarname.'\'');
                   4185:                 $this->_temp_tarname = '';
                   4186:                 return false;
                   4187:               }
                   4188:               if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
                   4189:                 $this->_error('Unable to open in write mode \''
                   4190:                                              .$this->_temp_tarname.'\'');
                   4191:                 $this->_temp_tarname = '';
                   4192:                 return false;
                   4193:               }
                   4194:               while ($v_data = @fread($v_file_from, 1024))
                   4195:                   @fwrite($v_file_to, $v_data);
                   4196:               @fclose($v_file_from);
                   4197:               @fclose($v_file_to);
                   4198:           }
                   4199: 
                   4200:           // ----- File to open if the local copy
                   4201:           $v_filename = $this->_temp_tarname;
                   4202: 
                   4203:         } else
                   4204:           // ----- File to open if the normal Tar file
                   4205:           $v_filename = $this->_tarname;
                   4206: 
                   4207:         if ($this->_compress_type == 'gz')
                   4208:             $this->_file = @gzopen($v_filename, "rb");
                   4209:         else if ($this->_compress_type == 'bz2')
                   4210:             $this->_file = @bzopen($v_filename, "r");
                   4211:         else if ($this->_compress_type == 'none')
                   4212:             $this->_file = @fopen($v_filename, "rb");
                   4213:         else
                   4214:             $this->_error('Unknown or missing compression type ('
                   4215:                                      .$this->_compress_type.')');
                   4216: 
                   4217:         if ($this->_file == 0) {
                   4218:             $this->_error('Unable to open in read mode \''.$v_filename.'\'');
                   4219:             return false;
                   4220:         }
                   4221: 
                   4222:         return true;
                   4223:     }
                   4224:     // }}}
                   4225: 
                   4226:     // {{{ _openReadWrite()
                   4227:     function _openReadWrite()
                   4228:     {
                   4229:         if ($this->_compress_type == 'gz')
                   4230:             $this->_file = @gzopen($this->_tarname, "r+b");
                   4231:         else if ($this->_compress_type == 'bz2') {
                   4232:             $this->_error('Unable to open bz2 in read/write mode \''
                   4233:                                      .$this->_tarname.'\' (limitation of bz2 extension)');
                   4234:             return false;
                   4235:         } else if ($this->_compress_type == 'none')
                   4236:             $this->_file = @fopen($this->_tarname, "r+b");
                   4237:         else
                   4238:             $this->_error('Unknown or missing compression type ('
                   4239:                                      .$this->_compress_type.')');
                   4240: 
                   4241:         if ($this->_file == 0) {
                   4242:             $this->_error('Unable to open in read/write mode \''
                   4243:                                      .$this->_tarname.'\'');
                   4244:             return false;
                   4245:         }
                   4246: 
                   4247:         return true;
                   4248:     }
                   4249:     // }}}
                   4250: 
                   4251:     // {{{ _close()
                   4252:     function _close()
                   4253:     {
                   4254:         //if (isset($this->_file)) {
                   4255:         if (is_resource($this->_file)) {
                   4256:             if ($this->_compress_type == 'gz')
                   4257:                 @gzclose($this->_file);
                   4258:             else if ($this->_compress_type == 'bz2')
                   4259:                 @bzclose($this->_file);
                   4260:             else if ($this->_compress_type == 'none')
                   4261:                 @fclose($this->_file);
                   4262:             else
                   4263:                 $this->_error('Unknown or missing compression type ('
                   4264:                                              .$this->_compress_type.')');
                   4265: 
                   4266:             $this->_file = 0;
                   4267:         }
                   4268: 
                   4269:         // ----- Look if a local copy need to be erase
                   4270:         // Note that it might be interesting to keep the url for a time : ToDo
                   4271:         if ($this->_temp_tarname != '') {
                   4272:             @unlink($this->_temp_tarname);
                   4273:             $this->_temp_tarname = '';
                   4274:         }
                   4275: 
                   4276:         return true;
                   4277:     }
                   4278:     // }}}
                   4279: 
                   4280:     // {{{ _cleanFile()
                   4281:     function _cleanFile()
                   4282:     {
                   4283:         $this->_close();
                   4284: 
                   4285:         // ----- Look for a local copy
                   4286:         if ($this->_temp_tarname != '') {
                   4287:             // ----- Remove the local copy but not the remote tarname
                   4288:             @unlink($this->_temp_tarname);
                   4289:             $this->_temp_tarname = '';
                   4290:         } else {
                   4291:             // ----- Remove the local tarname file
                   4292:             @unlink($this->_tarname);
                   4293:         }
                   4294:         $this->_tarname = '';
                   4295: 
                   4296:         return true;
                   4297:     }
                   4298:     // }}}
                   4299: 
                   4300:     // {{{ _writeBlock()
                   4301:     function _writeBlock($p_binary_data, $p_len=null)
                   4302:     {
                   4303:       if (is_resource($this->_file)) {
                   4304:           if ($p_len === null) {
                   4305:               if ($this->_compress_type == 'gz')
                   4306:                   @gzputs($this->_file, $p_binary_data);
                   4307:               else if ($this->_compress_type == 'bz2')
                   4308:                   @bzwrite($this->_file, $p_binary_data);
                   4309:               else if ($this->_compress_type == 'none')
                   4310:                   @fputs($this->_file, $p_binary_data);
                   4311:               else
                   4312:                   $this->_error('Unknown or missing compression type ('
                   4313:                                                .$this->_compress_type.')');
                   4314:           } else {
                   4315:               if ($this->_compress_type == 'gz')
                   4316:                   @gzputs($this->_file, $p_binary_data, $p_len);
                   4317:               else if ($this->_compress_type == 'bz2')
                   4318:                   @bzwrite($this->_file, $p_binary_data, $p_len);
                   4319:               else if ($this->_compress_type == 'none')
                   4320:                   @fputs($this->_file, $p_binary_data, $p_len);
                   4321:               else
                   4322:                   $this->_error('Unknown or missing compression type ('
                   4323:                                                .$this->_compress_type.')');
                   4324: 
                   4325:           }
                   4326:       }
                   4327:       return true;
                   4328:     }
                   4329:     // }}}
                   4330: 
                   4331:     // {{{ _readBlock()
                   4332:     function _readBlock()
                   4333:     {
                   4334:       $v_block = null;
                   4335:       if (is_resource($this->_file)) {
                   4336:           if ($this->_compress_type == 'gz')
                   4337:               $v_block = @gzread($this->_file, 512);
                   4338:           else if ($this->_compress_type == 'bz2')
                   4339:               $v_block = @bzread($this->_file, 512);
                   4340:           else if ($this->_compress_type == 'none')
                   4341:               $v_block = @fread($this->_file, 512);
                   4342:           else
                   4343:               $this->_error('Unknown or missing compression type ('
                   4344:                                        .$this->_compress_type.')');
                   4345:       }
                   4346:       return $v_block;
                   4347:     }
                   4348:     // }}}
                   4349: 
                   4350:     // {{{ _jumpBlock()
                   4351:     function _jumpBlock($p_len=null)
                   4352:     {
                   4353:       if (is_resource($this->_file)) {
                   4354:           if ($p_len === null)
                   4355:               $p_len = 1;
                   4356: 
                   4357:           if ($this->_compress_type == 'gz') {
                   4358:               @gzseek($this->_file, gztell($this->_file)+($p_len*512));
                   4359:           }
                   4360:           else if ($this->_compress_type == 'bz2') {
                   4361:               // ----- Replace missing bztell() and bzseek()
                   4362:               for ($i=0; $i<$p_len; $i++)
                   4363:                   $this->_readBlock();
                   4364:           } else if ($this->_compress_type == 'none')
                   4365:               @fseek($this->_file, $p_len*512, SEEK_CUR);
                   4366:           else
                   4367:               $this->_error('Unknown or missing compression type ('
                   4368:                                        .$this->_compress_type.')');
                   4369: 
                   4370:       }
                   4371:       return true;
                   4372:     }
                   4373:     // }}}
                   4374: 
                   4375:     // {{{ _writeFooter()
                   4376:     function _writeFooter()
                   4377:     {
                   4378:       if (is_resource($this->_file)) {
                   4379:           // ----- Write the last 0 filled block for end of archive
                   4380:           $v_binary_data = pack('a1024', '');
                   4381:           $this->_writeBlock($v_binary_data);
                   4382:       }
                   4383:       return true;
                   4384:     }
                   4385:     // }}}
                   4386: 
                   4387:     // {{{ _addList()
                   4388:     function _addList($p_list, $p_add_dir, $p_remove_dir)
                   4389:     {
                   4390:       $v_result=true;
                   4391:       $v_header = array();
                   4392: 
                   4393:       // ----- Remove potential windows directory separator
                   4394:       $p_add_dir = $this->_translateWinPath($p_add_dir);
                   4395:       $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
                   4396: 
                   4397:       if (!$this->_file) {
                   4398:           $this->_error('Invalid file descriptor');
                   4399:           return false;
                   4400:       }
                   4401: 
                   4402:       if (sizeof($p_list) == 0)
                   4403:           return true;
                   4404: 
                   4405:       foreach ($p_list as $v_filename) {
                   4406:           if (!$v_result) {
                   4407:               break;
                   4408:           }
                   4409: 
                   4410:         // ----- Skip the current tar name
                   4411:         if ($v_filename == $this->_tarname)
                   4412:             continue;
                   4413: 
                   4414:         if ($v_filename == '')
                   4415:             continue;
                   4416: 
                   4417:                // ----- ignore files and directories matching the ignore regular expression
                   4418:                if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
                   4419:             $this->_warning("File '$v_filename' ignored");
                   4420:                    continue;
                   4421:                }
                   4422: 
                   4423:         if (!file_exists($v_filename)) {
                   4424:             $this->_warning("File '$v_filename' does not exist");
                   4425:             continue;
                   4426:         }
                   4427: 
                   4428:         // ----- Add the file or directory header
                   4429:         if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
                   4430:             return false;
                   4431: 
                   4432:         if (@is_dir($v_filename) && !@is_link($v_filename)) {
                   4433:             if (!($p_hdir = opendir($v_filename))) {
                   4434:                 $this->_warning("Directory '$v_filename' can not be read");
                   4435:                 continue;
                   4436:             }
                   4437:             while (false !== ($p_hitem = readdir($p_hdir))) {
                   4438:                 if (($p_hitem != '.') && ($p_hitem != '..')) {
                   4439:                     if ($v_filename != ".")
                   4440:                         $p_temp_list[0] = $v_filename.'/'.$p_hitem;
                   4441:                     else
                   4442:                         $p_temp_list[0] = $p_hitem;
                   4443: 
                   4444:                     $v_result = $this->_addList($p_temp_list,
                   4445:                                                                    $p_add_dir,
                   4446:                                                                                                $p_remove_dir);
                   4447:                 }
                   4448:             }
                   4449: 
                   4450:             unset($p_temp_list);
                   4451:             unset($p_hdir);
                   4452:             unset($p_hitem);
                   4453:         }
                   4454:       }
                   4455: 
                   4456:       return $v_result;
                   4457:     }
                   4458:     // }}}
                   4459: 
                   4460:     // {{{ _addFile()
                   4461:     function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
                   4462:     {
                   4463:       if (!$this->_file) {
                   4464:           $this->_error('Invalid file descriptor');
                   4465:           return false;
                   4466:       }
                   4467: 
                   4468:       if ($p_filename == '') {
                   4469:           $this->_error('Invalid file name');
                   4470:           return false;
                   4471:       }
                   4472: 
                   4473:       // ----- Calculate the stored filename
                   4474:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   4475:       $v_stored_filename = $p_filename;
                   4476:       if (strcmp($p_filename, $p_remove_dir) == 0) {
                   4477:           return true;
                   4478:       }
                   4479:       if ($p_remove_dir != '') {
                   4480:           if (substr($p_remove_dir, -1) != '/')
                   4481:               $p_remove_dir .= '/';
                   4482: 
                   4483:           if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
                   4484:               $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
                   4485:       }
                   4486:       $v_stored_filename = $this->_translateWinPath($v_stored_filename);
                   4487:       if ($p_add_dir != '') {
                   4488:           if (substr($p_add_dir, -1) == '/')
                   4489:               $v_stored_filename = $p_add_dir.$v_stored_filename;
                   4490:           else
                   4491:               $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
                   4492:       }
                   4493: 
                   4494:       $v_stored_filename = $this->_pathReduction($v_stored_filename);
                   4495: 
                   4496:       if ($this->_isArchive($p_filename)) {
                   4497:           if (($v_file = @fopen($p_filename, "rb")) == 0) {
                   4498:               $this->_warning("Unable to open file '".$p_filename
                   4499:                                          ."' in binary read mode");
                   4500:               return true;
                   4501:           }
                   4502: 
                   4503:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   4504:               return false;
                   4505: 
                   4506:           while (($v_buffer = fread($v_file, 512)) != '') {
                   4507:               $v_binary_data = pack("a512", "$v_buffer");
                   4508:               $this->_writeBlock($v_binary_data);
                   4509:           }
                   4510: 
                   4511:           fclose($v_file);
                   4512: 
                   4513:       } else {
                   4514:           // ----- Only header for dir
                   4515:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   4516:               return false;
                   4517:       }
                   4518: 
                   4519:       return true;
                   4520:     }
                   4521:     // }}}
                   4522: 
                   4523:     // {{{ _addString()
                   4524:     function _addString($p_filename, $p_string)
                   4525:     {
                   4526:       if (!$this->_file) {
                   4527:           $this->_error('Invalid file descriptor');
                   4528:           return false;
                   4529:       }
                   4530: 
                   4531:       if ($p_filename == '') {
                   4532:           $this->_error('Invalid file name');
                   4533:           return false;
                   4534:       }
                   4535: 
                   4536:       // ----- Calculate the stored filename
                   4537:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   4538: 
                   4539:       if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
                   4540:                                          time(), 384, "", 0, 0))
                   4541:           return false;
                   4542: 
                   4543:       $i=0;
                   4544:       while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
                   4545:           $v_binary_data = pack("a512", $v_buffer);
                   4546:           $this->_writeBlock($v_binary_data);
                   4547:       }
                   4548: 
                   4549:       return true;
                   4550:     }
                   4551:     // }}}
                   4552: 
                   4553:     // {{{ _writeHeader()
                   4554:     function _writeHeader($p_filename, $p_stored_filename)
                   4555:     {
                   4556:         if ($p_stored_filename == '')
                   4557:             $p_stored_filename = $p_filename;
                   4558:         $v_reduce_filename = $this->_pathReduction($p_stored_filename);
                   4559: 
                   4560:         if (strlen($v_reduce_filename) > 99) {
                   4561:           if (!$this->_writeLongHeader($v_reduce_filename))
                   4562:             return false;
                   4563:         }
                   4564: 
                   4565:         $v_info = lstat($p_filename);
                   4566:         $v_uid = sprintf("%07s", DecOct($v_info[4]));
                   4567:         $v_gid = sprintf("%07s", DecOct($v_info[5]));
                   4568:         $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
                   4569: 
                   4570:         $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
                   4571: 
                   4572:         $v_linkname = '';
                   4573: 
                   4574:         if (@is_link($p_filename)) {
                   4575:           $v_typeflag = '2';
                   4576:           $v_linkname = readlink($p_filename);
                   4577:           $v_size = sprintf("%011s", DecOct(0));
                   4578:         } elseif (@is_dir($p_filename)) {
                   4579:           $v_typeflag = "5";
                   4580:           $v_size = sprintf("%011s", DecOct(0));
                   4581:         } else {
                   4582:           $v_typeflag = '0';
                   4583:           clearstatcache();
                   4584:           $v_size = sprintf("%011s", DecOct($v_info['size']));
                   4585:         }
                   4586: 
                   4587:         $v_magic = 'ustar ';
                   4588: 
                   4589:         $v_version = ' ';
                   4590:         
                   4591:         if (function_exists('posix_getpwuid'))
                   4592:         {
                   4593:           $userinfo = posix_getpwuid($v_info[4]);
                   4594:           $groupinfo = posix_getgrgid($v_info[5]);
                   4595:           
                   4596:           $v_uname = $userinfo['name'];
                   4597:           $v_gname = $groupinfo['name'];
                   4598:         }
                   4599:         else
                   4600:         {
                   4601:           $v_uname = '';
                   4602:           $v_gname = '';
                   4603:         }
                   4604: 
                   4605:         $v_devmajor = '';
                   4606: 
                   4607:         $v_devminor = '';
                   4608: 
                   4609:         $v_prefix = '';
                   4610: 
                   4611:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   4612:                                            $v_reduce_filename, $v_perms, $v_uid,
                   4613:                                                                        $v_gid, $v_size, $v_mtime);
                   4614:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4615:                                           $v_typeflag, $v_linkname, $v_magic,
                   4616:                                                                   $v_version, $v_uname, $v_gname,
                   4617:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4618: 
                   4619:         // ----- Calculate the checksum
                   4620:         $v_checksum = 0;
                   4621:         // ..... First part of the header
                   4622:         for ($i=0; $i<148; $i++)
                   4623:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4624:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4625:         for ($i=148; $i<156; $i++)
                   4626:             $v_checksum += ord(' ');
                   4627:         // ..... Last part of the header
                   4628:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4629:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4630: 
                   4631:         // ----- Write the first 148 bytes of the header in the archive
                   4632:         $this->_writeBlock($v_binary_data_first, 148);
                   4633: 
                   4634:         // ----- Write the calculated checksum
                   4635:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4636:         $v_binary_data = pack("a8", $v_checksum);
                   4637:         $this->_writeBlock($v_binary_data, 8);
                   4638: 
                   4639:         // ----- Write the last 356 bytes of the header in the archive
                   4640:         $this->_writeBlock($v_binary_data_last, 356);
                   4641: 
                   4642:         return true;
                   4643:     }
                   4644:     // }}}
                   4645: 
                   4646:     // {{{ _writeHeaderBlock()
                   4647:     function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
                   4648:                                   $p_type='', $p_uid=0, $p_gid=0)
                   4649:     {
                   4650:         $p_filename = $this->_pathReduction($p_filename);
                   4651: 
                   4652:         if (strlen($p_filename) > 99) {
                   4653:           if (!$this->_writeLongHeader($p_filename))
                   4654:             return false;
                   4655:         }
                   4656: 
                   4657:         if ($p_type == "5") {
                   4658:           $v_size = sprintf("%011s", DecOct(0));
                   4659:         } else {
                   4660:           $v_size = sprintf("%011s", DecOct($p_size));
                   4661:         }
                   4662: 
                   4663:         $v_uid = sprintf("%07s", DecOct($p_uid));
                   4664:         $v_gid = sprintf("%07s", DecOct($p_gid));
                   4665:         $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
                   4666: 
                   4667:         $v_mtime = sprintf("%11s", DecOct($p_mtime));
                   4668: 
                   4669:         $v_linkname = '';
                   4670: 
                   4671:         $v_magic = 'ustar ';
                   4672: 
                   4673:         $v_version = ' ';
                   4674: 
                   4675:         if (function_exists('posix_getpwuid'))
                   4676:         {
                   4677:           $userinfo = posix_getpwuid($p_uid);
                   4678:           $groupinfo = posix_getgrgid($p_gid);
                   4679:           
                   4680:           $v_uname = $userinfo['name'];
                   4681:           $v_gname = $groupinfo['name'];
                   4682:         }
                   4683:         else
                   4684:         {
                   4685:           $v_uname = '';
                   4686:           $v_gname = '';
                   4687:         }
                   4688:         
                   4689:         $v_devmajor = '';
                   4690: 
                   4691:         $v_devminor = '';
                   4692: 
                   4693:         $v_prefix = '';
                   4694: 
                   4695:         $v_binary_data_first = pack("a100a8a8a8a12A12",
                   4696:                                            $p_filename, $v_perms, $v_uid, $v_gid,
                   4697:                                                                        $v_size, $v_mtime);
                   4698:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4699:                                           $p_type, $v_linkname, $v_magic,
                   4700:                                                                   $v_version, $v_uname, $v_gname,
                   4701:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4702: 
                   4703:         // ----- Calculate the checksum
                   4704:         $v_checksum = 0;
                   4705:         // ..... First part of the header
                   4706:         for ($i=0; $i<148; $i++)
                   4707:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4708:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4709:         for ($i=148; $i<156; $i++)
                   4710:             $v_checksum += ord(' ');
                   4711:         // ..... Last part of the header
                   4712:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4713:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4714: 
                   4715:         // ----- Write the first 148 bytes of the header in the archive
                   4716:         $this->_writeBlock($v_binary_data_first, 148);
                   4717: 
                   4718:         // ----- Write the calculated checksum
                   4719:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4720:         $v_binary_data = pack("a8", $v_checksum);
                   4721:         $this->_writeBlock($v_binary_data, 8);
                   4722: 
                   4723:         // ----- Write the last 356 bytes of the header in the archive
                   4724:         $this->_writeBlock($v_binary_data_last, 356);
                   4725: 
                   4726:         return true;
                   4727:     }
                   4728:     // }}}
                   4729: 
                   4730:     // {{{ _writeLongHeader()
                   4731:     function _writeLongHeader($p_filename)
                   4732:     {
                   4733:         $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
                   4734: 
                   4735:         $v_typeflag = 'L';
                   4736: 
                   4737:         $v_linkname = '';
                   4738: 
                   4739:         $v_magic = '';
                   4740: 
                   4741:         $v_version = '';
                   4742: 
                   4743:         $v_uname = '';
                   4744: 
                   4745:         $v_gname = '';
                   4746: 
                   4747:         $v_devmajor = '';
                   4748: 
                   4749:         $v_devminor = '';
                   4750: 
                   4751:         $v_prefix = '';
                   4752: 
                   4753:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   4754:                                            '././@LongLink', 0, 0, 0, $v_size, 0);
                   4755:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4756:                                           $v_typeflag, $v_linkname, $v_magic,
                   4757:                                                                   $v_version, $v_uname, $v_gname,
                   4758:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4759: 
                   4760:         // ----- Calculate the checksum
                   4761:         $v_checksum = 0;
                   4762:         // ..... First part of the header
                   4763:         for ($i=0; $i<148; $i++)
                   4764:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4765:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4766:         for ($i=148; $i<156; $i++)
                   4767:             $v_checksum += ord(' ');
                   4768:         // ..... Last part of the header
                   4769:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4770:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4771: 
                   4772:         // ----- Write the first 148 bytes of the header in the archive
                   4773:         $this->_writeBlock($v_binary_data_first, 148);
                   4774: 
                   4775:         // ----- Write the calculated checksum
                   4776:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4777:         $v_binary_data = pack("a8", $v_checksum);
                   4778:         $this->_writeBlock($v_binary_data, 8);
                   4779: 
                   4780:         // ----- Write the last 356 bytes of the header in the archive
                   4781:         $this->_writeBlock($v_binary_data_last, 356);
                   4782: 
                   4783:         // ----- Write the filename as content of the block
                   4784:         $i=0;
                   4785:         while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
                   4786:             $v_binary_data = pack("a512", "$v_buffer");
                   4787:             $this->_writeBlock($v_binary_data);
                   4788:         }
                   4789: 
                   4790:         return true;
                   4791:     }
                   4792:     // }}}
                   4793: 
                   4794:     // {{{ _readHeader()
                   4795:     function _readHeader($v_binary_data, &$v_header)
                   4796:     {
                   4797:         if (strlen($v_binary_data)==0) {
                   4798:             $v_header['filename'] = '';
                   4799:             return true;
                   4800:         }
                   4801: 
                   4802:         if (strlen($v_binary_data) != 512) {
                   4803:             $v_header['filename'] = '';
                   4804:             $this->_error('Invalid block size : '.strlen($v_binary_data));
                   4805:             return false;
                   4806:         }
                   4807: 
                   4808:         if (!is_array($v_header)) {
                   4809:             $v_header = array();
                   4810:         }
                   4811:         // ----- Calculate the checksum
                   4812:         $v_checksum = 0;
                   4813:         // ..... First part of the header
                   4814:         for ($i=0; $i<148; $i++)
                   4815:             $v_checksum+=ord(substr($v_binary_data,$i,1));
                   4816:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4817:         for ($i=148; $i<156; $i++)
                   4818:             $v_checksum += ord(' ');
                   4819:         // ..... Last part of the header
                   4820:         for ($i=156; $i<512; $i++)
                   4821:            $v_checksum+=ord(substr($v_binary_data,$i,1));
                   4822: 
                   4823:         $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
                   4824:                                 ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
                   4825:                                                 ."a32uname/a32gname/a8devmajor/a8devminor",
                   4826:                                                 $v_binary_data);
                   4827: 
                   4828:         // ----- Extract the checksum
                   4829:         $v_header['checksum'] = OctDec(trim($v_data['checksum']));
                   4830:         if ($v_header['checksum'] != $v_checksum) {
                   4831:             $v_header['filename'] = '';
                   4832: 
                   4833:             // ----- Look for last block (empty block)
                   4834:             if (($v_checksum == 256) && ($v_header['checksum'] == 0))
                   4835:                 return true;
                   4836: 
                   4837:             $this->_error('Invalid checksum for file "'.$v_data['filename']
                   4838:                                      .'" : '.$v_checksum.' calculated, '
                   4839:                                                  .$v_header['checksum'].' expected');
                   4840:             return false;
                   4841:         }
                   4842: 
                   4843:         // ----- Extract the properties
                   4844:         $v_header['filename'] = $v_data['filename'];
                   4845:         if ($this->_maliciousFilename($v_header['filename'])) {
                   4846:             $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
                   4847:                 '" will not install in desired directory tree');
                   4848:             return false;
                   4849:         }
                   4850:         $v_header['mode'] = OctDec(trim($v_data['mode']));
                   4851:         $v_header['uid'] = OctDec(trim($v_data['uid']));
                   4852:         $v_header['gid'] = OctDec(trim($v_data['gid']));
                   4853:         $v_header['size'] = OctDec(trim($v_data['size']));
                   4854:         $v_header['mtime'] = OctDec(trim($v_data['mtime']));
                   4855:         if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
                   4856:           $v_header['size'] = 0;
                   4857:         }
                   4858:         $v_header['link'] = trim($v_data['link']);
                   4859:         /* ----- All these fields are removed form the header because
                   4860:                they do not carry interesting info
                   4861:         $v_header[magic] = trim($v_data[magic]);
                   4862:         $v_header[version] = trim($v_data[version]);
                   4863:         $v_header[uname] = trim($v_data[uname]);
                   4864:         $v_header[gname] = trim($v_data[gname]);
                   4865:         $v_header[devmajor] = trim($v_data[devmajor]);
                   4866:         $v_header[devminor] = trim($v_data[devminor]);
                   4867:         */
                   4868: 
                   4869:         return true;
                   4870:     }
                   4871:     // }}}
                   4872: 
                   4873:     // {{{ _maliciousFilename()
                   4874:     /**
                   4875:      * Detect and report a malicious file name
                   4876:      *
                   4877:      * @param string $file
                   4878:      * @return bool
                   4879:      * @access private
                   4880:      */
                   4881:     function _maliciousFilename($file)
                   4882:     {
                   4883:         if (strpos($file, '/../') !== false) {
                   4884:             return true;
                   4885:         }
                   4886:         if (strpos($file, '../') === 0) {
                   4887:             return true;
                   4888:         }
                   4889:         return false;
                   4890:     }
                   4891:     // }}}
                   4892: 
                   4893:     // {{{ _readLongHeader()
                   4894:     function _readLongHeader(&$v_header)
                   4895:     {
                   4896:       $v_filename = '';
                   4897:       $n = floor($v_header['size']/512);
                   4898:       for ($i=0; $i<$n; $i++) {
                   4899:         $v_content = $this->_readBlock();
                   4900:         $v_filename .= $v_content;
                   4901:       }
                   4902:       if (($v_header['size'] % 512) != 0) {
                   4903:         $v_content = $this->_readBlock();
                   4904:         $v_filename .= trim($v_content);
                   4905:       }
                   4906: 
                   4907:       // ----- Read the next header
                   4908:       $v_binary_data = $this->_readBlock();
                   4909: 
                   4910:       if (!$this->_readHeader($v_binary_data, $v_header))
                   4911:         return false;
                   4912: 
                   4913:       $v_filename = trim($v_filename);
                   4914:       $v_header['filename'] = $v_filename;
                   4915:         if ($this->_maliciousFilename($v_filename)) {
                   4916:             $this->_error('Malicious .tar detected, file "' . $v_filename .
                   4917:                 '" will not install in desired directory tree');
                   4918:             return false;
                   4919:       }
                   4920: 
                   4921:       return true;
                   4922:     }
                   4923:     // }}}
                   4924: 
                   4925:     // {{{ _extractInString()
                   4926:     /**
                   4927:     * This method extract from the archive one file identified by $p_filename.
                   4928:     * The return value is a string with the file content, or NULL on error.
                   4929:     * @param string $p_filename     The path of the file to extract in a string.
                   4930:     * @return                       a string with the file content or NULL.
                   4931:     * @access private
                   4932:     */
                   4933:     function _extractInString($p_filename)
                   4934:     {
                   4935:         $v_result_str = "";
                   4936: 
                   4937:         While (strlen($v_binary_data = $this->_readBlock()) != 0)
                   4938:         {
                   4939:           if (!$this->_readHeader($v_binary_data, $v_header))
                   4940:             return NULL;
                   4941: 
                   4942:           if ($v_header['filename'] == '')
                   4943:             continue;
                   4944: 
                   4945:           // ----- Look for long filename
                   4946:           if ($v_header['typeflag'] == 'L') {
                   4947:             if (!$this->_readLongHeader($v_header))
                   4948:               return NULL;
                   4949:           }
                   4950: 
                   4951:           if ($v_header['filename'] == $p_filename) {
                   4952:               if ($v_header['typeflag'] == "5") {
                   4953:                   $this->_error('Unable to extract in string a directory '
                   4954:                                                .'entry {'.$v_header['filename'].'}');
                   4955:                   return NULL;
                   4956:               } else {
                   4957:                   $n = floor($v_header['size']/512);
                   4958:                   for ($i=0; $i<$n; $i++) {
                   4959:                       $v_result_str .= $this->_readBlock();
                   4960:                   }
                   4961:                   if (($v_header['size'] % 512) != 0) {
                   4962:                       $v_content = $this->_readBlock();
                   4963:                       $v_result_str .= substr($v_content, 0,
                   4964:                                                                  ($v_header['size'] % 512));
                   4965:                   }
                   4966:                   return $v_result_str;
                   4967:               }
                   4968:           } else {
                   4969:               $this->_jumpBlock(ceil(($v_header['size']/512)));
                   4970:           }
                   4971:         }
                   4972: 
                   4973:         return NULL;
                   4974:     }
                   4975:     // }}}
                   4976: 
                   4977:     // {{{ _extractList()
                   4978:     function _extractList($p_path, &$p_list_detail, $p_mode,
                   4979:                              $p_file_list, $p_remove_path)
                   4980:     {
                   4981:     $v_result=true;
                   4982:     $v_nb = 0;
                   4983:     $v_extract_all = true;
                   4984:     $v_listing = false;
                   4985: 
                   4986:     $p_path = $this->_translateWinPath($p_path, false);
                   4987:     if ($p_path == '' || (substr($p_path, 0, 1) != '/'
                   4988:            && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
                   4989:       $p_path = "./".$p_path;
                   4990:     }
                   4991:     $p_remove_path = $this->_translateWinPath($p_remove_path);
                   4992: 
                   4993:     // ----- Look for path to remove format (should end by /)
                   4994:     if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
                   4995:       $p_remove_path .= '/';
                   4996:     $p_remove_path_size = strlen($p_remove_path);
                   4997: 
                   4998:     switch ($p_mode) {
                   4999:       case "complete" :
                   5000:         $v_extract_all = TRUE;
                   5001:         $v_listing = FALSE;
                   5002:       break;
                   5003:       case "partial" :
                   5004:           $v_extract_all = FALSE;
                   5005:           $v_listing = FALSE;
                   5006:       break;
                   5007:       case "list" :
                   5008:           $v_extract_all = FALSE;
                   5009:           $v_listing = TRUE;
                   5010:       break;
                   5011:       default :
                   5012:         $this->_error('Invalid extract mode ('.$p_mode.')');
                   5013:         return false;
                   5014:     }
                   5015: 
                   5016:     clearstatcache();
                   5017: 
                   5018:     while (strlen($v_binary_data = $this->_readBlock()) != 0)
                   5019:     {
                   5020:       $v_extract_file = FALSE;
                   5021:       $v_extraction_stopped = 0;
                   5022: 
                   5023:       if (!$this->_readHeader($v_binary_data, $v_header))
                   5024:         return false;
                   5025: 
                   5026:       if ($v_header['filename'] == '') {
                   5027:         continue;
                   5028:       }
                   5029: 
                   5030:       // ----- Look for long filename
                   5031:       if ($v_header['typeflag'] == 'L') {
                   5032:         if (!$this->_readLongHeader($v_header))
                   5033:           return false;
                   5034:       }
                   5035: 
                   5036:       if ((!$v_extract_all) && (is_array($p_file_list))) {
                   5037:         // ----- By default no unzip if the file is not found
                   5038:         $v_extract_file = false;
                   5039: 
                   5040:         for ($i=0; $i<sizeof($p_file_list); $i++) {
                   5041:           // ----- Look if it is a directory
                   5042:           if (substr($p_file_list[$i], -1) == '/') {
                   5043:             // ----- Look if the directory is in the filename path
                   5044:             if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
                   5045:                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
                   5046:                                    == $p_file_list[$i])) {
                   5047:               $v_extract_file = TRUE;
                   5048:               break;
                   5049:             }
                   5050:           }
                   5051: 
                   5052:           // ----- It is a file, so compare the file names
                   5053:           elseif ($p_file_list[$i] == $v_header['filename']) {
                   5054:             $v_extract_file = TRUE;
                   5055:             break;
                   5056:           }
                   5057:         }
                   5058:       } else {
                   5059:         $v_extract_file = TRUE;
                   5060:       }
                   5061: 
                   5062:       // ----- Look if this file need to be extracted
                   5063:       if (($v_extract_file) && (!$v_listing))
                   5064:       {
                   5065:         if (($p_remove_path != '')
                   5066:             && (substr($v_header['filename'], 0, $p_remove_path_size)
                   5067:                            == $p_remove_path))
                   5068:           $v_header['filename'] = substr($v_header['filename'],
                   5069:                                                 $p_remove_path_size);
                   5070:         if (($p_path != './') && ($p_path != '/')) {
                   5071:           while (substr($p_path, -1) == '/')
                   5072:             $p_path = substr($p_path, 0, strlen($p_path)-1);
                   5073: 
                   5074:           if (substr($v_header['filename'], 0, 1) == '/')
                   5075:               $v_header['filename'] = $p_path.$v_header['filename'];
                   5076:           else
                   5077:             $v_header['filename'] = $p_path.'/'.$v_header['filename'];
                   5078:         }
                   5079:         if (file_exists($v_header['filename'])) {
                   5080:           if (   (@is_dir($v_header['filename']))
                   5081:                      && ($v_header['typeflag'] == '')) {
                   5082:             $this->_error('File '.$v_header['filename']
                   5083:                                      .' already exists as a directory');
                   5084:             return false;
                   5085:           }
                   5086:           if (   ($this->_isArchive($v_header['filename']))
                   5087:                      && ($v_header['typeflag'] == "5")) {
                   5088:             $this->_error('Directory '.$v_header['filename']
                   5089:                                      .' already exists as a file');
                   5090:             return false;
                   5091:           }
                   5092:           if (!is_writeable($v_header['filename'])) {
                   5093:             $this->_error('File '.$v_header['filename']
                   5094:                                      .' already exists and is write protected');
                   5095:             return false;
                   5096:           }
                   5097:           if (filemtime($v_header['filename']) > $v_header['mtime']) {
                   5098:             // To be completed : An error or silent no replace ?
                   5099:           }
                   5100:         }
                   5101: 
                   5102:         // ----- Check the directory availability and create it if necessary
                   5103:         elseif (($v_result
                   5104:                         = $this->_dirCheck(($v_header['typeflag'] == "5"
                   5105:                                                    ?$v_header['filename']
                   5106:                                                                        :dirname($v_header['filename'])))) != 1) {
                   5107:             $this->_error('Unable to create path for '.$v_header['filename']);
                   5108:             return false;
                   5109:         }
                   5110: 
                   5111:         if ($v_extract_file) {
                   5112:           if ($v_header['typeflag'] == "5") {
                   5113:             if (!@file_exists($v_header['filename'])) {
                   5114:                 if (!@mkdir($v_header['filename'], 0777)) {
                   5115:                     $this->_error('Unable to create directory {'
                   5116:                                                      .$v_header['filename'].'}');
                   5117:                     return false;
                   5118:                 }
                   5119:             }
                   5120:           } elseif ($v_header['typeflag'] == "2") {
                   5121:               if (@file_exists($v_header['filename'])) {
                   5122:                   @unlink($v_header['filename']);
                   5123:               }
                   5124:               if (!@symlink($v_header['link'], $v_header['filename'])) {
                   5125:                   $this->_error('Unable to extract symbolic link {'
                   5126:                                 .$v_header['filename'].'}');
                   5127:                   return false;
                   5128:               }
                   5129:           } else {
                   5130:               if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                   5131:                   $this->_error('Error while opening {'.$v_header['filename']
                   5132:                                                .'} in write binary mode');
                   5133:                   return false;
                   5134:               } else {
                   5135:                   $n = floor($v_header['size']/512);
                   5136:                   for ($i=0; $i<$n; $i++) {
                   5137:                       $v_content = $this->_readBlock();
                   5138:                       fwrite($v_dest_file, $v_content, 512);
                   5139:                   }
                   5140:             if (($v_header['size'] % 512) != 0) {
                   5141:               $v_content = $this->_readBlock();
                   5142:               fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
                   5143:             }
                   5144: 
                   5145:             @fclose($v_dest_file);
                   5146: 
                   5147:             // ----- Change the file mode, mtime
                   5148:             @touch($v_header['filename'], $v_header['mtime']);
                   5149:             if ($v_header['mode'] & 0111) {
                   5150:                 // make file executable, obey umask
                   5151:                 $mode = fileperms($v_header['filename']) | (~umask() & 0111);
                   5152:                 @chmod($v_header['filename'], $mode);
                   5153:             }
                   5154:           }
                   5155: 
                   5156:           // ----- Check the file size
                   5157:           clearstatcache();
                   5158:           if (filesize($v_header['filename']) != $v_header['size']) {
                   5159:               $this->_error('Extracted file '.$v_header['filename']
                   5160:                                        .' does not have the correct file size \''
                   5161:                                                        .filesize($v_header['filename'])
                   5162:                                                        .'\' ('.$v_header['size']
                   5163:                                                        .' expected). Archive may be corrupted.');
                   5164:               return false;
                   5165:           }
                   5166:           }
                   5167:         } else {
                   5168:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   5169:         }
                   5170:       } else {
                   5171:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   5172:       }
                   5173: 
                   5174:       /* TBC : Seems to be unused ...
                   5175:       if ($this->_compress)
                   5176:         $v_end_of_file = @gzeof($this->_file);
                   5177:       else
                   5178:         $v_end_of_file = @feof($this->_file);
                   5179:         */
                   5180: 
                   5181:       if ($v_listing || $v_extract_file || $v_extraction_stopped) {
                   5182:         // ----- Log extracted files
                   5183:         if (($v_file_dir = dirname($v_header['filename']))
                   5184:                    == $v_header['filename'])
                   5185:           $v_file_dir = '';
                   5186:         if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
                   5187:           $v_file_dir = '/';
                   5188: 
                   5189:         $p_list_detail[$v_nb++] = $v_header;
                   5190:         if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
                   5191:             return true;
                   5192:         }
                   5193:       }
                   5194:     }
                   5195: 
                   5196:         return true;
                   5197:     }
                   5198:     // }}}
                   5199: 
                   5200:     // {{{ _openAppend()
                   5201:     function _openAppend()
                   5202:     {
                   5203:         if (filesize($this->_tarname) == 0)
                   5204:           return $this->_openWrite();
                   5205: 
                   5206:         if ($this->_compress) {
                   5207:             $this->_close();
                   5208: 
                   5209:             if (!@rename($this->_tarname, $this->_tarname.".tmp")) {
                   5210:                 $this->_error('Error while renaming \''.$this->_tarname
                   5211:                                              .'\' to temporary file \''.$this->_tarname
                   5212:                                                          .'.tmp\'');
                   5213:                 return false;
                   5214:             }
                   5215: 
                   5216:             if ($this->_compress_type == 'gz')
                   5217:                 $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
                   5218:             elseif ($this->_compress_type == 'bz2')
                   5219:                 $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
                   5220: 
                   5221:             if ($v_temp_tar == 0) {
                   5222:                 $this->_error('Unable to open file \''.$this->_tarname
                   5223:                                              .'.tmp\' in binary read mode');
                   5224:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   5225:                 return false;
                   5226:             }
                   5227: 
                   5228:             if (!$this->_openWrite()) {
                   5229:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   5230:                 return false;
                   5231:             }
                   5232: 
                   5233:             if ($this->_compress_type == 'gz') {
                   5234:                 while (!@gzeof($v_temp_tar)) {
                   5235:                     $v_buffer = @gzread($v_temp_tar, 512);
                   5236:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
                   5237:                         // do not copy end blocks, we will re-make them
                   5238:                         // after appending
                   5239:                         continue;
                   5240:                     }
                   5241:                     $v_binary_data = pack("a512", $v_buffer);
                   5242:                     $this->_writeBlock($v_binary_data);
                   5243:                 }
                   5244: 
                   5245:                 @gzclose($v_temp_tar);
                   5246:             }
                   5247:             elseif ($this->_compress_type == 'bz2') {
                   5248:                 while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
                   5249:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
                   5250:                         continue;
                   5251:                     }
                   5252:                     $v_binary_data = pack("a512", $v_buffer);
                   5253:                     $this->_writeBlock($v_binary_data);
                   5254:                 }
                   5255: 
                   5256:                 @bzclose($v_temp_tar);
                   5257:             }
                   5258: 
                   5259:             if (!@unlink($this->_tarname.".tmp")) {
                   5260:                 $this->_error('Error while deleting temporary file \''
                   5261:                                              .$this->_tarname.'.tmp\'');
                   5262:             }
                   5263: 
                   5264:         } else {
                   5265:             // ----- For not compressed tar, just add files before the last
                   5266:                        //       one or two 512 bytes block
                   5267:             if (!$this->_openReadWrite())
                   5268:                return false;
                   5269: 
                   5270:             clearstatcache();
                   5271:             $v_size = filesize($this->_tarname);
                   5272: 
                   5273:             // We might have zero, one or two end blocks.
                   5274:             // The standard is two, but we should try to handle
                   5275:             // other cases.
                   5276:             fseek($this->_file, $v_size - 1024);
                   5277:             if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   5278:                 fseek($this->_file, $v_size - 1024);
                   5279:             }
                   5280:             elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   5281:                 fseek($this->_file, $v_size - 512);
                   5282:             }
                   5283:         }
                   5284: 
                   5285:         return true;
                   5286:     }
                   5287:     // }}}
                   5288: 
                   5289:     // {{{ _append()
                   5290:     function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
                   5291:     {
                   5292:         if (!$this->_openAppend())
                   5293:             return false;
                   5294: 
                   5295:         if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
                   5296:            $this->_writeFooter();
                   5297: 
                   5298:         $this->_close();
                   5299: 
                   5300:         return true;
                   5301:     }
                   5302:     // }}}
                   5303: 
                   5304:     // {{{ _dirCheck()
                   5305: 
                   5306:     /**
                   5307:      * Check if a directory exists and create it (including parent
                   5308:      * dirs) if not.
                   5309:      *
                   5310:      * @param string $p_dir directory to check
                   5311:      *
                   5312:      * @return bool TRUE if the directory exists or was created
                   5313:      */
                   5314:     function _dirCheck($p_dir)
                   5315:     {
                   5316:         clearstatcache();
                   5317:         if ((@is_dir($p_dir)) || ($p_dir == ''))
                   5318:             return true;
                   5319: 
                   5320:         $p_parent_dir = dirname($p_dir);
                   5321: 
                   5322:         if (($p_parent_dir != $p_dir) &&
                   5323:             ($p_parent_dir != '') &&
                   5324:             (!$this->_dirCheck($p_parent_dir)))
                   5325:              return false;
                   5326: 
                   5327:         if (!@mkdir($p_dir, 0777)) {
                   5328:             $this->_error("Unable to create directory '$p_dir'");
                   5329:             return false;
                   5330:         }
                   5331: 
                   5332:         return true;
                   5333:     }
                   5334: 
                   5335:     // }}}
                   5336: 
                   5337:     // {{{ _pathReduction()
                   5338: 
                   5339:     /**
                   5340:      * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
                   5341:      * rand emove double slashes.
                   5342:      *
                   5343:      * @param string $p_dir path to reduce
                   5344:      *
                   5345:      * @return string reduced path
                   5346:      *
                   5347:      * @access private
                   5348:      *
                   5349:      */
                   5350:     function _pathReduction($p_dir)
                   5351:     {
                   5352:         $v_result = '';
                   5353: 
                   5354:         // ----- Look for not empty path
                   5355:         if ($p_dir != '') {
                   5356:             // ----- Explode path by directory names
                   5357:             $v_list = explode('/', $p_dir);
                   5358: 
                   5359:             // ----- Study directories from last to first
                   5360:             for ($i=sizeof($v_list)-1; $i>=0; $i--) {
                   5361:                 // ----- Look for current path
                   5362:                 if ($v_list[$i] == ".") {
                   5363:                     // ----- Ignore this directory
                   5364:                     // Should be the first $i=0, but no check is done
                   5365:                 }
                   5366:                 else if ($v_list[$i] == "..") {
                   5367:                     // ----- Ignore it and ignore the $i-1
                   5368:                     $i--;
                   5369:                 }
                   5370:                 else if (   ($v_list[$i] == '')
                   5371:                                         && ($i!=(sizeof($v_list)-1))
                   5372:                                                 && ($i!=0)) {
                   5373:                     // ----- Ignore only the double '//' in path,
                   5374:                     // but not the first and last /
                   5375:                 } else {
                   5376:                     $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
                   5377:                                                    .$v_result:'');
                   5378:                 }
                   5379:             }
                   5380:         }
                   5381:         $v_result = strtr($v_result, '\\', '/');
                   5382:         return $v_result;
                   5383:     }
                   5384: 
                   5385:     // }}}
                   5386: 
                   5387:     // {{{ _translateWinPath()
                   5388:     function _translateWinPath($p_path, $p_remove_disk_letter=true)
                   5389:     {
                   5390:       if (defined('OS_WINDOWS') && OS_WINDOWS) {
                   5391:           // ----- Look for potential disk letter
                   5392:           if (   ($p_remove_disk_letter)
                   5393:                      && (($v_position = strpos($p_path, ':')) != false)) {
                   5394:               $p_path = substr($p_path, $v_position+1);
                   5395:           }
                   5396:           // ----- Change potential windows directory separator
                   5397:           if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
                   5398:               $p_path = strtr($p_path, '\\', '/');
                   5399:           }
                   5400:       }
                   5401:       return $p_path;
                   5402:     }
                   5403:     // }}}
                   5404: 
                   5405: }
                   5406: ?>
                   5407: Archive_Tar-1.3.7/docs/Archive_Tar.txt100644   1750   1750       43673      100644  12710 Documentation for class Archive_Tar
                   5408: ===================================
                   5409: Last update : 2001-08-15
                   5410: 
                   5411: 
                   5412: 
                   5413: Overview :
                   5414: ----------
                   5415: 
                   5416:   The Archive_Tar class helps in creating and managing GNU TAR format
                   5417:   files compressed by GNU ZIP or not. 
                   5418:   The class offers basic functions like creating an archive, adding
                   5419:   files in the archive, extracting files from the archive and listing
                   5420:   the archive content. 
                   5421:   It also provide advanced functions that allow the adding and
                   5422:   extraction of files with path manipulation. 
                   5423: 
                   5424: 
                   5425: Sample :
                   5426: --------
                   5427: 
                   5428:   // ----- Creating the object (uncompressed archive)
                   5429:   $tar_object = new Archive_Tar("tarname.tar");
                   5430:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);
                   5431: 
                   5432:   // ----- Creating the archive
                   5433:   $v_list[0]="file.txt";
                   5434:   $v_list[1]="data/";
                   5435:   $v_list[2]="file.log";
                   5436:   $tar_object->create($v_list);
                   5437: 
                   5438:   // ----- Adding files
                   5439:   $v_list[0]="dev/file.txt";
                   5440:   $v_list[1]="dev/data/";
                   5441:   $v_list[2]="log/file.log";
                   5442:   $tar_object->add($v_list);
                   5443: 
                   5444:   // ----- Adding more files
                   5445:   $tar_object->add("release/newfile.log release/readme.txt");
                   5446: 
                   5447:   // ----- Listing the content
                   5448:   if (($v_list  =  $tar_object->listContent()) != 0)
                   5449:     for ($i=0; $i<sizeof($v_list); $i++)
                   5450:     {
                   5451:       echo "Filename :'".$v_list[$i][filename]."'<br>";
                   5452:       echo " .size :'".$v_list[$i][size]."'<br>";
                   5453:       echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
                   5454:       echo " .mode :'".$v_list[$i][mode]."'<br>";
                   5455:       echo " .uid :'".$v_list[$i][uid]."'<br>";
                   5456:       echo " .gid :'".$v_list[$i][gid]."'<br>";
                   5457:       echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
                   5458:     }
                   5459: 
                   5460:   // ----- Extracting the archive in directory "install"
                   5461:   $tar_object->extract("install");
                   5462: 
                   5463: 
                   5464: Public arguments :
                   5465: ------------------
                   5466: 
                   5467: None
                   5468: 
                   5469: 
                   5470: Public Methods :
                   5471: ----------------
                   5472: 
                   5473: Method : Archive_Tar($p_tarname, $compress = null)
                   5474: Description :
                   5475:   Archive_Tar Class constructor. This flavour of the constructor only
                   5476:   declare a new Archive_Tar object, identifying it by the name of the
                   5477:   tar file.
                   5478:   If the compress argument is set the tar will be read or created as a
                   5479:   gzip or bz2 compressed TAR file. 
                   5480: Arguments :
                   5481:   $p_tarname : A valid filename for the tar archive file.
                   5482:   $p_compress : can be null, 'gz' or 'bz2'. For
                   5483:                 compatibility reason it can also be true. This
                   5484:                 parameter indicates if gzip or bz2 compression
                   5485:                 is required. 
                   5486: Return value :
                   5487:   The Archive_Tar object.
                   5488: Sample :
                   5489:   $tar_object = new Archive_Tar("tarname.tar");
                   5490:   $tar_object_compressed = new Archive_Tar("tarname.tgz", true);
                   5491: How it works :
                   5492:   Initialize the object.
                   5493: 
                   5494: Method : create($p_filelist)
                   5495: Description :
                   5496:   This method creates the archive file and add the files / directories
                   5497:   that are listed in $p_filelist. 
                   5498:   If the file already exists and is writable, it is replaced by the
                   5499:   new tar. It is a create and not an add. If the file exists and is
                   5500:   read-only or is a directory it is not replaced. The method return
                   5501:   false and a PEAR error text. 
                   5502:   The $p_filelist parameter can be an array of string, each string
                   5503:   representing a filename or a directory name with their path if
                   5504:   needed. It can also be a single string with names separated by a
                   5505:   single blank. 
                   5506:   See also createModify() method for more details.
                   5507: Arguments :
                   5508:   $p_filelist : An array of filenames and directory names, or a single
                   5509:   string with names separated by a single blank space. 
                   5510: Return value :
                   5511:   true on success, false on error.
                   5512: Sample 1 :
                   5513:   $tar_object = new Archive_Tar("tarname.tar");
                   5514:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5515:   $v_list[0]="file.txt";
                   5516:   $v_list[1]="data/"; (Optional '/' at the end)
                   5517:   $v_list[2]="file.log";
                   5518:   $tar_object->create($v_list);
                   5519: Sample 2 :
                   5520:   $tar_object = new Archive_Tar("tarname.tar");
                   5521:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5522:   $tar_object->create("file.txt data/ file.log");
                   5523: How it works :
                   5524:   Just calling the createModify() method with the right parameters.
                   5525: 
                   5526: Method : createModify($p_filelist, $p_add_dir, $p_remove_dir = "")
                   5527: Description :
                   5528:   This method creates the archive file and add the files / directories
                   5529:   that are listed in $p_filelist. 
                   5530:   If the file already exists and is writable, it is replaced by the
                   5531:   new tar. It is a create and not an add. If the file exists and is
                   5532:   read-only or is a directory it is not replaced. The method return
                   5533:   false and a PEAR error text. 
                   5534:   The $p_filelist parameter can be an array of string, each string
                   5535:   representing a filename or a directory name with their path if
                   5536:   needed. It can also be a single string with names separated by a
                   5537:   single blank. 
                   5538:   The path indicated in $p_remove_dir will be removed from the
                   5539:   memorized path of each file / directory listed when this path
                   5540:   exists. By default nothing is removed (empty path "") 
                   5541:   The path indicated in $p_add_dir will be added at the beginning of
                   5542:   the memorized path of each file / directory listed. However it can
                   5543:   be set to empty "". The adding of a path is done after the removing
                   5544:   of path. 
                   5545:   The path add/remove ability enables the user to prepare an archive
                   5546:   for extraction in a different path than the origin files are. 
                   5547:   See also addModify() method for file adding properties.
                   5548: Arguments :
                   5549:   $p_filelist : An array of filenames and directory names, or a single
                   5550:                 string with names separated by a single blank space.
                   5551:   $p_add_dir : A string which contains a path to be added to the
                   5552:                memorized path of each element in the list. 
                   5553:   $p_remove_dir : A string which contains a path to be removed from
                   5554:                   the memorized path of each element in the list, when
                   5555:                  relevant.
                   5556: Return value :
                   5557:   true on success, false on error.
                   5558: Sample 1 :
                   5559:   $tar_object = new Archive_Tar("tarname.tar");
                   5560:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5561:   $v_list[0]="file.txt";
                   5562:   $v_list[1]="data/"; (Optional '/' at the end)
                   5563:   $v_list[2]="file.log";
                   5564:   $tar_object->createModify($v_list, "install");
                   5565:   // files are stored in the archive as :
                   5566:   //   install/file.txt
                   5567:   //   install/data
                   5568:   //   install/data/file1.txt
                   5569:   //   install/data/... all the files and sub-dirs of data/
                   5570:   //   install/file.log
                   5571: Sample 2 :
                   5572:   $tar_object = new Archive_Tar("tarname.tar");
                   5573:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5574:   $v_list[0]="dev/file.txt";
                   5575:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5576:   $v_list[2]="log/file.log";
                   5577:   $tar_object->createModify($v_list, "install", "dev");
                   5578:   // files are stored in the archive as :
                   5579:   //   install/file.txt
                   5580:   //   install/data
                   5581:   //   install/data/file1.txt
                   5582:   //   install/data/... all the files and sub-dirs of data/
                   5583:   //   install/log/file.log
                   5584: How it works :
                   5585:   Open the file in write mode (erasing the existing one if one),
                   5586:   call the _addList() method for adding the files in an empty archive,
                   5587:   add the tar footer (512 bytes block), close the tar file.
                   5588: 
                   5589: 
                   5590: Method : addModify($p_filelist, $p_add_dir, $p_remove_dir="")
                   5591: Description :
                   5592:   This method add the files / directories listed in $p_filelist at the
                   5593:   end of the existing archive. If the archive does not yet exists it
                   5594:   is created.
                   5595:   The $p_filelist parameter can be an array of string, each string
                   5596:   representing a filename or a directory name with their path if
                   5597:   needed. It can also be a single string with names separated by a
                   5598:   single blank. 
                   5599:   The path indicated in $p_remove_dir will be removed from the
                   5600:   memorized path of each file / directory listed when this path
                   5601:   exists. By default nothing is removed (empty path "") 
                   5602:   The path indicated in $p_add_dir will be added at the beginning of
                   5603:   the memorized path of each file / directory listed. However it can
                   5604:   be set to empty "". The adding of a path is done after the removing
                   5605:   of path. 
                   5606:   The path add/remove ability enables the user to prepare an archive
                   5607:   for extraction in a different path than the origin files are. 
                   5608:   If a file/dir is already in the archive it will only be added at the
                   5609:   end of the archive. There is no update of the existing archived
                   5610:   file/dir. However while extracting the archive, the last file will
                   5611:   replace the first one. This results in a none optimization of the
                   5612:   archive size. 
                   5613:   If a file/dir does not exist the file/dir is ignored. However an
                   5614:   error text is send to PEAR error. 
                   5615:   If a file/dir is not readable the file/dir is ignored. However an
                   5616:   error text is send to PEAR error. 
                   5617:   If the resulting filename/dirname (after the add/remove option or
                   5618:   not) string is greater than 99 char, the file/dir is
                   5619:   ignored. However an error text is send to PEAR error. 
                   5620: Arguments :
                   5621:   $p_filelist : An array of filenames and directory names, or a single
                   5622:                 string with names separated by a single blank space. 
                   5623:   $p_add_dir : A string which contains a path to be added to the
                   5624:                memorized path of each element in the list. 
                   5625:   $p_remove_dir : A string which contains a path to be removed from
                   5626:                   the memorized path of each element in the list, when
                   5627:                  relevant.
                   5628: Return value :
                   5629:   true on success, false on error.
                   5630: Sample 1 :
                   5631:   $tar_object = new Archive_Tar("tarname.tar");
                   5632:   [...]
                   5633:   $v_list[0]="dev/file.txt";
                   5634:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5635:   $v_list[2]="log/file.log";
                   5636:   $tar_object->addModify($v_list, "install");
                   5637:   // files are stored in the archive as :
                   5638:   //   install/file.txt
                   5639:   //   install/data
                   5640:   //   install/data/file1.txt
                   5641:   //   install/data/... all the files and sub-dirs of data/
                   5642:   //   install/file.log
                   5643: Sample 2 :
                   5644:   $tar_object = new Archive_Tar("tarname.tar");
                   5645:   [...]
                   5646:   $v_list[0]="dev/file.txt";
                   5647:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5648:   $v_list[2]="log/file.log";
                   5649:   $tar_object->addModify($v_list, "install", "dev");
                   5650:   // files are stored in the archive as :
                   5651:   //   install/file.txt
                   5652:   //   install/data
                   5653:   //   install/data/file1.txt
                   5654:   //   install/data/... all the files and sub-dirs of data/
                   5655:   //   install/log/file.log
                   5656: How it works :
                   5657:   If the archive does not exists it create it and add the files.
                   5658:   If the archive does exists and is not compressed, it open it, jump
                   5659:   before the last empty 512 bytes block (tar footer) and add the files
                   5660:   at this point.
                   5661:   If the archive does exists and is compressed, a temporary copy file
                   5662:   is created. This temporary file is then 'gzip' read block by block
                   5663:   until the last empty block. The new files are then added in the
                   5664:   compressed file.
                   5665:   The adding of files is done by going through the file/dir list,
                   5666:   adding files per files, in a recursive way through the
                   5667:   directory. Each time a path need to be added/removed it is done
                   5668:   before writing the file header in the archive.
                   5669: 
                   5670: Method : add($p_filelist)
                   5671: Description :
                   5672:   This method add the files / directories listed in $p_filelist at the
                   5673:   end of the existing archive. If the archive does not yet exists it
                   5674:   is created. 
                   5675:   The $p_filelist parameter can be an array of string, each string
                   5676:   representing a filename or a directory name with their path if
                   5677:   needed. It can also be a single string with names separated by a
                   5678:   single blank. 
                   5679:   See addModify() method for details and limitations.
                   5680: Arguments :
                   5681:   $p_filelist : An array of filenames and directory names, or a single
                   5682:   string with names separated by a single blank space. 
                   5683: Return value :
                   5684:   true on success, false on error.
                   5685: Sample 1 :
                   5686:   $tar_object = new Archive_Tar("tarname.tar");
                   5687:   [...]
                   5688:   $v_list[0]="dev/file.txt";
                   5689:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5690:   $v_list[2]="log/file.log";
                   5691:   $tar_object->add($v_list);
                   5692: Sample 2 :
                   5693:   $tar_object = new Archive_Tar("tarname.tgz", true);
                   5694:   [...]
                   5695:   $v_list[0]="dev/file.txt";
                   5696:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5697:   $v_list[2]="log/file.log";
                   5698:   $tar_object->add($v_list);
                   5699: How it works :
                   5700:   Simply call the addModify() method with the right parameters.
                   5701: 
                   5702: Method : addString($p_filename, $p_string)
                   5703: Description :
                   5704:   This method add a single string as a file at the
                   5705:   end of the existing archive. If the archive does not yet exists it
                   5706:   is created.
                   5707: Arguments :
                   5708:   $p_filename : A string which contains the full filename path
                   5709:                 that will be associated with the string.
                   5710:   $p_string :   The content of the file added in the archive.
                   5711: Return value :
                   5712:   true on success, false on error.
                   5713: Sample 1 :
                   5714:   $v_archive = & new Archive_Tar($p_filename);
                   5715:   $v_archive->setErrorHandling(PEAR_ERROR_PRINT);
                   5716:   $v_result = $v_archive->addString('data/test.txt', 'This is the text of the string');
                   5717: 
                   5718: 
                   5719: Method : extract($p_path = "")
                   5720: Description :
                   5721:   This method extract all the content of the archive in the directory
                   5722:   indicated by $p_path.If $p_path is optional, if not set the archive
                   5723:   is extracted in the current directory. 
                   5724:   While extracting a file, if the directory path does not exists it is
                   5725:   created. 
                   5726:   See extractModify() for details and limitations.
                   5727: Arguments :
                   5728:   $p_path : Optional path where the files/dir need to by extracted.
                   5729: Return value :
                   5730:   true on success, false on error.
                   5731: Sample :
                   5732:   $tar_object = new Archive_Tar("tarname.tar");
                   5733:   $tar_object->extract();
                   5734: How it works :
                   5735:   Simply call the extractModify() method with appropriate parameters.
                   5736: 
                   5737: Method : extractModify($p_path, $p_remove_path)
                   5738: Description :
                   5739:   This method extract all the content of the archive in the directory
                   5740:   indicated by $p_path. When relevant the memorized path of the
                   5741:   files/dir can be modified by removing the $p_remove_path path at the
                   5742:   beginning of the file/dir path. 
                   5743:   While extracting a file, if the directory path does not exists it is
                   5744:   created. 
                   5745:   While extracting a file, if the file already exists it is replaced
                   5746:   without looking for last modification date. 
                   5747:   While extracting a file, if the file already exists and is write
                   5748:   protected, the extraction is aborted. 
                   5749:   While extracting a file, if a directory with the same name already
                   5750:   exists, the extraction is aborted. 
                   5751:   While extracting a directory, if a file with the same name already
                   5752:   exists, the extraction is aborted. 
                   5753:   While extracting a file/directory if the destination directory exist
                   5754:   and is write protected, or does not exist but can not be created,
                   5755:   the extraction is aborted. 
                   5756:   If after extraction an extracted file does not show the correct
                   5757:   stored file size, the extraction is aborted. 
                   5758:   When the extraction is aborted, a PEAR error text is set and false
                   5759:   is returned. However the result can be a partial extraction that may
                   5760:   need to be manually cleaned. 
                   5761: Arguments :
                   5762:   $p_path : The path of the directory where the files/dir need to by
                   5763:             extracted. 
                   5764:   $p_remove_path : Part of the memorized path that can be removed if
                   5765:                    present at the beginning of the file/dir path. 
                   5766: Return value :
                   5767:   true on success, false on error.
                   5768: Sample :
                   5769:   // Imagine tarname.tar with files :
                   5770:   //   dev/data/file.txt
                   5771:   //   dev/data/log.txt
                   5772:   //   readme.txt
                   5773:   $tar_object = new Archive_Tar("tarname.tar");
                   5774:   $tar_object->extractModify("install", "dev");
                   5775:   // Files will be extracted there :
                   5776:   //   install/data/file.txt
                   5777:   //   install/data/log.txt
                   5778:   //   install/readme.txt
                   5779: How it works :
                   5780:   Open the archive and call a more generic function that can extract
                   5781:   only a part of the archive or all the archive. 
                   5782:   See extractList() method for more details.
                   5783: 
                   5784: Method : extractInString($p_filename)
                   5785: Description :
                   5786:   This method extract from the archive one file identified by $p_filename.
                   5787:   The return value is a string with the file content, or NULL on error. 
                   5788: Arguments :
                   5789:   $p_filename : The path of the file to extract in a string. 
                   5790: Return value :
                   5791:   a string with the file content or NULL.
                   5792: Sample :
                   5793:   // Imagine tarname.tar with files :
                   5794:   //   dev/data/file.txt
                   5795:   //   dev/data/log.txt
                   5796:   //   dev/readme.txt
                   5797:   $v_archive = & new Archive_Tar('tarname.tar');
                   5798:   $v_archive->setErrorHandling(PEAR_ERROR_PRINT);
                   5799:   $v_string = $v_archive->extractInString('dev/readme.txt');
                   5800:   echo $v_string;
                   5801: 
                   5802: Method : listContent()
                   5803: Description :
                   5804:   This method returns an array of arrays that describe each
                   5805:   file/directory present in the archive. 
                   5806:   The array is not sorted, so it show the position of the file in the
                   5807:   archive. 
                   5808:   The file informations are :
                   5809:     $file[filename] : Name and path of the file/dir.
                   5810:     $file[mode] : File permissions (result of fileperms())
                   5811:     $file[uid] : user id
                   5812:     $file[gid] : group id
                   5813:     $file[size] : filesize
                   5814:     $file[mtime] : Last modification time (result of filemtime())
                   5815:     $file[typeflag] : "" for file, "5" for directory
                   5816: Arguments :
                   5817: Return value :
                   5818:   An array of arrays or 0 on error.
                   5819: Sample :
                   5820:   $tar_object = new Archive_Tar("tarname.tar");
                   5821:   if (($v_list  =  $tar_object->listContent()) != 0)
                   5822:     for ($i=0; $i<sizeof($v_list); $i++)
                   5823:     {
                   5824:       echo "Filename :'".$v_list[$i][filename]."'<br>";
                   5825:       echo " .size :'".$v_list[$i][size]."'<br>";
                   5826:       echo " .mtime :'".$v_list[$i][mtime]."' (".
                   5827:            date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
                   5828:       echo " .mode :'".$v_list[$i][mode]."'<br>";
                   5829:       echo " .uid :'".$v_list[$i][uid]."'<br>";
                   5830:       echo " .gid :'".$v_list[$i][gid]."'<br>";
                   5831:       echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
                   5832:     }
                   5833: How it works :
                   5834:   Call the same function as an extract however with a flag to only go
                   5835:   through the archive without extracting the files. 
                   5836: 
                   5837: Method : extractList($p_filelist, $p_path = "", $p_remove_path = "")
                   5838: Description :
                   5839:   This method extract from the archive only the files indicated in the
                   5840:   $p_filelist. These files are extracted in the current directory or
                   5841:   in the directory indicated by the optional $p_path parameter. 
                   5842:   If indicated the $p_remove_path can be used in the same way as it is
                   5843:   used in extractModify() method. 
                   5844: Arguments :
                   5845:   $p_filelist : An array of filenames and directory names, or a single
                   5846:                 string with names separated by a single blank space. 
                   5847:   $p_path : The path of the directory where the files/dir need to by
                   5848:             extracted. 
                   5849:   $p_remove_path : Part of the memorized path that can be removed if
                   5850:                    present at the beginning of the file/dir path. 
                   5851: Return value :
                   5852:   true on success, false on error.
                   5853: Sample :
                   5854:   // Imagine tarname.tar with files :
                   5855:   //   dev/data/file.txt
                   5856:   //   dev/data/log.txt
                   5857:   //   readme.txt
                   5858:   $tar_object = new Archive_Tar("tarname.tar");
                   5859:   $tar_object->extractList("dev/data/file.txt readme.txt", "install",
                   5860:                            "dev");
                   5861:   // Files will be extracted there :
                   5862:   //   install/data/file.txt
                   5863:   //   install/readme.txt
                   5864: How it works :
                   5865:   Go through the archive and extract only the files present in the
                   5866:   list. 
                   5867: 
                   5868: <?php
                   5869: /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   5870: /**
                   5871:  * PHP Version 5
                   5872:  *
                   5873:  * Copyright (c) 1997-2004 The PHP Group
                   5874:  *
                   5875:  * This source file is subject to version 3.0 of the PHP license,
                   5876:  * that is bundled with this package in the file LICENSE, and is
                   5877:  * available through the world-wide-web at the following url:
                   5878:  * http://www.php.net/license/3_0.txt.
                   5879:  * If you did not receive a copy of the PHP license and are unable to
                   5880:  * obtain it through the world-wide-web, please send a note to
                   5881:  * license@php.net so we can mail you a copy immediately.
                   5882:  *
                   5883:  * @category Console
                   5884:  * @package  Console_Getopt
                   5885:  * @author   Andrei Zmievski <andrei@php.net>
                   5886:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   5887:  * @version  CVS: $Id: Getopt.php 306067 2010-12-08 00:13:31Z dufuz $
                   5888:  * @link     http://pear.php.net/package/Console_Getopt
                   5889:  */
                   5890: 
                   5891: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   5892: 
                   5893: /**
                   5894:  * Command-line options parsing class.
                   5895:  *
                   5896:  * @category Console
                   5897:  * @package  Console_Getopt
                   5898:  * @author   Andrei Zmievski <andrei@php.net>
                   5899:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   5900:  * @link     http://pear.php.net/package/Console_Getopt
                   5901:  */
                   5902: class Console_Getopt
                   5903: {
                   5904: 
                   5905:     /**
                   5906:      * Parses the command-line options.
                   5907:      *
                   5908:      * The first parameter to this function should be the list of command-line
                   5909:      * arguments without the leading reference to the running program.
                   5910:      *
                   5911:      * The second parameter is a string of allowed short options. Each of the
                   5912:      * option letters can be followed by a colon ':' to specify that the option
                   5913:      * requires an argument, or a double colon '::' to specify that the option
                   5914:      * takes an optional argument.
                   5915:      *
                   5916:      * The third argument is an optional array of allowed long options. The
                   5917:      * leading '--' should not be included in the option name. Options that
                   5918:      * require an argument should be followed by '=', and options that take an
                   5919:      * option argument should be followed by '=='.
                   5920:      *
                   5921:      * The return value is an array of two elements: the list of parsed
                   5922:      * options and the list of non-option command-line arguments. Each entry in
                   5923:      * the list of parsed options is a pair of elements - the first one
                   5924:      * specifies the option, and the second one specifies the option argument,
                   5925:      * if there was one.
                   5926:      *
                   5927:      * Long and short options can be mixed.
                   5928:      *
                   5929:      * Most of the semantics of this function are based on GNU getopt_long().
                   5930:      *
                   5931:      * @param array  $args          an array of command-line arguments
                   5932:      * @param string $short_options specifies the list of allowed short options
                   5933:      * @param array  $long_options  specifies the list of allowed long options
                   5934:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   5935:      *
                   5936:      * @return array two-element array containing the list of parsed options and
                   5937:      * the non-option arguments
                   5938:      * @access public
                   5939:      */
                   5940:     function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
                   5941:     {
                   5942:         return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
                   5943:     }
                   5944: 
                   5945:     /**
                   5946:      * This function expects $args to start with the script name (POSIX-style).
                   5947:      * Preserved for backwards compatibility.
                   5948:      *
                   5949:      * @param array  $args          an array of command-line arguments
                   5950:      * @param string $short_options specifies the list of allowed short options
                   5951:      * @param array  $long_options  specifies the list of allowed long options
                   5952:      *
                   5953:      * @see getopt2()
                   5954:      * @return array two-element array containing the list of parsed options and
                   5955:      * the non-option arguments
                   5956:      */
                   5957:     function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
                   5958:     {
                   5959:         return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
                   5960:     }
                   5961: 
                   5962:     /**
                   5963:      * The actual implementation of the argument parsing code.
                   5964:      *
                   5965:      * @param int    $version       Version to use
                   5966:      * @param array  $args          an array of command-line arguments
                   5967:      * @param string $short_options specifies the list of allowed short options
                   5968:      * @param array  $long_options  specifies the list of allowed long options
                   5969:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   5970:      *
                   5971:      * @return array
                   5972:      */
                   5973:     function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
                   5974:     {
                   5975:         // in case you pass directly readPHPArgv() as the first arg
                   5976:         if (PEAR::isError($args)) {
                   5977:             return $args;
                   5978:         }
                   5979: 
                   5980:         if (empty($args)) {
                   5981:             return array(array(), array());
                   5982:         }
                   5983: 
                   5984:         $non_opts = $opts = array();
                   5985: 
                   5986:         settype($args, 'array');
                   5987: 
                   5988:         if ($long_options) {
                   5989:             sort($long_options);
                   5990:         }
                   5991: 
                   5992:         /*
                   5993:          * Preserve backwards compatibility with callers that relied on
                   5994:          * erroneous POSIX fix.
                   5995:          */
                   5996:         if ($version < 2) {
                   5997:             if (isset($args[0]{0}) && $args[0]{0} != '-') {
                   5998:                 array_shift($args);
                   5999:             }
                   6000:         }
                   6001: 
                   6002:         reset($args);
                   6003:         while (list($i, $arg) = each($args)) {
                   6004:             /* The special element '--' means explicit end of
                   6005:                options. Treat the rest of the arguments as non-options
                   6006:                and end the loop. */
                   6007:             if ($arg == '--') {
                   6008:                 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
                   6009:                 break;
                   6010:             }
                   6011: 
                   6012:             if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
                   6013:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6014:                 break;
                   6015:             } elseif (strlen($arg) > 1 && $arg{1} == '-') {
                   6016:                 $error = Console_Getopt::_parseLongOption(substr($arg, 2),
                   6017:                                                           $long_options,
                   6018:                                                           $opts,
                   6019:                                                           $args,
                   6020:                                                           $skip_unknown);
                   6021:                 if (PEAR::isError($error)) {
                   6022:                     return $error;
                   6023:                 }
                   6024:             } elseif ($arg == '-') {
                   6025:                 // - is stdin
                   6026:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6027:                 break;
                   6028:             } else {
                   6029:                 $error = Console_Getopt::_parseShortOption(substr($arg, 1),
                   6030:                                                            $short_options,
                   6031:                                                            $opts,
                   6032:                                                            $args,
                   6033:                                                            $skip_unknown);
                   6034:                 if (PEAR::isError($error)) {
                   6035:                     return $error;
                   6036:                 }
                   6037:             }
                   6038:         }
                   6039: 
                   6040:         return array($opts, $non_opts);
                   6041:     }
                   6042: 
                   6043:     /**
                   6044:      * Parse short option
                   6045:      *
                   6046:      * @param string     $arg           Argument
                   6047:      * @param string[]   $short_options Available short options
                   6048:      * @param string[][] &$opts
                   6049:      * @param string[]   &$args
                   6050:      * @param boolean    $skip_unknown suppresses Console_Getopt: unrecognized option
                   6051:      *
                   6052:      * @access private
                   6053:      * @return void
                   6054:      */
                   6055:     function _parseShortOption($arg, $short_options, &$opts, &$args, $skip_unknown)
                   6056:     {
                   6057:         for ($i = 0; $i < strlen($arg); $i++) {
                   6058:             $opt     = $arg{$i};
                   6059:             $opt_arg = null;
                   6060: 
                   6061:             /* Try to find the short option in the specifier string. */
                   6062:             if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') {
                   6063:                 if ($skip_unknown === true) {
                   6064:                     break;
                   6065:                 }
                   6066: 
                   6067:                 $msg = "Console_Getopt: unrecognized option -- $opt";
                   6068:                 return PEAR::raiseError($msg);
                   6069:             }
                   6070: 
                   6071:             if (strlen($spec) > 1 && $spec{1} == ':') {
                   6072:                 if (strlen($spec) > 2 && $spec{2} == ':') {
                   6073:                     if ($i + 1 < strlen($arg)) {
                   6074:                         /* Option takes an optional argument. Use the remainder of
                   6075:                            the arg string if there is anything left. */
                   6076:                         $opts[] = array($opt, substr($arg, $i + 1));
                   6077:                         break;
                   6078:                     }
                   6079:                 } else {
                   6080:                     /* Option requires an argument. Use the remainder of the arg
                   6081:                        string if there is anything left. */
                   6082:                     if ($i + 1 < strlen($arg)) {
                   6083:                         $opts[] = array($opt,  substr($arg, $i + 1));
                   6084:                         break;
                   6085:                     } else if (list(, $opt_arg) = each($args)) {
                   6086:                         /* Else use the next argument. */;
                   6087:                         if (Console_Getopt::_isShortOpt($opt_arg)
                   6088:                             || Console_Getopt::_isLongOpt($opt_arg)) {
                   6089:                             $msg = "option requires an argument --$opt";
                   6090:                             return PEAR::raiseError("Console_Getopt:" . $msg);
                   6091:                         }
                   6092:                     } else {
                   6093:                         $msg = "option requires an argument --$opt";
                   6094:                         return PEAR::raiseError("Console_Getopt:" . $msg);
                   6095:                     }
                   6096:                 }
                   6097:             }
                   6098: 
                   6099:             $opts[] = array($opt, $opt_arg);
                   6100:         }
                   6101:     }
                   6102: 
                   6103:     /**
                   6104:      * Checks if an argument is a short option
                   6105:      *
                   6106:      * @param string $arg Argument to check
                   6107:      *
                   6108:      * @access private
                   6109:      * @return bool
                   6110:      */
                   6111:     function _isShortOpt($arg)
                   6112:     {
                   6113:         return strlen($arg) == 2 && $arg[0] == '-'
                   6114:                && preg_match('/[a-zA-Z]/', $arg[1]);
                   6115:     }
                   6116: 
                   6117:     /**
                   6118:      * Checks if an argument is a long option
                   6119:      *
                   6120:      * @param string $arg Argument to check
                   6121:      *
                   6122:      * @access private
                   6123:      * @return bool
                   6124:      */
                   6125:     function _isLongOpt($arg)
                   6126:     {
                   6127:         return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
                   6128:                preg_match('/[a-zA-Z]+$/', substr($arg, 2));
                   6129:     }
                   6130: 
                   6131:     /**
                   6132:      * Parse long option
                   6133:      *
                   6134:      * @param string     $arg          Argument
                   6135:      * @param string[]   $long_options Available long options
                   6136:      * @param string[][] &$opts
                   6137:      * @param string[]   &$args
                   6138:      *
                   6139:      * @access private
                   6140:      * @return void|PEAR_Error
                   6141:      */
                   6142:     function _parseLongOption($arg, $long_options, &$opts, &$args, $skip_unknown)
                   6143:     {
                   6144:         @list($opt, $opt_arg) = explode('=', $arg, 2);
                   6145: 
                   6146:         $opt_len = strlen($opt);
                   6147: 
                   6148:         for ($i = 0; $i < count($long_options); $i++) {
                   6149:             $long_opt  = $long_options[$i];
                   6150:             $opt_start = substr($long_opt, 0, $opt_len);
                   6151: 
                   6152:             $long_opt_name = str_replace('=', '', $long_opt);
                   6153: 
                   6154:             /* Option doesn't match. Go on to the next one. */
                   6155:             if ($long_opt_name != $opt) {
                   6156:                 continue;
                   6157:             }
                   6158: 
                   6159:             $opt_rest = substr($long_opt, $opt_len);
                   6160: 
                   6161:             /* Check that the options uniquely matches one of the allowed
                   6162:                options. */
                   6163:             if ($i + 1 < count($long_options)) {
                   6164:                 $next_option_rest = substr($long_options[$i + 1], $opt_len);
                   6165:             } else {
                   6166:                 $next_option_rest = '';
                   6167:             }
                   6168: 
                   6169:             if ($opt_rest != '' && $opt{0} != '=' &&
                   6170:                 $i + 1 < count($long_options) &&
                   6171:                 $opt == substr($long_options[$i+1], 0, $opt_len) &&
                   6172:                 $next_option_rest != '' &&
                   6173:                 $next_option_rest{0} != '=') {
                   6174: 
                   6175:                 $msg = "Console_Getopt: option --$opt is ambiguous";
                   6176:                 return PEAR::raiseError($msg);
                   6177:             }
                   6178: 
                   6179:             if (substr($long_opt, -1) == '=') {
                   6180:                 if (substr($long_opt, -2) != '==') {
                   6181:                     /* Long option requires an argument.
                   6182:                        Take the next argument if one wasn't specified. */;
                   6183:                     if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
                   6184:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6185:                         return PEAR::raiseError($msg);
                   6186:                     }
                   6187: 
                   6188:                     if (Console_Getopt::_isShortOpt($opt_arg)
                   6189:                         || Console_Getopt::_isLongOpt($opt_arg)) {
                   6190:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6191:                         return PEAR::raiseError($msg);
                   6192:                     }
                   6193:                 }
                   6194:             } else if ($opt_arg) {
                   6195:                 $msg = "Console_Getopt: option --$opt doesn't allow an argument";
                   6196:                 return PEAR::raiseError($msg);
                   6197:             }
                   6198: 
                   6199:             $opts[] = array('--' . $opt, $opt_arg);
                   6200:             return;
                   6201:         }
                   6202: 
                   6203:         if ($skip_unknown === true) {
                   6204:             return;
                   6205:         }
                   6206: 
                   6207:         return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
                   6208:     }
                   6209: 
                   6210:     /**
                   6211:      * Safely read the $argv PHP array across different PHP configurations.
                   6212:      * Will take care on register_globals and register_argc_argv ini directives
                   6213:      *
                   6214:      * @access public
                   6215:      * @return mixed the $argv PHP array or PEAR error if not registered
                   6216:      */
                   6217:     function readPHPArgv()
                   6218:     {
                   6219:         global $argv;
                   6220:         if (!is_array($argv)) {
                   6221:             if (!@is_array($_SERVER['argv'])) {
                   6222:                 if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
                   6223:                     $msg = "Could not read cmd args (register_argc_argv=Off?)";
                   6224:                     return PEAR::raiseError("Console_Getopt: " . $msg);
                   6225:                 }
                   6226:                 return $GLOBALS['HTTP_SERVER_VARS']['argv'];
                   6227:             }
                   6228:             return $_SERVER['argv'];
                   6229:         }
                   6230:         return $argv;
                   6231:     }
                   6232: 
                   6233: }package.xml0000644000076500000240000001132511500756375012161 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8"?>
                   6234: <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">
                   6235:  <name>Console_Getopt</name>
                   6236:  <channel>pear.php.net</channel>
                   6237:  <summary>Command-line option parser</summary>
                   6238:  <description>This is a PHP implementation of &quot;getopt&quot; supporting both
                   6239: short and long options.</description>
                   6240:  <lead>
                   6241:   <name>Andrei Zmievski</name>
                   6242:   <user>andrei</user>
                   6243:   <email>andrei@php.net</email>
                   6244:   <active>yes</active>
                   6245:  </lead>
                   6246:  <developer>
                   6247:   <name>Stig Bakken</name>
                   6248:   <user>ssb</user>
                   6249:   <email>stig@php.net</email>
                   6250:   <active>no</active>
                   6251:  </developer>
                   6252:  <helper>
                   6253:   <name>Greg Beaver</name>
                   6254:   <user>cellog</user>
                   6255:   <email>cellog@php.net</email>
                   6256:   <active>yes</active>
                   6257:  </helper>
                   6258:  <date>2010-12-11</date>
                   6259:  <time>20:20:13</time>
                   6260:  <version>
                   6261:   <release>1.3.0</release>
                   6262:   <api>1.3.0</api>
                   6263:  </version>
                   6264:  <stability>
                   6265:   <release>stable</release>
                   6266:   <api>stable</api>
                   6267:  </stability>
                   6268:  <license uri="http://www.php.net/license">PHP License</license>
                   6269:  <notes>
                   6270: * Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]
                   6271:  </notes>
                   6272:  <contents>
                   6273:   <dir name="/">
                   6274:    <file md5sum="ed666da6b1c5d01c3ecbf1f588a70a60" name="Console/Getopt.php" role="php" />
                   6275:   </dir>
                   6276:  </contents>
                   6277:  <compatible>
                   6278:   <name>PEAR</name>
                   6279:   <channel>pear.php.net</channel>
                   6280:   <min>1.4.0</min>
                   6281:   <max>1.10.0</max>
                   6282:  </compatible>
                   6283:  <dependencies>
                   6284:   <required>
                   6285:    <php>
                   6286:     <min>4.3.0</min>
                   6287:    </php>
                   6288:    <pearinstaller>
                   6289:     <min>1.9.1</min>
                   6290:    </pearinstaller>
                   6291:   </required>
                   6292:  </dependencies>
                   6293:  <phprelease />
                   6294:  <changelog>
                   6295:   <release>
                   6296:    <date>2007-06-12</date>
                   6297:    <version>
                   6298:     <release>1.2.3</release>
                   6299:     <api>1.2.1</api>
                   6300:    </version>
                   6301:    <stability>
                   6302:     <release>stable</release>
                   6303:     <api>stable</api>
                   6304:    </stability>
                   6305:    <license uri="http://www.php.net/license">PHP License</license>
                   6306:    <notes>
                   6307: * fix Bug #11068: No way to read plain &quot;-&quot; option [cardoe]
                   6308:    </notes>
                   6309:   </release>
                   6310:   <release>
                   6311:    <version>
                   6312:     <release>1.2.2</release>
                   6313:     <api>1.2.1</api>
                   6314:    </version>
                   6315:    <stability>
                   6316:     <release>stable</release>
                   6317:     <api>stable</api>
                   6318:    </stability>
                   6319:    <date>2007-02-17</date>
                   6320:    <license uri="http://www.php.net/license">PHP License</license>
                   6321:    <notes>
                   6322: * fix Bug #4475: An ambiguous error occurred when specifying similar longoption name.
                   6323: * fix Bug #10055: Not failing properly on short options missing required values
                   6324:    </notes>
                   6325:   </release>
                   6326:   <release>
                   6327:    <version>
                   6328:     <release>1.2.1</release>
                   6329:     <api>1.2.1</api>
                   6330:    </version>
                   6331:    <stability>
                   6332:     <release>stable</release>
                   6333:     <api>stable</api>
                   6334:    </stability>
                   6335:    <date>2006-12-08</date>
                   6336:    <license uri="http://www.php.net/license">PHP License</license>
                   6337:    <notes>
                   6338: Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag)
                   6339:    </notes>
                   6340:   </release>
                   6341:   <release>
                   6342:    <version>
                   6343:     <release>1.2</release>
                   6344:     <api>1.2</api>
                   6345:    </version>
                   6346:    <stability>
                   6347:     <release>stable</release>
                   6348:     <api>stable</api>
                   6349:    </stability>
                   6350:    <date>2003-12-11</date>
                   6351:    <license uri="http://www.php.net/license">PHP License</license>
                   6352:    <notes>
                   6353: Fix to preserve BC with 1.0 and allow correct behaviour for new users
                   6354:    </notes>
                   6355:   </release>
                   6356:   <release>
                   6357:    <version>
                   6358:     <release>1.0</release>
                   6359:     <api>1.0</api>
                   6360:    </version>
                   6361:    <stability>
                   6362:     <release>stable</release>
                   6363:     <api>stable</api>
                   6364:    </stability>
                   6365:    <date>2002-09-13</date>
                   6366:    <license uri="http://www.php.net/license">PHP License</license>
                   6367:    <notes>
                   6368: Stable release
                   6369:    </notes>
                   6370:   </release>
                   6371:   <release>
                   6372:    <version>
                   6373:     <release>0.11</release>
                   6374:     <api>0.11</api>
                   6375:    </version>
                   6376:    <stability>
                   6377:     <release>beta</release>
                   6378:     <api>beta</api>
                   6379:    </stability>
                   6380:    <date>2002-05-26</date>
                   6381:    <license uri="http://www.php.net/license">PHP License</license>
                   6382:    <notes>
                   6383: POSIX getopt compatibility fix: treat first element of args
                   6384:         array as command name
                   6385:    </notes>
                   6386:   </release>
                   6387:   <release>
                   6388:    <version>
                   6389:     <release>0.10</release>
                   6390:     <api>0.10</api>
                   6391:    </version>
                   6392:    <stability>
                   6393:     <release>beta</release>
                   6394:     <api>beta</api>
                   6395:    </stability>
                   6396:    <date>2002-05-12</date>
                   6397:    <license uri="http://www.php.net/license">PHP License</license>
                   6398:    <notes>
                   6399: Packaging fix
                   6400:    </notes>
                   6401:   </release>
                   6402:   <release>
                   6403:    <version>
                   6404:     <release>0.9</release>
                   6405:     <api>0.9</api>
                   6406:    </version>
                   6407:    <stability>
                   6408:     <release>beta</release>
                   6409:     <api>beta</api>
                   6410:    </stability>
                   6411:    <date>2002-05-12</date>
                   6412:    <license uri="http://www.php.net/license">PHP License</license>
                   6413:    <notes>
                   6414: Initial release
                   6415:    </notes>
                   6416:   </release>
                   6417:  </changelog>
                   6418: </package>
                   6419: Console_Getopt-1.3.0/Console/Getopt.php0000644000076500000240000003223511500756375017005 0ustar  helgistaff<?php
                   6420: /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   6421: /**
                   6422:  * PHP Version 5
                   6423:  *
                   6424:  * Copyright (c) 1997-2004 The PHP Group
                   6425:  *
                   6426:  * This source file is subject to version 3.0 of the PHP license,
                   6427:  * that is bundled with this package in the file LICENSE, and is
                   6428:  * available through the world-wide-web at the following url:
                   6429:  * http://www.php.net/license/3_0.txt.
                   6430:  * If you did not receive a copy of the PHP license and are unable to
                   6431:  * obtain it through the world-wide-web, please send a note to
                   6432:  * license@php.net so we can mail you a copy immediately.
                   6433:  *
                   6434:  * @category Console
                   6435:  * @package  Console_Getopt
                   6436:  * @author   Andrei Zmievski <andrei@php.net>
                   6437:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6438:  * @version  CVS: $Id: Getopt.php 306067 2010-12-08 00:13:31Z dufuz $
                   6439:  * @link     http://pear.php.net/package/Console_Getopt
                   6440:  */
                   6441: 
                   6442: require_once 'PEAR.php';
                   6443: 
                   6444: /**
                   6445:  * Command-line options parsing class.
                   6446:  *
                   6447:  * @category Console
                   6448:  * @package  Console_Getopt
                   6449:  * @author   Andrei Zmievski <andrei@php.net>
                   6450:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6451:  * @link     http://pear.php.net/package/Console_Getopt
                   6452:  */
                   6453: class Console_Getopt
                   6454: {
                   6455: 
                   6456:     /**
                   6457:      * Parses the command-line options.
                   6458:      *
                   6459:      * The first parameter to this function should be the list of command-line
                   6460:      * arguments without the leading reference to the running program.
                   6461:      *
                   6462:      * The second parameter is a string of allowed short options. Each of the
                   6463:      * option letters can be followed by a colon ':' to specify that the option
                   6464:      * requires an argument, or a double colon '::' to specify that the option
                   6465:      * takes an optional argument.
                   6466:      *
                   6467:      * The third argument is an optional array of allowed long options. The
                   6468:      * leading '--' should not be included in the option name. Options that
                   6469:      * require an argument should be followed by '=', and options that take an
                   6470:      * option argument should be followed by '=='.
                   6471:      *
                   6472:      * The return value is an array of two elements: the list of parsed
                   6473:      * options and the list of non-option command-line arguments. Each entry in
                   6474:      * the list of parsed options is a pair of elements - the first one
                   6475:      * specifies the option, and the second one specifies the option argument,
                   6476:      * if there was one.
                   6477:      *
                   6478:      * Long and short options can be mixed.
                   6479:      *
                   6480:      * Most of the semantics of this function are based on GNU getopt_long().
                   6481:      *
                   6482:      * @param array  $args          an array of command-line arguments
                   6483:      * @param string $short_options specifies the list of allowed short options
                   6484:      * @param array  $long_options  specifies the list of allowed long options
                   6485:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6486:      *
                   6487:      * @return array two-element array containing the list of parsed options and
                   6488:      * the non-option arguments
                   6489:      * @access public
                   6490:      */
                   6491:     function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
                   6492:     {
                   6493:         return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
                   6494:     }
                   6495: 
                   6496:     /**
                   6497:      * This function expects $args to start with the script name (POSIX-style).
                   6498:      * Preserved for backwards compatibility.
                   6499:      *
                   6500:      * @param array  $args          an array of command-line arguments
                   6501:      * @param string $short_options specifies the list of allowed short options
                   6502:      * @param array  $long_options  specifies the list of allowed long options
                   6503:      *
                   6504:      * @see getopt2()
                   6505:      * @return array two-element array containing the list of parsed options and
                   6506:      * the non-option arguments
                   6507:      */
                   6508:     function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
                   6509:     {
                   6510:         return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
                   6511:     }
                   6512: 
                   6513:     /**
                   6514:      * The actual implementation of the argument parsing code.
                   6515:      *
                   6516:      * @param int    $version       Version to use
                   6517:      * @param array  $args          an array of command-line arguments
                   6518:      * @param string $short_options specifies the list of allowed short options
                   6519:      * @param array  $long_options  specifies the list of allowed long options
                   6520:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6521:      *
                   6522:      * @return array
                   6523:      */
                   6524:     function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
                   6525:     {
                   6526:         // in case you pass directly readPHPArgv() as the first arg
                   6527:         if (PEAR::isError($args)) {
                   6528:             return $args;
                   6529:         }
                   6530: 
                   6531:         if (empty($args)) {
                   6532:             return array(array(), array());
                   6533:         }
                   6534: 
                   6535:         $non_opts = $opts = array();
                   6536: 
                   6537:         settype($args, 'array');
                   6538: 
                   6539:         if ($long_options) {
                   6540:             sort($long_options);
                   6541:         }
                   6542: 
                   6543:         /*
                   6544:          * Preserve backwards compatibility with callers that relied on
                   6545:          * erroneous POSIX fix.
                   6546:          */
                   6547:         if ($version < 2) {
                   6548:             if (isset($args[0]{0}) && $args[0]{0} != '-') {
                   6549:                 array_shift($args);
                   6550:             }
                   6551:         }
                   6552: 
                   6553:         reset($args);
                   6554:         while (list($i, $arg) = each($args)) {
                   6555:             /* The special element '--' means explicit end of
                   6556:                options. Treat the rest of the arguments as non-options
                   6557:                and end the loop. */
                   6558:             if ($arg == '--') {
                   6559:                 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
                   6560:                 break;
                   6561:             }
                   6562: 
                   6563:             if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
                   6564:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6565:                 break;
                   6566:             } elseif (strlen($arg) > 1 && $arg{1} == '-') {
                   6567:                 $error = Console_Getopt::_parseLongOption(substr($arg, 2),
                   6568:                                                           $long_options,
                   6569:                                                           $opts,
                   6570:                                                           $args,
                   6571:                                                           $skip_unknown);
                   6572:                 if (PEAR::isError($error)) {
                   6573:                     return $error;
                   6574:                 }
                   6575:             } elseif ($arg == '-') {
                   6576:                 // - is stdin
                   6577:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6578:                 break;
                   6579:             } else {
                   6580:                 $error = Console_Getopt::_parseShortOption(substr($arg, 1),
                   6581:                                                            $short_options,
                   6582:                                                            $opts,
                   6583:                                                            $args,
                   6584:                                                            $skip_unknown);
                   6585:                 if (PEAR::isError($error)) {
                   6586:                     return $error;
                   6587:                 }
                   6588:             }
                   6589:         }
                   6590: 
                   6591:         return array($opts, $non_opts);
                   6592:     }
                   6593: 
                   6594:     /**
                   6595:      * Parse short option
                   6596:      *
                   6597:      * @param string     $arg           Argument
                   6598:      * @param string[]   $short_options Available short options
                   6599:      * @param string[][] &$opts
                   6600:      * @param string[]   &$args
                   6601:      * @param boolean    $skip_unknown suppresses Console_Getopt: unrecognized option
                   6602:      *
                   6603:      * @access private
                   6604:      * @return void
                   6605:      */
                   6606:     function _parseShortOption($arg, $short_options, &$opts, &$args, $skip_unknown)
                   6607:     {
                   6608:         for ($i = 0; $i < strlen($arg); $i++) {
                   6609:             $opt     = $arg{$i};
                   6610:             $opt_arg = null;
                   6611: 
                   6612:             /* Try to find the short option in the specifier string. */
                   6613:             if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') {
                   6614:                 if ($skip_unknown === true) {
                   6615:                     break;
                   6616:                 }
                   6617: 
                   6618:                 $msg = "Console_Getopt: unrecognized option -- $opt";
                   6619:                 return PEAR::raiseError($msg);
                   6620:             }
                   6621: 
                   6622:             if (strlen($spec) > 1 && $spec{1} == ':') {
                   6623:                 if (strlen($spec) > 2 && $spec{2} == ':') {
                   6624:                     if ($i + 1 < strlen($arg)) {
                   6625:                         /* Option takes an optional argument. Use the remainder of
                   6626:                            the arg string if there is anything left. */
                   6627:                         $opts[] = array($opt, substr($arg, $i + 1));
                   6628:                         break;
                   6629:                     }
                   6630:                 } else {
                   6631:                     /* Option requires an argument. Use the remainder of the arg
                   6632:                        string if there is anything left. */
                   6633:                     if ($i + 1 < strlen($arg)) {
                   6634:                         $opts[] = array($opt,  substr($arg, $i + 1));
                   6635:                         break;
                   6636:                     } else if (list(, $opt_arg) = each($args)) {
                   6637:                         /* Else use the next argument. */;
                   6638:                         if (Console_Getopt::_isShortOpt($opt_arg)
                   6639:                             || Console_Getopt::_isLongOpt($opt_arg)) {
                   6640:                             $msg = "option requires an argument --$opt";
                   6641:                             return PEAR::raiseError("Console_Getopt:" . $msg);
                   6642:                         }
                   6643:                     } else {
                   6644:                         $msg = "option requires an argument --$opt";
                   6645:                         return PEAR::raiseError("Console_Getopt:" . $msg);
                   6646:                     }
                   6647:                 }
                   6648:             }
                   6649: 
                   6650:             $opts[] = array($opt, $opt_arg);
                   6651:         }
                   6652:     }
                   6653: 
                   6654:     /**
                   6655:      * Checks if an argument is a short option
                   6656:      *
                   6657:      * @param string $arg Argument to check
                   6658:      *
                   6659:      * @access private
                   6660:      * @return bool
                   6661:      */
                   6662:     function _isShortOpt($arg)
                   6663:     {
                   6664:         return strlen($arg) == 2 && $arg[0] == '-'
                   6665:                && preg_match('/[a-zA-Z]/', $arg[1]);
                   6666:     }
                   6667: 
                   6668:     /**
                   6669:      * Checks if an argument is a long option
                   6670:      *
                   6671:      * @param string $arg Argument to check
                   6672:      *
                   6673:      * @access private
                   6674:      * @return bool
                   6675:      */
                   6676:     function _isLongOpt($arg)
                   6677:     {
                   6678:         return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
                   6679:                preg_match('/[a-zA-Z]+$/', substr($arg, 2));
                   6680:     }
                   6681: 
                   6682:     /**
                   6683:      * Parse long option
                   6684:      *
                   6685:      * @param string     $arg          Argument
                   6686:      * @param string[]   $long_options Available long options
                   6687:      * @param string[][] &$opts
                   6688:      * @param string[]   &$args
                   6689:      *
                   6690:      * @access private
                   6691:      * @return void|PEAR_Error
                   6692:      */
                   6693:     function _parseLongOption($arg, $long_options, &$opts, &$args, $skip_unknown)
                   6694:     {
                   6695:         @list($opt, $opt_arg) = explode('=', $arg, 2);
                   6696: 
                   6697:         $opt_len = strlen($opt);
                   6698: 
                   6699:         for ($i = 0; $i < count($long_options); $i++) {
                   6700:             $long_opt  = $long_options[$i];
                   6701:             $opt_start = substr($long_opt, 0, $opt_len);
                   6702: 
                   6703:             $long_opt_name = str_replace('=', '', $long_opt);
                   6704: 
                   6705:             /* Option doesn't match. Go on to the next one. */
                   6706:             if ($long_opt_name != $opt) {
                   6707:                 continue;
                   6708:             }
                   6709: 
                   6710:             $opt_rest = substr($long_opt, $opt_len);
                   6711: 
                   6712:             /* Check that the options uniquely matches one of the allowed
                   6713:                options. */
                   6714:             if ($i + 1 < count($long_options)) {
                   6715:                 $next_option_rest = substr($long_options[$i + 1], $opt_len);
                   6716:             } else {
                   6717:                 $next_option_rest = '';
                   6718:             }
                   6719: 
                   6720:             if ($opt_rest != '' && $opt{0} != '=' &&
                   6721:                 $i + 1 < count($long_options) &&
                   6722:                 $opt == substr($long_options[$i+1], 0, $opt_len) &&
                   6723:                 $next_option_rest != '' &&
                   6724:                 $next_option_rest{0} != '=') {
                   6725: 
                   6726:                 $msg = "Console_Getopt: option --$opt is ambiguous";
                   6727:                 return PEAR::raiseError($msg);
                   6728:             }
                   6729: 
                   6730:             if (substr($long_opt, -1) == '=') {
                   6731:                 if (substr($long_opt, -2) != '==') {
                   6732:                     /* Long option requires an argument.
                   6733:                        Take the next argument if one wasn't specified. */;
                   6734:                     if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
                   6735:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6736:                         return PEAR::raiseError($msg);
                   6737:                     }
                   6738: 
                   6739:                     if (Console_Getopt::_isShortOpt($opt_arg)
                   6740:                         || Console_Getopt::_isLongOpt($opt_arg)) {
                   6741:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6742:                         return PEAR::raiseError($msg);
                   6743:                     }
                   6744:                 }
                   6745:             } else if ($opt_arg) {
                   6746:                 $msg = "Console_Getopt: option --$opt doesn't allow an argument";
                   6747:                 return PEAR::raiseError($msg);
                   6748:             }
                   6749: 
                   6750:             $opts[] = array('--' . $opt, $opt_arg);
                   6751:             return;
                   6752:         }
                   6753: 
                   6754:         if ($skip_unknown === true) {
                   6755:             return;
                   6756:         }
                   6757: 
                   6758:         return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
                   6759:     }
                   6760: 
                   6761:     /**
                   6762:      * Safely read the $argv PHP array across different PHP configurations.
                   6763:      * Will take care on register_globals and register_argc_argv ini directives
                   6764:      *
                   6765:      * @access public
                   6766:      * @return mixed the $argv PHP array or PEAR error if not registered
                   6767:      */
                   6768:     function readPHPArgv()
                   6769:     {
                   6770:         global $argv;
                   6771:         if (!is_array($argv)) {
                   6772:             if (!@is_array($_SERVER['argv'])) {
                   6773:                 if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
                   6774:                     $msg = "Could not read cmd args (register_argc_argv=Off?)";
                   6775:                     return PEAR::raiseError("Console_Getopt: " . $msg);
                   6776:                 }
                   6777:                 return $GLOBALS['HTTP_SERVER_VARS']['argv'];
                   6778:             }
                   6779:             return $_SERVER['argv'];
                   6780:         }
                   6781:         return $argv;
                   6782:     }
                   6783: 
                   6784: }<?php
                   6785: while (@ob_end_flush());
                   6786: /* $Id: install-pear.php 308763 2011-02-28 16:18:46Z dufuz $ */
                   6787: 
                   6788: error_reporting(1803);
                   6789: 
                   6790: if (ini_get('date.timezone') === '' && function_exists('date_default_timezone_set')) {
                   6791:     date_default_timezone_set('UTC');
                   6792: }
                   6793: 
                   6794: $pear_dir = dirname(__FILE__);
                   6795: ini_set('include_path', '');
                   6796: if (function_exists('mb_internal_encoding')) {
                   6797:     mb_internal_encoding('ASCII');
                   6798: }
                   6799: set_time_limit(0);
                   6800: include_once 'phar://install-pear-nozlib.phar/PEAR.php';
                   6801: include_once 'phar://install-pear-nozlib.phar/PEAR/Installer.php';
                   6802: include_once 'phar://install-pear-nozlib.phar/PEAR/Registry.php';
                   6803: include_once 'phar://install-pear-nozlib.phar/PEAR/PackageFile.php';
                   6804: include_once 'phar://install-pear-nozlib.phar/PEAR/Downloader/Package.php';
                   6805: include_once 'phar://install-pear-nozlib.phar/PEAR/Frontend.php';
                   6806: $a = true;
                   6807: if (!PEAR::loadExtension('xml')) {
                   6808:     $a = false;
                   6809:     echo "[PEAR] xml extension is required\n";
                   6810: }
                   6811: if (!PEAR::loadExtension('pcre')) {
                   6812:     $a = false;
                   6813:     echo "[PEAR] pcre extension is required\n";
                   6814: }
                   6815: if (!$a) {
                   6816:     return -1;
                   6817: }
                   6818: 
                   6819: $force = false;
                   6820: $install_files = array('Archive_Tar' => 'phar://install-pear-nozlib.phar/Archive_Tar-1.3.7.tar',
                   6821: 'Console_Getopt' => 'phar://install-pear-nozlib.phar/Console_Getopt-1.3.0.tar',
                   6822: 'Structures_Graph' => 'phar://install-pear-nozlib.phar/Structures_Graph-1.0.4.tar',
                   6823: 'XML_Util' => 'phar://install-pear-nozlib.phar/XML_Util-1.2.1.tar',
                   6824: 'PEAR' => 'phar://install-pear-nozlib.phar/PEAR-1.9.4.tar',
                   6825: );
                   6826: array_shift($argv);
                   6827: $debug = false;
                   6828: for ($i = 0; $i < sizeof($argv); $i++) {
                   6829:     $arg = $argv[$i];
                   6830:     $bn = basename($arg);
                   6831:     if (preg_match('/package-(.*)\.xml$/', $bn, $matches) ||
                   6832:         preg_match('/([A-Za-z0-9_:]+)-.*\.(tar|tgz)$/', $bn, $matches)) {
                   6833:         $install_files[$matches[1]] = $arg;
                   6834:     } elseif ($arg == '-a') {
                   6835:         $cache_dir = $argv[$i+1];
                   6836:         $i++;
                   6837:     } elseif ($arg == '--force') {
                   6838:         $force = true;
                   6839:     } elseif ($arg == '-dp') {
                   6840:         $prefix = $argv[$i+1];
                   6841:         $i++;
                   6842:     } elseif ($arg == '-ds') {
                   6843:         $suffix = $argv[$i+1];
                   6844:         $i++;
                   6845:     } elseif ($arg == '-d') {
                   6846:         $with_dir = $argv[$i+1];
                   6847:         $i++;
                   6848:     } elseif ($arg == '-b') {
                   6849:         $bin_dir = $argv[$i+1];
                   6850:         $i++;
                   6851:     } elseif ($arg == '-c') {
                   6852:         $cfg_dir = $argv[$i+1];
                   6853:         $i++;
                   6854:     } elseif ($arg == '-w') {
                   6855:         $www_dir = $argv[$i+1];
                   6856:         $i++;
                   6857:     } elseif ($arg == '-p') {
                   6858:         $php_bin = $argv[$i+1];
                   6859:         $i++;
                   6860:     } elseif ($arg == '-o') {
                   6861:         $download_dir = $argv[$i+1];
                   6862:         $i++;
                   6863:     } elseif ($arg == '-t') {
                   6864:         $temp_dir = $argv[$i+1];
                   6865:         $i++;
                   6866:     } elseif ($arg == '--debug') {
                   6867:         $debug = 1;
                   6868:     } elseif ($arg == '--extremedebug') {
                   6869:         $debug = 2;
                   6870:     }
                   6871: }
                   6872: 
                   6873: $config = PEAR_Config::singleton();
                   6874: 
                   6875: if (PEAR::isError($config)) {
                   6876:     $locs = PEAR_Config::getDefaultConfigFiles();
                   6877:     die("ERROR: One of $locs[user] or $locs[system] is corrupt, please remove them and try again");
                   6878: }
                   6879: 
                   6880: // make sure we use only default values
                   6881: $config_layers = $config->getLayers();
                   6882: foreach ($config_layers as $layer) {
                   6883:     if ($layer == 'default') continue;
                   6884:     $config->removeLayer($layer);
                   6885: }
                   6886: $keys = $config->getKeys();
                   6887: if ($debug) {
                   6888:     $config->set('verbose', 5, 'default');
                   6889: } else {
                   6890:     $config->set('verbose', 0, 'default');
                   6891: }
                   6892: // PEAR executables
                   6893: if (!empty($bin_dir)) {
                   6894:     $config->set('bin_dir', $bin_dir, 'default');
                   6895: }
                   6896: 
                   6897: // Cache files
                   6898: if (!empty($cache_dir)) {
                   6899:     $config->set('cache_dir', $cache_dir, 'default');
                   6900: }
                   6901: 
                   6902: // Config files
                   6903: if (!empty($cfg_dir)) {
                   6904:     $config->set('cfg_dir', $cfg_dir, 'default');
                   6905: }
                   6906: 
                   6907: // Web files
                   6908: if (!empty($www_dir)) {
                   6909:     $config->set('www_dir', $www_dir, 'default');
                   6910: }
                   6911: 
                   6912: // Downloaded files
                   6913: if (!empty($download_dir)) {
                   6914:     $config->set('download_dir', $download_dir, 'default');
                   6915: }
                   6916: 
                   6917: // Temporary files
                   6918: if (!empty($temp_dir)) {
                   6919:     $config->set('temp_dir', $temp_dir, 'default');
                   6920: }
                   6921: 
                   6922: // User supplied a dir prefix
                   6923: if (!empty($with_dir)) {
                   6924:     $ds = DIRECTORY_SEPARATOR;
                   6925:     $config->set('php_dir', $with_dir, 'default');
                   6926:     $config->set('doc_dir', $with_dir . $ds . 'doc', 'default');
                   6927:     $config->set('data_dir', $with_dir . $ds . 'data', 'default');
                   6928:     $config->set('test_dir', $with_dir . $ds . 'test', 'default');
                   6929:     if (empty($www_dir)) {
                   6930:         $config->set('www_dir', $with_dir . $ds . 'htdocs', 'default');
                   6931:     }
                   6932:     if (empty($cfg_dir)) {
                   6933:         $config->set('cfg_dir', $with_dir . $ds . 'cfg', 'default');
                   6934:     }
                   6935:     if (!is_writable($config->get('cache_dir'))) {
                   6936:         include_once 'phar://install-pear-nozlib.phar/System.php';
                   6937:         $cdir = System::mktemp(array('-d', 'pear'));
                   6938:         if (PEAR::isError($cdir)) {
                   6939:             $ui->outputData("[PEAR] cannot make new temporary directory: " . $cdir);
                   6940:             die(1);
                   6941:         }
                   6942:         $oldcachedir = $config->get('cache_dir');
                   6943:         $config->set('cache_dir', $cdir);
                   6944:     }
                   6945: }
                   6946: 
                   6947: // PHP executable
                   6948: if (!empty($php_bin)) {
                   6949:     $config->set('php_bin', $php_bin);
                   6950: }
                   6951: 
                   6952: // PHP prefix
                   6953: if (isset($prefix)) {
                   6954:     if ($prefix != 'a') {
                   6955:         if ($prefix[0] == 'a') {
                   6956:             $prefix = substr($prefix, 1);
                   6957:         }
                   6958:         $config->set('php_prefix', $prefix, 'system');
                   6959:     }
                   6960: }
                   6961: 
                   6962: // PHP suffix
                   6963: if (isset($suffix)) {
                   6964:     if ($suffix != 'a') {
                   6965:         if ($suffix[0] == 'a') {
                   6966:             $suffix = substr($suffix, 1);
                   6967:         }
                   6968:         $config->set('php_suffix', $suffix, 'system');
                   6969:     }
                   6970: }
                   6971: 
                   6972: /* Print PEAR Conf (useful for debuging do NOT REMOVE) */
                   6973: if ($debug) {
                   6974:     sort($keys);
                   6975:     foreach ($keys as $key) {
                   6976:         echo $key . '    ' .
                   6977:             $config->getPrompt($key) . ": " . $config->get($key, null, 'default') . "\n";
                   6978:     }
                   6979:     if ($debug == 2) { // extreme debugging
                   6980:         exit;
                   6981:     }
                   6982: }
                   6983: // end print
                   6984: 
                   6985: $php_dir = $config->get('php_dir');
                   6986: $options = array();
                   6987: $options['upgrade'] = true;
                   6988: $install_root = getenv('INSTALL_ROOT');
                   6989: if (!empty($install_root)) {
                   6990:     $options['packagingroot'] = $install_root;
                   6991:     $reg = &new PEAR_Registry($options['packagingroot']);
                   6992: } else {
                   6993:     $reg = $config->getRegistry('default');
                   6994: }
                   6995: 
                   6996: $ui = PEAR_Frontend::singleton('PEAR_Frontend_CLI');
                   6997: if (PEAR::isError($ui)) {
                   6998:     die($ui->getMessage());
                   6999: }
                   7000: $installer = new PEAR_Installer($ui);
                   7001: $pkg = new PEAR_PackageFile($config, $debug);
                   7002: 
                   7003: foreach ($install_files as $package => $instfile) {
                   7004:     $info = $pkg->fromAnyFile($instfile, PEAR_VALIDATE_INSTALLING);
                   7005:     if (PEAR::isError($info)) {
                   7006:         if (is_array($info->getUserInfo())) {
                   7007:             foreach ($info->getUserInfo() as $err) {
                   7008:                 $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err['message']));
                   7009:             }
                   7010:         }
                   7011:         $ui->outputData(sprintf("[PEAR] %s: %s", $package, $info->getMessage()));
                   7012:         continue;
                   7013:     }
                   7014:     $new_ver = $info->getVersion();
                   7015:     $downloaderpackage = new PEAR_Downloader_Package($installer);
                   7016:     $err = $downloaderpackage->initialize($instfile);
                   7017:     if (PEAR::isError($err)) {
                   7018:         $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7019:         continue;
                   7020:     }
                   7021:     if ($reg->packageExists($package)) {
                   7022:         $old_ver = $reg->packageInfo($package, 'version');
                   7023:         if (version_compare($new_ver, $old_ver, 'gt')) {
                   7024:             $installer->setOptions($options);
                   7025:             $dp = array($downloaderpackage);
                   7026:             $installer->setDownloadedPackages($dp);
                   7027:             $err = $installer->install($downloaderpackage, $options);
                   7028:             if (PEAR::isError($err)) {
                   7029:                 $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7030:                 continue;
                   7031:             }
                   7032:             $ui->outputData(sprintf("[PEAR] %-15s- upgraded:  %s", $package, $new_ver));
                   7033:         } else {
                   7034:             if ($force) {
                   7035:                 $options['force'] = true;
                   7036:                 $installer->setOptions($options);
                   7037:                 $dp = array($downloaderpackage);
                   7038:                 $installer->setDownloadedPackages($dp);
                   7039:                 $err = $installer->install($downloaderpackage, $options);
                   7040:                 if (PEAR::isError($err)) {
                   7041:                     $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7042:                     continue;
                   7043:                 }
                   7044:                 $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver));
                   7045:             } else {
                   7046:                 $ui->outputData(sprintf("[PEAR] %-15s- already installed: %s", $package, $old_ver));
                   7047:             }
                   7048:         }
                   7049:     } else {
                   7050:         $options['nodeps'] = true;
                   7051:         $installer->setOptions($options);
                   7052:         $dp = array($downloaderpackage);
                   7053:         $installer->setDownloadedPackages($dp);
                   7054:         $err = $installer->install($downloaderpackage, $options);
                   7055:         if (PEAR::isError($err)) {
                   7056:             $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7057:             continue;
                   7058:         }
                   7059:         $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver));
                   7060:     }
                   7061:     if ($package == 'PEAR') {
                   7062:         if (is_file($ufile = $config->getConfFile('user'))) {
                   7063:             $ui->outputData('Warning! a PEAR user config file already exists from ' .
                   7064:                             'a previous PEAR installation at ' .
                   7065:                             "'$ufile'. You may probably want to remove it.");
                   7066:         }
                   7067:         $config->set('verbose', 1, 'default');
                   7068:         if (isset($oldcachedir)) {
                   7069:             $config->set('cache_dir', $oldcachedir);
                   7070:         }
                   7071:         $data = array();
                   7072:         foreach ($config->getKeys() as $key) {
                   7073:             $data[$key] = $config->get($key);
                   7074:         }
                   7075:         $cnf_file = $config->getConfFile('system');
                   7076:         if (!empty($install_root)) {
                   7077:             $cnf_file = $install_root . DIRECTORY_SEPARATOR . $cnf_file;
                   7078:         }
                   7079:         $config->writeConfigFile($cnf_file, 'system', $data);
                   7080:         $ui->outputData('Wrote PEAR system config file at: ' . $cnf_file);
                   7081:         $ui->outputData('You may want to add: ' . $config->get('php_dir') . ' to your php.ini include_path');
                   7082:     }
                   7083: }
                   7084: ?>
                   7085: <?php
                   7086: /**
                   7087:  * The OS_Guess class
                   7088:  *
                   7089:  * PHP versions 4 and 5
                   7090:  *
                   7091:  * @category   pear
                   7092:  * @package    PEAR
                   7093:  * @author     Stig Bakken <ssb@php.net>
                   7094:  * @author     Gregory Beaver <cellog@php.net>
                   7095:  * @copyright  1997-2009 The Authors
                   7096:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   7097:  * @version    CVS: $Id: Guess.php 278521 2009-04-09 22:24:12Z dufuz $
                   7098:  * @link       http://pear.php.net/package/PEAR
                   7099:  * @since      File available since PEAR 0.1
                   7100:  */
                   7101: 
                   7102: // {{{ uname examples
                   7103: 
                   7104: // php_uname() without args returns the same as 'uname -a', or a PHP-custom
                   7105: // string for Windows.
                   7106: // PHP versions prior to 4.3 return the uname of the host where PHP was built,
                   7107: // as of 4.3 it returns the uname of the host running the PHP code.
                   7108: //
                   7109: // PC RedHat Linux 7.1:
                   7110: // Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
                   7111: //
                   7112: // PC Debian Potato:
                   7113: // Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
                   7114: //
                   7115: // PC FreeBSD 3.3:
                   7116: // 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
                   7117: //
                   7118: // PC FreeBSD 4.3:
                   7119: // 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
                   7120: //
                   7121: // PC FreeBSD 4.5:
                   7122: // 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
                   7123: //
                   7124: // PC FreeBSD 4.5 w/uname from GNU shellutils:
                   7125: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
                   7126: //
                   7127: // HP 9000/712 HP-UX 10:
                   7128: // HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
                   7129: //
                   7130: // HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
                   7131: // HP-UX host B.10.10 A 9000/712 unknown
                   7132: //
                   7133: // IBM RS6000/550 AIX 4.3:
                   7134: // AIX host 3 4 000003531C00
                   7135: //
                   7136: // AIX 4.3 w/uname from GNU shellutils:
                   7137: // AIX host 3 4 000003531C00 unknown
                   7138: //
                   7139: // SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
                   7140: // IRIX64 host 6.5 01091820 IP19 mips
                   7141: //
                   7142: // SGI Onyx IRIX 6.5:
                   7143: // IRIX64 host 6.5 01091820 IP19
                   7144: //
                   7145: // SparcStation 20 Solaris 8 w/uname from GNU shellutils:
                   7146: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
                   7147: //
                   7148: // SparcStation 20 Solaris 8:
                   7149: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
                   7150: //
                   7151: // Mac OS X (Darwin)
                   7152: // 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
                   7153: //
                   7154: // Mac OS X early versions
                   7155: //
                   7156: 
                   7157: // }}}
                   7158: 
                   7159: /* TODO:
                   7160:  * - define endianness, to allow matchSignature("bigend") etc.
                   7161:  */
                   7162: 
                   7163: /**
                   7164:  * Retrieves information about the current operating system
                   7165:  *
                   7166:  * This class uses php_uname() to grok information about the current OS
                   7167:  *
                   7168:  * @category   pear
                   7169:  * @package    PEAR
                   7170:  * @author     Stig Bakken <ssb@php.net>
                   7171:  * @author     Gregory Beaver <cellog@php.net>
                   7172:  * @copyright  1997-2009 The Authors
                   7173:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   7174:  * @version    Release: 1.10.0beta1
                   7175:  * @link       http://pear.php.net/package/PEAR
                   7176:  * @since      Class available since Release 0.1
                   7177:  */
                   7178: class OS_Guess
                   7179: {
                   7180:     var $sysname;
                   7181:     var $nodename;
                   7182:     var $cpu;
                   7183:     var $release;
                   7184:     var $extra;
                   7185: 
                   7186:     function OS_Guess($uname = null)
                   7187:     {
                   7188:         list($this->sysname,
                   7189:              $this->release,
                   7190:              $this->cpu,
                   7191:              $this->extra,
                   7192:              $this->nodename) = $this->parseSignature($uname);
                   7193:     }
                   7194: 
                   7195:     function parseSignature($uname = null)
                   7196:     {
                   7197:         static $sysmap = array(
                   7198:             'HP-UX' => 'hpux',
                   7199:             'IRIX64' => 'irix',
                   7200:         );
                   7201:         static $cpumap = array(
                   7202:             'i586' => 'i386',
                   7203:             'i686' => 'i386',
                   7204:             'ppc' => 'powerpc',
                   7205:         );
                   7206:         if ($uname === null) {
                   7207:             $uname = php_uname();
                   7208:         }
                   7209:         $parts = preg_split('/\s+/', trim($uname));
                   7210:         $n = count($parts);
                   7211: 
                   7212:         $release  = $machine = $cpu = '';
                   7213:         $sysname  = $parts[0];
                   7214:         $nodename = $parts[1];
                   7215:         $cpu      = $parts[$n-1];
                   7216:         $extra = '';
                   7217:         if ($cpu == 'unknown') {
                   7218:             $cpu = $parts[$n - 2];
                   7219:         }
                   7220: 
                   7221:         switch ($sysname) {
                   7222:             case 'AIX' :
                   7223:                 $release = "$parts[3].$parts[2]";
                   7224:                 break;
                   7225:             case 'Windows' :
                   7226:                 switch ($parts[1]) {
                   7227:                     case '95/98':
                   7228:                         $release = '9x';
                   7229:                         break;
                   7230:                     default:
                   7231:                         $release = $parts[1];
                   7232:                         break;
                   7233:                 }
                   7234:                 $cpu = 'i386';
                   7235:                 break;
                   7236:             case 'Linux' :
                   7237:                 $extra = $this->_detectGlibcVersion();
                   7238:                 // use only the first two digits from the kernel version
                   7239:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   7240:                 break;
                   7241:             case 'Mac' :
                   7242:                 $sysname = 'darwin';
                   7243:                 $nodename = $parts[2];
                   7244:                 $release = $parts[3];
                   7245:                 if ($cpu == 'Macintosh') {
                   7246:                     if ($parts[$n - 2] == 'Power') {
                   7247:                         $cpu = 'powerpc';
                   7248:                     }
                   7249:                 }
                   7250:                 break;
                   7251:             case 'Darwin' :
                   7252:                 if ($cpu == 'Macintosh') {
                   7253:                     if ($parts[$n - 2] == 'Power') {
                   7254:                         $cpu = 'powerpc';
                   7255:                     }
                   7256:                 }
                   7257:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   7258:                 break;
                   7259:             default:
                   7260:                 $release = preg_replace('/-.*/', '', $parts[2]);
                   7261:                 break;
                   7262:         }
                   7263: 
                   7264:         if (isset($sysmap[$sysname])) {
                   7265:             $sysname = $sysmap[$sysname];
                   7266:         } else {
                   7267:             $sysname = strtolower($sysname);
                   7268:         }
                   7269:         if (isset($cpumap[$cpu])) {
                   7270:             $cpu = $cpumap[$cpu];
                   7271:         }
                   7272:         return array($sysname, $release, $cpu, $extra, $nodename);
                   7273:     }
                   7274: 
                   7275:     function _detectGlibcVersion()
                   7276:     {
                   7277:         static $glibc = false;
                   7278:         if ($glibc !== false) {
                   7279:             return $glibc; // no need to run this multiple times
                   7280:         }
                   7281:         $major = $minor = 0;
                   7282:         include_once 'phar://install-pear-nozlib.phar/' . "System.php";
                   7283:         // Use glibc's <features.h> header file to
                   7284:         // get major and minor version number:
                   7285:         if (@file_exists('/usr/include/features.h') &&
                   7286:               @is_readable('/usr/include/features.h')) {
                   7287:             if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
                   7288:                 $features_file = fopen('/usr/include/features.h', 'rb');
                   7289:                 while (!feof($features_file)) {
                   7290:                     $line = fgets($features_file, 8192);
                   7291:                     if (!$line || (strpos($line, '#define') === false)) {
                   7292:                         continue;
                   7293:                     }
                   7294:                     if (strpos($line, '__GLIBC__')) {
                   7295:                         // major version number #define __GLIBC__ version
                   7296:                         $line = preg_split('/\s+/', $line);
                   7297:                         $glibc_major = trim($line[2]);
                   7298:                         if (isset($glibc_minor)) {
                   7299:                             break;
                   7300:                         }
                   7301:                         continue;
                   7302:                     }
                   7303: 
                   7304:                     if (strpos($line, '__GLIBC_MINOR__'))  {
                   7305:                         // got the minor version number
                   7306:                         // #define __GLIBC_MINOR__ version
                   7307:                         $line = preg_split('/\s+/', $line);
                   7308:                         $glibc_minor = trim($line[2]);
                   7309:                         if (isset($glibc_major)) {
                   7310:                             break;
                   7311:                         }
                   7312:                         continue;
                   7313:                     }
                   7314:                 }
                   7315:                 fclose($features_file);
                   7316:                 if (!isset($glibc_major) || !isset($glibc_minor)) {
                   7317:                     return $glibc = '';
                   7318:                 }
                   7319:                 return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
                   7320:             } // no cpp
                   7321: 
                   7322:             $tmpfile = System::mktemp("glibctest");
                   7323:             $fp = fopen($tmpfile, "w");
                   7324:             fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
                   7325:             fclose($fp);
                   7326:             $cpp = popen("/usr/bin/cpp $tmpfile", "r");
                   7327:             while ($line = fgets($cpp, 1024)) {
                   7328:                 if ($line{0} == '#' || trim($line) == '') {
                   7329:                     continue;
                   7330:                 }
                   7331: 
                   7332:                 if (list($major, $minor) = explode(' ', trim($line))) {
                   7333:                     break;
                   7334:                 }
                   7335:             }
                   7336:             pclose($cpp);
                   7337:             unlink($tmpfile);
                   7338:         } // features.h
                   7339: 
                   7340:         if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
                   7341:             // Let's try reading the libc.so.6 symlink
                   7342:             if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
                   7343:                 list($major, $minor) = explode('.', $matches[1]);
                   7344:             }
                   7345:         }
                   7346: 
                   7347:         if (!($major && $minor)) {
                   7348:             return $glibc = '';
                   7349:         }
                   7350: 
                   7351:         return $glibc = "glibc{$major}.{$minor}";
                   7352:     }
                   7353: 
                   7354:     function getSignature()
                   7355:     {
                   7356:         if (empty($this->extra)) {
                   7357:             return "{$this->sysname}-{$this->release}-{$this->cpu}";
                   7358:         }
                   7359:         return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
                   7360:     }
                   7361: 
                   7362:     function getSysname()
                   7363:     {
                   7364:         return $this->sysname;
                   7365:     }
                   7366: 
                   7367:     function getNodename()
                   7368:     {
                   7369:         return $this->nodename;
                   7370:     }
                   7371: 
                   7372:     function getCpu()
                   7373:     {
                   7374:         return $this->cpu;
                   7375:     }
                   7376: 
                   7377:     function getRelease()
                   7378:     {
                   7379:         return $this->release;
                   7380:     }
                   7381: 
                   7382:     function getExtra()
                   7383:     {
                   7384:         return $this->extra;
                   7385:     }
                   7386: 
                   7387:     function matchSignature($match)
                   7388:     {
                   7389:         $fragments = is_array($match) ? $match : explode('-', $match);
                   7390:         $n = count($fragments);
                   7391:         $matches = 0;
                   7392:         if ($n > 0) {
                   7393:             $matches += $this->_matchFragment($fragments[0], $this->sysname);
                   7394:         }
                   7395:         if ($n > 1) {
                   7396:             $matches += $this->_matchFragment($fragments[1], $this->release);
                   7397:         }
                   7398:         if ($n > 2) {
                   7399:             $matches += $this->_matchFragment($fragments[2], $this->cpu);
                   7400:         }
                   7401:         if ($n > 3) {
                   7402:             $matches += $this->_matchFragment($fragments[3], $this->extra);
                   7403:         }
                   7404:         return ($matches == $n);
                   7405:     }
                   7406: 
                   7407:     function _matchFragment($fragment, $value)
                   7408:     {
                   7409:         if (strcspn($fragment, '*?') < strlen($fragment)) {
                   7410:             $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
                   7411:             return preg_match($reg, $value);
                   7412:         }
                   7413:         return ($fragment == '*' || !strcasecmp($fragment, $value));
                   7414:     }
                   7415: 
                   7416: }
                   7417: /*
                   7418:  * Local Variables:
                   7419:  * indent-tabs-mode: nil
                   7420:  * c-basic-offset: 4
                   7421:  * End:
                   7422:  */package2.xml0000644000076500000240000013062211605156760012243 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8"?>
                   7423: <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">
                   7424:  <name>PEAR</name>
                   7425:  <channel>pear.php.net</channel>
                   7426:  <summary>PEAR Base System</summary>
                   7427:  <description>The PEAR package contains:
                   7428:  * the PEAR installer, for creating, distributing
                   7429:    and installing packages
                   7430:  * the PEAR_Exception PHP5 error handling mechanism
                   7431:  * the PEAR_ErrorStack advanced error handling mechanism
                   7432:  * the PEAR_Error error handling mechanism
                   7433:  * the OS_Guess class for retrieving info about the OS
                   7434:    where PHP is running on
                   7435:  * the System class for quick handling of common operations
                   7436:    with files and directories
                   7437:  * the PEAR base class
                   7438:   Features in a nutshell:
                   7439:   * full support for channels
                   7440:   * pre-download dependency validation
                   7441:   * new package.xml 2.0 format allows tremendous flexibility while maintaining BC
                   7442:   * support for optional dependency groups and limited support for sub-packaging
                   7443:   * robust dependency support
                   7444:   * full dependency validation on uninstall
                   7445:   * remote install for hosts with only ftp access - no more problems with
                   7446:     restricted host installation
                   7447:   * full support for mirroring
                   7448:   * support for bundling several packages into a single tarball
                   7449:   * support for static dependencies on a url-based package
                   7450:   * support for custom file roles and installation tasks</description>
                   7451:  <lead>
                   7452:   <name>Greg Beaver</name>
                   7453:   <user>cellog</user>
                   7454:   <email>cellog@php.net</email>
                   7455:   <active>no</active>
                   7456:  </lead>
                   7457:  <lead>
                   7458:   <name>Pierre-Alain Joye</name>
                   7459:   <user>pajoye</user>
                   7460:   <email>pierre@php.net</email>
                   7461:   <active>no</active>
                   7462:  </lead>
                   7463:  <lead>
                   7464:   <name>Stig Bakken</name>
                   7465:   <user>ssb</user>
                   7466:   <email>stig@php.net</email>
                   7467:   <active>no</active>
                   7468:  </lead>
                   7469:  <lead>
                   7470:   <name>Tomas V.V.Cox</name>
                   7471:   <user>cox</user>
                   7472:   <email>cox@idecnet.com</email>
                   7473:   <active>no</active>
                   7474:  </lead>
                   7475:  <lead>
                   7476:   <name>Helgi Thormar</name>
                   7477:   <user>dufuz</user>
                   7478:   <email>dufuz@php.net</email>
                   7479:   <active>yes</active>
                   7480:  </lead>
                   7481:  <developer>
                   7482:   <name>Tias Guns</name>
                   7483:   <user>tias</user>
                   7484:   <email>tias@php.net</email>
                   7485:   <active>yes</active>
                   7486:  </developer>
                   7487:  <helper>
                   7488:   <name>Tim Jackson</name>
                   7489:   <user>timj</user>
                   7490:   <email>timj@php.net</email>
                   7491:   <active>no</active>
                   7492:  </helper>
                   7493:  <helper>
                   7494:   <name>Bertrand Gugger</name>
                   7495:   <user>toggg</user>
                   7496:   <email>toggg@php.net</email>
                   7497:   <active>no</active>
                   7498:  </helper>
                   7499:  <helper>
                   7500:   <name>Martin Jansen</name>
                   7501:   <user>mj</user>
                   7502:   <email>mj@php.net</email>
                   7503:   <active>no</active>
                   7504:  </helper>
                   7505:  <date>2011-07-06</date>
                   7506:  <time>22:13:04</time>
                   7507:  <version>
                   7508:   <release>1.9.4</release>
                   7509:   <api>1.9.4</api>
                   7510:  </version>
                   7511:  <stability>
                   7512:   <release>stable</release>
                   7513:   <api>stable</api>
                   7514:  </stability>
                   7515:  <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   7516:  <notes>
                   7517: Bug Fixes:
                   7518: * Bug #17350: &quot;pear install --force&quot; doesn&apos;t uninstall files from previous pkg versions [dufuz]
                   7519: * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz]
                   7520: * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz]
                   7521: * Bug #18581: &quot;config-get -c&quot; not returning channel&apos;s configuration when using alias [dufuz]
                   7522: * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz]
                   7523: 
                   7524: Features
                   7525: * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes.
                   7526:   Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz]
                   7527:  </notes>
                   7528:  <contents>
                   7529:   <dir name="/">
                   7530:    <file md5sum="a74724b2a02b50afb0e71f78b7661a4c" name="OS/Guess.php" role="php">
                   7531:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7532:    </file>
                   7533:    <file md5sum="d453b69059dceb53e5a61b9881fe2336" name="PEAR/ChannelFile/Parser.php" role="php">
                   7534:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7535:    </file>
                   7536:    <file md5sum="8fd87e64002e11fd86eb2f3fbfee6599" name="PEAR/Command/Auth.xml" role="php" />
                   7537:    <file md5sum="314f2756d74b4cc529e77be45847b3ac" name="PEAR/Command/Auth.php" role="php">
                   7538:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7539:    </file>
                   7540:    <file md5sum="73602fd7f051eaf8d37452d0e3063bdb" name="PEAR/Command/Build.xml" role="php" />
                   7541:    <file md5sum="aa7961eff628901fd6a08074715d18ac" name="PEAR/Command/Build.php" role="php">
                   7542:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7543:    </file>
                   7544:    <file md5sum="6d5aab4d4308c3005b5f584c7783a031" name="PEAR/Command/Channels.xml" role="php" />
                   7545:    <file md5sum="d61f91d95657304c3e7facf3f4a3ab7b" name="PEAR/Command/Channels.php" role="php">
                   7546:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7547:    </file>
                   7548:    <file md5sum="1214f0f5edb4d7531e54b32e75c3b162" name="PEAR/Command/Common.php" role="php">
                   7549:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7550:    </file>
                   7551:    <file md5sum="91f189cb9423b5e87ee0abc5ea1a2be3" name="PEAR/Command/Config.xml" role="php" />
                   7552:    <file md5sum="2cca5bfb4005291d3a234b9cc00e4091" name="PEAR/Command/Config.php" role="php">
                   7553:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7554:    </file>
                   7555:    <file md5sum="2db0386b865d3f9a29f9126728722ece" name="PEAR/Command/Install.xml" role="php" />
                   7556:    <file md5sum="32d3ee477937685cffec094424390c18" name="PEAR/Command/Install.php" role="php">
                   7557:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7558:    </file>
                   7559:    <file md5sum="5cb62a04c0a268f4edd64a49a3895c92" name="PEAR/Command/Mirror.xml" role="php" />
                   7560:    <file md5sum="bc0b8df989565f87f1693ac7a2ce0e4b" name="PEAR/Command/Mirror.php" role="php">
                   7561:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7562:    </file>
                   7563:    <file md5sum="9367dcd7e4dbdde423f9c4c7d3f3a919" name="PEAR/Command/Package.xml" role="php" />
                   7564:    <file md5sum="68f45817fe926173b45018e1b1dec108" name="PEAR/Command/Package.php" role="php">
                   7565:     <tasks:replace from="@DATA-DIR@" to="data_dir" type="pear-config" />
                   7566:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7567:    </file>
                   7568:    <file md5sum="28dc842ea725d8787b9f9c3dbca5aa22" name="PEAR/Command/Pickle.xml" role="php" />
                   7569:    <file md5sum="583e8d10daab8e16b2e2a9fc3498b1ac" name="PEAR/Command/Pickle.php" role="php">
                   7570:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7571:    </file>
                   7572:    <file md5sum="49b046cfc14747f0365e02e9c3f0e6dc" name="PEAR/Command/Registry.xml" role="php" />
                   7573:    <file md5sum="59629a5d63b0d5e54f49de509a1a6cf9" name="PEAR/Command/Registry.php" role="php">
                   7574:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7575:    </file>
                   7576:    <file md5sum="29c02e823879b4e3e291f6b36fb339f1" name="PEAR/Command/Remote.xml" role="php" />
                   7577:    <file md5sum="36c02597c5db0b5148aef6e49d3b2604" name="PEAR/Command/Remote.php" role="php">
                   7578:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7579:    </file>
                   7580:    <file md5sum="a50c32015005e0761cc3b04679b29ed0" name="PEAR/Command/Test.xml" role="php" />
                   7581:    <file md5sum="8794af46ada0364362db0e131607e6d1" name="PEAR/Command/Test.php" role="php">
                   7582:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7583:    </file>
                   7584:    <file md5sum="2a4bfddd597fcb1d63b2a06ea4544b91" name="PEAR/Downloader/Package.php" role="php">
                   7585:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7586:    </file>
                   7587:    <file md5sum="8c8ebc9143aeff5fd5803c63e1cd0070" name="PEAR/Frontend/CLI.php" role="php">
                   7588:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7589:    </file>
                   7590:    <file md5sum="6a0785b8e9678b7283d56eba9aaea390" name="PEAR/Installer/Role/Common.php" role="php">
                   7591:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7592:    </file>
                   7593:    <file md5sum="d8c62e6275e3aaa7784290912406092c" name="PEAR/Installer/Role/Cfg.xml" role="php" />
                   7594:    <file md5sum="faee4c4408cf77aa73c608b54ed3a587" name="PEAR/Installer/Role/Cfg.php" role="php">
                   7595:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7596:    </file>
                   7597:    <file md5sum="89a4a2a286e842d45a98974f40a0565c" name="PEAR/Installer/Role/Data.xml" role="php" />
                   7598:    <file md5sum="6273b7a0c754f7ec61a9ad0e7476ab35" name="PEAR/Installer/Role/Data.php" role="php">
                   7599:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7600:    </file>
                   7601:    <file md5sum="b1ce0fe105251c3b75209d6518ee69ac" name="PEAR/Installer/Role/Doc.xml" role="php" />
                   7602:    <file md5sum="f965a64b0fc06036ed4299ab51521874" name="PEAR/Installer/Role/Doc.php" role="php">
                   7603:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7604:    </file>
                   7605:    <file md5sum="af71c0ad42d16a323afe24a4f884ef15" name="PEAR/Installer/Role/Ext.xml" role="php" />
                   7606:    <file md5sum="8222eb9dc206801ebd0495720e94490f" name="PEAR/Installer/Role/Ext.php" role="php">
                   7607:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7608:    </file>
                   7609:    <file md5sum="ef88f0321d3e481c2130c95122cf76d8" name="PEAR/Installer/Role/Php.xml" role="php" />
                   7610:    <file md5sum="5bb9fe55b02ec58880243234bd847e57" name="PEAR/Installer/Role/Php.php" role="php">
                   7611:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7612:    </file>
                   7613:    <file md5sum="746461dc3b48af6d24094cb0211608f2" name="PEAR/Installer/Role/Script.xml" role="php" />
                   7614:    <file md5sum="769a902fe324b627357860b1b922aa1c" name="PEAR/Installer/Role/Script.php" role="php">
                   7615:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7616:    </file>
                   7617:    <file md5sum="e147d63f168ea156fc2be38caaa63804" name="PEAR/Installer/Role/Src.xml" role="php" />
                   7618:    <file md5sum="8f38f7e74a60e90a7e1363b6f509b426" name="PEAR/Installer/Role/Src.php" role="php">
                   7619:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7620:    </file>
                   7621:    <file md5sum="a24b596ec987aa5688fc19e8ed4e97ea" name="PEAR/Installer/Role/Test.xml" role="php" />
                   7622:    <file md5sum="b12694a189904c77db170d89f8aa9b61" name="PEAR/Installer/Role/Test.php" role="php">
                   7623:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7624:    </file>
                   7625:    <file md5sum="7641e71c5785bb33a4261ebe25ed0fd7" name="PEAR/Installer/Role/Www.xml" role="php" />
                   7626:    <file md5sum="0a3b8808e8c7f26a7f2e3c115fd09fdc" name="PEAR/Installer/Role/Www.php" role="php">
                   7627:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7628:    </file>
                   7629:    <file md5sum="bd136be2697af553a4ba35f7eaca7f68" name="PEAR/Installer/Role.php" role="php">
                   7630:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7631:    </file>
                   7632:    <file md5sum="7db4fa3f069fc2ed490464b1efe6d801" name="PEAR/PackageFile/Generator/v1.php" role="php">
                   7633:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7634:    </file>
                   7635:    <file md5sum="8294267046359e521dc226ebbbed8d37" name="PEAR/PackageFile/Generator/v2.php" role="php">
                   7636:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7637:    </file>
                   7638:    <file md5sum="ef7d06b95df06047a46df12187997a4f" name="PEAR/PackageFile/Parser/v1.php" role="php">
                   7639:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7640:    </file>
                   7641:    <file md5sum="98b457406963b0ba61d6206ee3b22615" name="PEAR/PackageFile/Parser/v2.php" role="php">
                   7642:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7643:    </file>
                   7644:    <file md5sum="6cb5b523de08db7641d53fbd01161806" name="PEAR/PackageFile/v2/rw.php" role="php">
                   7645:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7646:    </file>
                   7647:    <file md5sum="4bb188500dcecfca3ee085572a6f88d2" name="PEAR/PackageFile/v2/Validator.php" role="php">
                   7648:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7649:    </file>
                   7650:    <file md5sum="6211d1048871e00e38509001e3a0248a" name="PEAR/PackageFile/v1.php" role="php">
                   7651:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7652:    </file>
                   7653:    <file md5sum="76d76e677471159a4bd4595190f849f8" name="PEAR/PackageFile/v2.php" role="php">
                   7654:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7655:    </file>
                   7656:    <file md5sum="e4a28d36a4e0e4d406034acc92f563de" name="PEAR/REST/10.php" role="php">
                   7657:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7658:    </file>
                   7659:    <file md5sum="256b8c9bd6f2411f17054a8bb8e56fa5" name="PEAR/REST/11.php" role="php">
                   7660:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7661:    </file>
                   7662:    <file md5sum="45b3138f8102e186da7cfdf8d2bd4150" name="PEAR/REST/13.php" role="php">
                   7663:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7664:    </file>
                   7665:    <file md5sum="77205d37ba0c4233ee343a78ddb6cd9d" name="PEAR/Task/Postinstallscript/rw.php" role="php">
                   7666:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7667:    </file>
                   7668:    <file md5sum="3c27b135962a1826a4e7d6b977b0b288" name="PEAR/Task/Replace/rw.php" role="php">
                   7669:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7670:    </file>
                   7671:    <file md5sum="0441c97aa22e4c281f1974df324a5cfb" name="PEAR/Task/Unixeol/rw.php" role="php">
                   7672:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7673:    </file>
                   7674:    <file md5sum="e9a7f560abe1db1c114b0cc7f3134a4a" name="PEAR/Task/Windowseol/rw.php" role="php">
                   7675:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7676:    </file>
                   7677:    <file md5sum="53e67f33a146cf9ee2d951239ab95ba0" name="PEAR/Task/Common.php" role="php">
                   7678:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7679:    </file>
                   7680:    <file md5sum="9eed944f3f795c52caba0cb87665cd7f" name="PEAR/Task/Postinstallscript.php" role="php">
                   7681:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7682:    </file>
                   7683:    <file md5sum="b51702374ca8c34dd4e540f8848f8f57" name="PEAR/Task/Replace.php" role="php">
                   7684:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7685:    </file>
                   7686:    <file md5sum="7a280f398b108bc030a126a10e75af7e" name="PEAR/Task/Unixeol.php" role="php">
                   7687:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7688:    </file>
                   7689:    <file md5sum="c321484c304ebb4de50cd204b6a61c6d" name="PEAR/Task/Windowseol.php" role="php">
                   7690:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7691:    </file>
                   7692:    <file md5sum="b8d475e539a47999dd78ddc0f2831b0e" name="PEAR/Validator/PECL.php" role="php">
                   7693:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7694:    </file>
                   7695:    <file md5sum="598ad0a7c788a4ee154501223f607fa5" name="PEAR/Autoloader.php" role="php">
                   7696:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7697:    </file>
                   7698:    <file md5sum="3a236b984c43be942864e9a2c2f7f618" name="PEAR/Builder.php" role="php">
                   7699:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7700:    </file>
                   7701:    <file md5sum="fe1651f49d9b4e77e252c817c5ac8fb8" name="PEAR/ChannelFile.php" role="php">
                   7702:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7703:    </file>
                   7704:    <file md5sum="8dfb2616d94dc0d54ca05d6d2a9a3d60" name="PEAR/Command.php" role="php">
                   7705:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7706:    </file>
                   7707:    <file md5sum="3134df96c00615c595bc3c74c0fb605f" name="PEAR/Common.php" role="php">
                   7708:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7709:    </file>
                   7710:    <file md5sum="ef2e1652bed814e36676d605c9a7b599" name="PEAR/Config.php" role="php">
                   7711:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7712:    </file>
                   7713:    <file md5sum="708a3a44875759e005b881179b3d5ed4" name="PEAR/DependencyDB.php" role="php">
                   7714:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7715:    </file>
                   7716:    <file md5sum="0744ce601546afb988e2542b27d82aa9" name="PEAR/Dependency2.php" role="php">
                   7717:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7718:    </file>
                   7719:    <file md5sum="3f62de6899c2ca37c89810e3510b77b9" name="PEAR/Downloader.php" role="php">
                   7720:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7721:    </file>
                   7722:    <file md5sum="3d1ee44f11a5c927f98149041cbba536" name="PEAR/ErrorStack.php" role="php">
                   7723:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7724:    </file>
                   7725:    <file md5sum="ebea74b4b24af93a0982536ae6faeb76" name="PEAR/Exception.php" role="php">
                   7726:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7727:    </file>
                   7728:    <file md5sum="e0e4cbcec4a972fbad779d0f9d323120" name="PEAR/FixPHP5PEARWarnings.php" role="php" />
                   7729:    <file md5sum="e00af62b175d4a15430be6394b09afaa" name="PEAR/Frontend.php" role="php">
                   7730:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7731:    </file>
                   7732:    <file md5sum="5b77738449ea8d539883d520f0f05d2a" name="PEAR/Installer.php" role="php">
                   7733:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7734:    </file>
                   7735:    <file md5sum="60600f35203b87481eb354b9b58c05f9" name="PEAR/PackageFile.php" role="php">
                   7736:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7737:    </file>
                   7738:    <file md5sum="5e553c0ac9530fc8757735675f0837ee" name="PEAR/Packager.php" role="php">
                   7739:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7740:    </file>
                   7741:    <file md5sum="5ff450e917d7128af3dc5d596e02bd04" name="PEAR/Registry.php" role="php">
                   7742:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7743:    </file>
                   7744:    <file md5sum="9d0e60efa1884de7d2a812e815cbd30e" name="PEAR/REST.php" role="php">
                   7745:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7746:    </file>
                   7747:    <file md5sum="20315d45a87c2c9fb9992f5e27a0e354" name="PEAR/RunTest.php" role="php">
                   7748:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7749:    </file>
                   7750:    <file md5sum="709e306baa715e79696de0fcd7f5db6a" name="PEAR/Validate.php" role="php">
                   7751:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7752:    </file>
                   7753:    <file md5sum="496230695ea1e3f7e0eb1a1e7030383f" name="PEAR/XMLParser.php" role="php">
                   7754:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7755:    </file>
                   7756:    <file baseinstalldir="/" md5sum="d888d06143e3cac0dae78bbb2e761366" name="scripts/pear.bat" role="script">
                   7757:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   7758:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7759:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7760:     <tasks:windowseol />
                   7761:    </file>
                   7762:    <file baseinstalldir="/" md5sum="762c9aeb3a91f7160a12896ce197acb6" name="scripts/peardev.bat" role="script">
                   7763:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   7764:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7765:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7766:     <tasks:windowseol />
                   7767:    </file>
                   7768:    <file baseinstalldir="/" md5sum="2bd742ce721c8dd5aa164613c063a8a9" name="scripts/pecl.bat" role="script">
                   7769:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   7770:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7771:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7772:     <tasks:windowseol />
                   7773:    </file>
                   7774:    <file baseinstalldir="/" md5sum="8ac139504e80bede470aef6d405100b6" name="scripts/pear.sh" role="script">
                   7775:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7776:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   7777:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   7778:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7779:     <tasks:unixeol />
                   7780:    </file>
                   7781:    <file baseinstalldir="/" md5sum="08ea03525b4ba914dfd9ec69c4238cf4" name="scripts/peardev.sh" role="script">
                   7782:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7783:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   7784:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   7785:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7786:     <tasks:unixeol />
                   7787:    </file>
                   7788:    <file baseinstalldir="/" md5sum="41fab77b7808267d88b8e06097a1fbbe" name="scripts/pecl.sh" role="script">
                   7789:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7790:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   7791:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   7792:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7793:     <tasks:unixeol />
                   7794:    </file>
                   7795:    <file baseinstalldir="/" md5sum="fc547ba1ab80167d9c9cfcbb439d1537" name="scripts/pearcmd.php" role="php">
                   7796:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7797:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   7798:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   7799:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7800:    </file>
                   7801:    <file baseinstalldir="/" md5sum="e758c3c57ace46749eb39868fe98b2ca" name="scripts/peclcmd.php" role="php">
                   7802:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   7803:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   7804:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   7805:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   7806:    </file>
                   7807:    <file md5sum="45b44486d8090de17b2a8b4211fab247" name="LICENSE" role="doc" />
                   7808:    <file md5sum="8e9d494169d0dea3d7b24bae14d85aba" name="INSTALL" role="doc" />
                   7809:    <file md5sum="4a49bc83a392934e57af45c70a589fda" name="package.dtd" role="data" />
                   7810:    <file md5sum="1a8f67d58009372a6cbcddd638b128cf" name="PEAR5.php" role="php" />
                   7811:    <file md5sum="962bdcdbc2e4467f047b233fa45296bd" name="PEAR.php" role="php">
                   7812:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7813:    </file>
                   7814:    <file md5sum="b10231f9dd564ac24951758b67f6e155" name="README" role="doc" />
                   7815:    <file md5sum="1d62197f092116e711e6c9b7ed0c4fe9" name="System.php" role="php">
                   7816:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7817:    </file>
                   7818:    <file md5sum="acd010e3bc43c0f72df584acde7b9158" name="template.spec" role="data" />
                   7819:   </dir>
                   7820:  </contents>
                   7821:  <dependencies>
                   7822:   <required>
                   7823:    <php>
                   7824:     <min>4.4.0</min>
                   7825:     <exclude>5.0</exclude>
                   7826:     <exclude>5.1.0</exclude>
                   7827:     <exclude>5.1.1</exclude>
                   7828:     <exclude>5.1.2</exclude>
                   7829:     <exclude>5.1.3</exclude>
                   7830:     <exclude>5.1.4</exclude>
                   7831:     <exclude>5.1.5</exclude>
                   7832:    </php>
                   7833:    <pearinstaller>
                   7834:     <min>1.4.3</min>
                   7835:    </pearinstaller>
                   7836:    <package>
                   7837:     <name>Archive_Tar</name>
                   7838:     <channel>pear.php.net</channel>
                   7839:     <min>1.3.7</min>
                   7840:    </package>
                   7841:    <package>
                   7842:     <name>Structures_Graph</name>
                   7843:     <channel>pear.php.net</channel>
                   7844:     <min>1.0.2</min>
                   7845:     <recommended>1.0.4</recommended>
                   7846:    </package>
                   7847:    <package>
                   7848:     <name>Console_Getopt</name>
                   7849:     <channel>pear.php.net</channel>
                   7850:     <min>1.2</min>
                   7851:     <recommended>1.2.3</recommended>
                   7852:    </package>
                   7853:    <package>
                   7854:     <name>XML_Util</name>
                   7855:     <channel>pear.php.net</channel>
                   7856:     <min>1.2.0</min>
                   7857:     <recommended>1.2.1</recommended>
                   7858:    </package>
                   7859:    <package>
                   7860:     <name>PEAR_Frontend_Web</name>
                   7861:     <channel>pear.php.net</channel>
                   7862:     <max>0.4</max>
                   7863:     <conflicts />
                   7864:    </package>
                   7865:    <package>
                   7866:     <name>PEAR_Frontend_Gtk</name>
                   7867:     <channel>pear.php.net</channel>
                   7868:     <max>0.4.0</max>
                   7869:     <exclude>0.4.0</exclude>
                   7870:     <conflicts />
                   7871:    </package>
                   7872:    <extension>
                   7873:     <name>xml</name>
                   7874:    </extension>
                   7875:    <extension>
                   7876:     <name>pcre</name>
                   7877:    </extension>
                   7878:   </required>
                   7879:   <group hint="PEAR's web-based installer" name="webinstaller">
                   7880:    <package>
                   7881:     <name>PEAR_Frontend_Web</name>
                   7882:     <channel>pear.php.net</channel>
                   7883:     <min>0.5.1</min>
                   7884:    </package>
                   7885:   </group>
                   7886:   <group hint="PEAR's PHP-GTK-based installer" name="gtkinstaller">
                   7887:    <package>
                   7888:     <name>PEAR_Frontend_Gtk</name>
                   7889:     <channel>pear.php.net</channel>
                   7890:     <min>0.4.0</min>
                   7891:    </package>
                   7892:   </group>
                   7893:   <group hint="PEAR's PHP-GTK2-based installer" name="gtk2installer">
                   7894:    <package>
                   7895:     <name>PEAR_Frontend_Gtk2</name>
                   7896:     <channel>pear.php.net</channel>
                   7897:    </package>
                   7898:   </group>
                   7899:  </dependencies>
                   7900:  <phprelease>
                   7901:   <installconditions>
                   7902:    <os>
                   7903:     <name>windows</name>
                   7904:    </os>
                   7905:   </installconditions>
                   7906:   <filelist>
                   7907:    <install as="pear.bat" name="scripts/pear.bat" />
                   7908:    <install as="peardev.bat" name="scripts/peardev.bat" />
                   7909:    <install as="pecl.bat" name="scripts/pecl.bat" />
                   7910:    <install as="pearcmd.php" name="scripts/pearcmd.php" />
                   7911:    <install as="peclcmd.php" name="scripts/peclcmd.php" />
                   7912:    <ignore name="scripts/peardev.sh" />
                   7913:    <ignore name="scripts/pear.sh" />
                   7914:    <ignore name="scripts/pecl.sh" />
                   7915:   </filelist>
                   7916:  </phprelease>
                   7917:  <phprelease>
                   7918:   <filelist>
                   7919:    <install as="pear" name="scripts/pear.sh" />
                   7920:    <install as="peardev" name="scripts/peardev.sh" />
                   7921:    <install as="pecl" name="scripts/pecl.sh" />
                   7922:    <install as="pearcmd.php" name="scripts/pearcmd.php" />
                   7923:    <install as="peclcmd.php" name="scripts/peclcmd.php" />
                   7924:    <ignore name="scripts/pear.bat" />
                   7925:    <ignore name="scripts/peardev.bat" />
                   7926:    <ignore name="scripts/pecl.bat" />
                   7927:   </filelist>
                   7928:  </phprelease>
                   7929:  <changelog>
                   7930:   <release>
                   7931:    <version>
                   7932:     <release>1.8.0alpha1</release>
                   7933:     <api>1.8.0</api>
                   7934:    </version>
                   7935:    <stability>
                   7936:     <release>alpha</release>
                   7937:     <api>stable</api>
                   7938:    </stability>
                   7939:    <date>2009-03-09</date>
                   7940:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   7941:    <notes>
                   7942: * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   7943: * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   7944: * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   7945: * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   7946: * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   7947: * Implement Request #12706: pear list -a hard to read [dufuz]
                   7948: * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   7949: * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   7950: * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   7951: * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   7952: * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   7953:   - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   7954:     better what other package managers are doing. upgrade-all will still work as intended.
                   7955: * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   7956:   - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   7957:     channel specific upgrades
                   7958: * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   7959: * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   7960: 
                   7961: * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   7962: * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   7963: 
                   7964: * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   7965: * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   7966: * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   7967: * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   7968: * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   7969: * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   7970: * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   7971: * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   7972: * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   7973: * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   7974: * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   7975: * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   7976: * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   7977: * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   7978: * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   7979: * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   7980: * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   7981: * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   7982: 
                   7983: NOTE!
                   7984: Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   7985: to migrate over to one of the alternatives that have ben provided:
                   7986: * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   7987: * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   7988: * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   7989: * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   7990: * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   7991: * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   7992: * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   7993: * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   7994: * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   7995: * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   7996:   PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   7997: 
                   7998: PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   7999: pear upgrade -f PEAR will allow people with lower versions
                   8000: to upgrade to this release but no guarantees will be made that it will work properly.
                   8001: 
                   8002: Support for XML RPC channels has been dropped - The only ones that used it
                   8003: (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   8004: SOAP support also removed as it was only proof of concept.
                   8005: 
                   8006: Move codebase from the PHP License to New BSD 2 clause license
                   8007:    </notes>
                   8008:   </release>
                   8009:   <release>
                   8010:    <date>2009-03-27</date>
                   8011:    <version>
                   8012:     <release>1.8.0RC1</release>
                   8013:     <api>1.8.0</api>
                   8014:    </version>
                   8015:    <stability>
                   8016:     <release>beta</release>
                   8017:     <api>stable</api>
                   8018:    </stability>
                   8019:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8020:    <notes>
                   8021: * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   8022: * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   8023: 
                   8024: * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   8025: * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   8026:    </notes>
                   8027:   </release>
                   8028:   <release>
                   8029:    <date>2009-04-10</date>
                   8030:    <version>
                   8031:     <release>1.8.0</release>
                   8032:     <api>1.8.0</api>
                   8033:    </version>
                   8034:    <stability>
                   8035:     <release>stable</release>
                   8036:     <api>stable</api>
                   8037:    </stability>
                   8038:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8039:    <notes>
                   8040: Changes since RC1:
                   8041:   * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz]
                   8042:   * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz]
                   8043:   * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz]
                   8044: 
                   8045:   Remove custom XML_Util class in favor of using upstream XML_Util package as dependency
                   8046: 
                   8047: RC1 Release Notes:
                   8048:   * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   8049:   * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   8050: 
                   8051:   * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   8052:   * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   8053: 
                   8054: Alpha1 Release Notes:
                   8055:   * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   8056:   * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   8057:   * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   8058:   * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   8059:   * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   8060:   * Implement Request #12706: pear list -a hard to read [dufuz]
                   8061:   * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   8062:   * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   8063:   * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   8064:   * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   8065:   * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   8066:     - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   8067:       better what other package managers are doing. upgrade-all will still work as intended.
                   8068:   * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   8069:     - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   8070:       channel specific upgrades
                   8071:   * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   8072:   * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   8073: 
                   8074:   * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   8075:   * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   8076: 
                   8077:   * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   8078:   * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   8079:   * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   8080:   * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   8081:   * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   8082:   * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   8083:   * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   8084:   * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   8085:   * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   8086:   * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   8087:   * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   8088:   * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   8089:   * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   8090:   * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   8091:   * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   8092:   * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   8093:   * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   8094:   * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   8095: 
                   8096:   NOTE!
                   8097:   Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   8098:   to migrate over to one of the alternatives that have ben provided:
                   8099:   * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   8100:   * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   8101:   * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   8102:   * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   8103:   * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   8104:   * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   8105:   * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   8106:   * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   8107:   * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   8108:   * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   8109:     PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   8110: 
                   8111:   PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   8112:   pear upgrade -f PEAR will allow people with lower versions
                   8113:   to upgrade to this release but no guarantees will be made that it will work properly.
                   8114: 
                   8115:   Support for XML RPC channels has been dropped - The only ones that used it
                   8116:   (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   8117:   SOAP support also removed as it was only proof of concept.
                   8118: 
                   8119:   Move codebase from the PHP License to New BSD 2 clause license
                   8120:    </notes>
                   8121:   </release>
                   8122:   <release>
                   8123:    <date>2009-04-15</date>
                   8124:    <version>
                   8125:     <release>1.8.1</release>
                   8126:     <api>1.8.1</api>
                   8127:    </version>
                   8128:    <stability>
                   8129:     <release>stable</release>
                   8130:     <api>stable</api>
                   8131:    </stability>
                   8132:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8133:    <notes>
                   8134: * Fix Bug #16099       PEAR crash on PHP4 (parse error) [dufuz]
                   8135:    </notes>
                   8136:   </release>
                   8137:   <release>
                   8138:    <date>2009-08-18</date>
                   8139:    <version>
                   8140:     <release>1.9.0RC1</release>
                   8141:     <api>1.9.0RC1</api>
                   8142:    </version>
                   8143:    <stability>
                   8144:     <release>beta</release>
                   8145:     <api>stable</api>
                   8146:    </stability>
                   8147:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8148:    <notes>
                   8149: * Implement Request #16213: add alias to list-channels output [dufuz]
                   8150: * Implement Request #16378: pear svntag [dufuz]
                   8151: * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj]
                   8152: * Implement Request #16396: package-dependencies should allow package names [dufuz]
                   8153: 
                   8154: * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz]
                   8155: * Fix Bug #14493: pear install --offline doesn&apos;t print out errors [dufuz]
                   8156: * Fix Bug #11348: pear package-dependencies isn&apos;t well explained [dufuz]
                   8157: * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz]
                   8158: * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz]
                   8159: * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz]
                   8160: * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz]
                   8161: * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj]
                   8162: * Fix Bug #16444: Setting preferred mirror fails [dufuz]
                   8163: * Fix the shutdown functions where a index might not exist and thus raise a notice [derick]
                   8164:    </notes>
                   8165:   </release>
                   8166:   <release>
                   8167:    <date>2009-08-20</date>
                   8168:    <version>
                   8169:     <release>1.9.0RC2</release>
                   8170:     <api>1.9.0RC2</api>
                   8171:    </version>
                   8172:    <stability>
                   8173:     <release>beta</release>
                   8174:     <api>stable</api>
                   8175:    </stability>
                   8176:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8177:    <notes>
                   8178: * REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz]
                   8179:    </notes>
                   8180:   </release>
                   8181:   <release>
                   8182:    <date>2009-08-21</date>
                   8183:    <version>
                   8184:     <release>1.9.0RC3</release>
                   8185:     <api>1.9.0RC3</api>
                   8186:    </version>
                   8187:    <stability>
                   8188:     <release>beta</release>
                   8189:     <api>stable</api>
                   8190:    </stability>
                   8191:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8192:    <notes>
                   8193: * Improved svntag support to handle packages like PEAR it self [dufuz]
                   8194:    </notes>
                   8195:   </release>
                   8196:   <release>
                   8197:    <date>2009-08-23</date>
                   8198:    <version>
                   8199:     <release>1.9.0RC4</release>
                   8200:     <api>1.9.0RC4</api>
                   8201:    </version>
                   8202:    <stability>
                   8203:     <release>beta</release>
                   8204:     <api>stable</api>
                   8205:    </stability>
                   8206:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8207:    <notes>
                   8208: * Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz]
                   8209: * Make sure channel aliases can&apos;t be made to start with - [dufuz]
                   8210: * Output issues with pear search [dufuz]
                   8211: * Fixed couple of stray notices [dufuz]
                   8212:    </notes>
                   8213:   </release>
                   8214:   <release>
                   8215:    <date>2009-09-03</date>
                   8216:    <version>
                   8217:     <release>1.9.0</release>
                   8218:     <api>1.9.0</api>
                   8219:    </version>
                   8220:    <stability>
                   8221:     <release>stable</release>
                   8222:     <api>stable</api>
                   8223:    </stability>
                   8224:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8225:    <notes>
                   8226: * Fix  Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz]
                   8227:    </notes>
                   8228:   </release>
                   8229:   <release>
                   8230:    <date>2010-05-26</date>
                   8231:    <version>
                   8232:     <release>1.9.1</release>
                   8233:     <api>1.9.1</api>
                   8234:    </version>
                   8235:    <stability>
                   8236:     <release>stable</release>
                   8237:     <api>stable</api>
                   8238:    </stability>
                   8239:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8240:    <notes>
                   8241: * svntag improvements, tag package files passed into the command and better directory checks [dufuz]
                   8242: * rely on Structures_Graph minimum version instead of recommended version [saltybeagle]
                   8243: * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz]
                   8244: * Fix Bug #14841: Installing pear into directory with space fails [dufuz]
                   8245: * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)]
                   8246: * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)]
                   8247: * Fix Bug #16864: &quot;pear list-upgrades -i&quot; issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)]
                   8248: * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz]
                   8249: * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz]
                   8250: * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian]
                   8251: * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz]
                   8252: * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz]
                   8253:    </notes>
                   8254:   </release>
                   8255:   <release>
                   8256:    <date>2011-02-28</date>
                   8257:    <time>18:30:00</time>
                   8258:    <version>
                   8259:     <release>1.9.2</release>
                   8260:     <api>1.9.2</api>
                   8261:    </version>
                   8262:    <stability>
                   8263:     <release>stable</release>
                   8264:     <api>stable</api>
                   8265:    </stability>
                   8266:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8267:    <notes>
                   8268: Important! This is a security fix release. The advisory can be found at
                   8269: http://pear.php.net/advisory-20110228.txt
                   8270: 
                   8271:     Bugs:
                   8272:     * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor]
                   8273:     * Fixed Bug #17641: pecl-list doesn&apos;t sort packages by name [dufuz]
                   8274:     * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz]
                   8275:     * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)]
                   8276:     * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz]
                   8277:     * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz]
                   8278:     * Fixed Bug #17997: Strange output if directories are not writeable [dufuz]
                   8279:     * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz]
                   8280:     * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz]
                   8281:     * Fixed Bug #18218: &quot;pear package&quot; does not allow the use of late static binding [dufuz and Christer Edvartsen]
                   8282:     * Fixed Bug #18238: Wrong return code from &quot;pear help&quot; [till]
                   8283:     * Fixed Bug #18308: Broken error message about missing channel validator [yunosh]
                   8284: 
                   8285:     This feature is implemented as a result of #18056
                   8286:     * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz]
                   8287:    </notes>
                   8288:   </release>
                   8289:   <release>
                   8290:    <date>2011-06-04</date>
                   8291:    <time>15:30:00</time>
                   8292:    <version>
                   8293:     <release>1.9.3</release>
                   8294:     <api>1.9.2</api>
                   8295:    </version>
                   8296:    <stability>
                   8297:     <release>stable</release>
                   8298:     <api>stable</api>
                   8299:    </stability>
                   8300:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8301:    <notes>
                   8302: * Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz]
                   8303: * Fixed Bug #18340: raiseErro typo [doconnor]
                   8304: * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz]
                   8305: * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz]
                   8306: * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz]
                   8307: * Fixed Bug #18428: invalid preg_match patterns [glen]
                   8308: * Fixed Bug #18486: REST/10.php does not check error condition [dufuz]
                   8309: * Fixed a problem in RunTest and code coverage. Correctly register the
                   8310:   code coverage shutdown function in case we are inside a namespace. [sebastian]
                   8311: * Fixed a bug with extensions not providing their config.m4 and co in the root directory of
                   8312:   their pecl package but rather in a sub directory, such as xhprof. [dufuz]
                   8313:    </notes>
                   8314:   </release>
                   8315:  </changelog>
                   8316: </package>
                   8317: PEAR-1.9.4/OS/Guess.php0000644000076500000240000002463411605156760013367 0ustar  helgistaff<?php
                   8318: /**
                   8319:  * The OS_Guess class
                   8320:  *
                   8321:  * PHP versions 4 and 5
                   8322:  *
                   8323:  * @category   pear
                   8324:  * @package    PEAR
                   8325:  * @author     Stig Bakken <ssb@php.net>
                   8326:  * @author     Gregory Beaver <cellog@php.net>
                   8327:  * @copyright  1997-2009 The Authors
                   8328:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8329:  * @version    CVS: $Id: Guess.php 313023 2011-07-06 19:17:11Z dufuz $
                   8330:  * @link       http://pear.php.net/package/PEAR
                   8331:  * @since      File available since PEAR 0.1
                   8332:  */
                   8333: 
                   8334: // {{{ uname examples
                   8335: 
                   8336: // php_uname() without args returns the same as 'uname -a', or a PHP-custom
                   8337: // string for Windows.
                   8338: // PHP versions prior to 4.3 return the uname of the host where PHP was built,
                   8339: // as of 4.3 it returns the uname of the host running the PHP code.
                   8340: //
                   8341: // PC RedHat Linux 7.1:
                   8342: // Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
                   8343: //
                   8344: // PC Debian Potato:
                   8345: // Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
                   8346: //
                   8347: // PC FreeBSD 3.3:
                   8348: // 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
                   8349: //
                   8350: // PC FreeBSD 4.3:
                   8351: // 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
                   8352: //
                   8353: // PC FreeBSD 4.5:
                   8354: // 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
                   8355: //
                   8356: // PC FreeBSD 4.5 w/uname from GNU shellutils:
                   8357: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
                   8358: //
                   8359: // HP 9000/712 HP-UX 10:
                   8360: // HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
                   8361: //
                   8362: // HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
                   8363: // HP-UX host B.10.10 A 9000/712 unknown
                   8364: //
                   8365: // IBM RS6000/550 AIX 4.3:
                   8366: // AIX host 3 4 000003531C00
                   8367: //
                   8368: // AIX 4.3 w/uname from GNU shellutils:
                   8369: // AIX host 3 4 000003531C00 unknown
                   8370: //
                   8371: // SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
                   8372: // IRIX64 host 6.5 01091820 IP19 mips
                   8373: //
                   8374: // SGI Onyx IRIX 6.5:
                   8375: // IRIX64 host 6.5 01091820 IP19
                   8376: //
                   8377: // SparcStation 20 Solaris 8 w/uname from GNU shellutils:
                   8378: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
                   8379: //
                   8380: // SparcStation 20 Solaris 8:
                   8381: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
                   8382: //
                   8383: // Mac OS X (Darwin)
                   8384: // 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
                   8385: //
                   8386: // Mac OS X early versions
                   8387: //
                   8388: 
                   8389: // }}}
                   8390: 
                   8391: /* TODO:
                   8392:  * - define endianness, to allow matchSignature("bigend") etc.
                   8393:  */
                   8394: 
                   8395: /**
                   8396:  * Retrieves information about the current operating system
                   8397:  *
                   8398:  * This class uses php_uname() to grok information about the current OS
                   8399:  *
                   8400:  * @category   pear
                   8401:  * @package    PEAR
                   8402:  * @author     Stig Bakken <ssb@php.net>
                   8403:  * @author     Gregory Beaver <cellog@php.net>
                   8404:  * @copyright  1997-2009 The Authors
                   8405:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8406:  * @version    Release: 1.9.4
                   8407:  * @link       http://pear.php.net/package/PEAR
                   8408:  * @since      Class available since Release 0.1
                   8409:  */
                   8410: class OS_Guess
                   8411: {
                   8412:     var $sysname;
                   8413:     var $nodename;
                   8414:     var $cpu;
                   8415:     var $release;
                   8416:     var $extra;
                   8417: 
                   8418:     function OS_Guess($uname = null)
                   8419:     {
                   8420:         list($this->sysname,
                   8421:              $this->release,
                   8422:              $this->cpu,
                   8423:              $this->extra,
                   8424:              $this->nodename) = $this->parseSignature($uname);
                   8425:     }
                   8426: 
                   8427:     function parseSignature($uname = null)
                   8428:     {
                   8429:         static $sysmap = array(
                   8430:             'HP-UX' => 'hpux',
                   8431:             'IRIX64' => 'irix',
                   8432:         );
                   8433:         static $cpumap = array(
                   8434:             'i586' => 'i386',
                   8435:             'i686' => 'i386',
                   8436:             'ppc' => 'powerpc',
                   8437:         );
                   8438:         if ($uname === null) {
                   8439:             $uname = php_uname();
                   8440:         }
                   8441:         $parts = preg_split('/\s+/', trim($uname));
                   8442:         $n = count($parts);
                   8443: 
                   8444:         $release  = $machine = $cpu = '';
                   8445:         $sysname  = $parts[0];
                   8446:         $nodename = $parts[1];
                   8447:         $cpu      = $parts[$n-1];
                   8448:         $extra = '';
                   8449:         if ($cpu == 'unknown') {
                   8450:             $cpu = $parts[$n - 2];
                   8451:         }
                   8452: 
                   8453:         switch ($sysname) {
                   8454:             case 'AIX' :
                   8455:                 $release = "$parts[3].$parts[2]";
                   8456:                 break;
                   8457:             case 'Windows' :
                   8458:                 switch ($parts[1]) {
                   8459:                     case '95/98':
                   8460:                         $release = '9x';
                   8461:                         break;
                   8462:                     default:
                   8463:                         $release = $parts[1];
                   8464:                         break;
                   8465:                 }
                   8466:                 $cpu = 'i386';
                   8467:                 break;
                   8468:             case 'Linux' :
                   8469:                 $extra = $this->_detectGlibcVersion();
                   8470:                 // use only the first two digits from the kernel version
                   8471:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   8472:                 break;
                   8473:             case 'Mac' :
                   8474:                 $sysname = 'darwin';
                   8475:                 $nodename = $parts[2];
                   8476:                 $release = $parts[3];
                   8477:                 if ($cpu == 'Macintosh') {
                   8478:                     if ($parts[$n - 2] == 'Power') {
                   8479:                         $cpu = 'powerpc';
                   8480:                     }
                   8481:                 }
                   8482:                 break;
                   8483:             case 'Darwin' :
                   8484:                 if ($cpu == 'Macintosh') {
                   8485:                     if ($parts[$n - 2] == 'Power') {
                   8486:                         $cpu = 'powerpc';
                   8487:                     }
                   8488:                 }
                   8489:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   8490:                 break;
                   8491:             default:
                   8492:                 $release = preg_replace('/-.*/', '', $parts[2]);
                   8493:                 break;
                   8494:         }
                   8495: 
                   8496:         if (isset($sysmap[$sysname])) {
                   8497:             $sysname = $sysmap[$sysname];
                   8498:         } else {
                   8499:             $sysname = strtolower($sysname);
                   8500:         }
                   8501:         if (isset($cpumap[$cpu])) {
                   8502:             $cpu = $cpumap[$cpu];
                   8503:         }
                   8504:         return array($sysname, $release, $cpu, $extra, $nodename);
                   8505:     }
                   8506: 
                   8507:     function _detectGlibcVersion()
                   8508:     {
                   8509:         static $glibc = false;
                   8510:         if ($glibc !== false) {
                   8511:             return $glibc; // no need to run this multiple times
                   8512:         }
                   8513:         $major = $minor = 0;
                   8514:         include_once "System.php";
                   8515:         // Use glibc's <features.h> header file to
                   8516:         // get major and minor version number:
                   8517:         if (@file_exists('/usr/include/features.h') &&
                   8518:               @is_readable('/usr/include/features.h')) {
                   8519:             if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
                   8520:                 $features_file = fopen('/usr/include/features.h', 'rb');
                   8521:                 while (!feof($features_file)) {
                   8522:                     $line = fgets($features_file, 8192);
                   8523:                     if (!$line || (strpos($line, '#define') === false)) {
                   8524:                         continue;
                   8525:                     }
                   8526:                     if (strpos($line, '__GLIBC__')) {
                   8527:                         // major version number #define __GLIBC__ version
                   8528:                         $line = preg_split('/\s+/', $line);
                   8529:                         $glibc_major = trim($line[2]);
                   8530:                         if (isset($glibc_minor)) {
                   8531:                             break;
                   8532:                         }
                   8533:                         continue;
                   8534:                     }
                   8535: 
                   8536:                     if (strpos($line, '__GLIBC_MINOR__'))  {
                   8537:                         // got the minor version number
                   8538:                         // #define __GLIBC_MINOR__ version
                   8539:                         $line = preg_split('/\s+/', $line);
                   8540:                         $glibc_minor = trim($line[2]);
                   8541:                         if (isset($glibc_major)) {
                   8542:                             break;
                   8543:                         }
                   8544:                         continue;
                   8545:                     }
                   8546:                 }
                   8547:                 fclose($features_file);
                   8548:                 if (!isset($glibc_major) || !isset($glibc_minor)) {
                   8549:                     return $glibc = '';
                   8550:                 }
                   8551:                 return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
                   8552:             } // no cpp
                   8553: 
                   8554:             $tmpfile = System::mktemp("glibctest");
                   8555:             $fp = fopen($tmpfile, "w");
                   8556:             fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
                   8557:             fclose($fp);
                   8558:             $cpp = popen("/usr/bin/cpp $tmpfile", "r");
                   8559:             while ($line = fgets($cpp, 1024)) {
                   8560:                 if ($line{0} == '#' || trim($line) == '') {
                   8561:                     continue;
                   8562:                 }
                   8563: 
                   8564:                 if (list($major, $minor) = explode(' ', trim($line))) {
                   8565:                     break;
                   8566:                 }
                   8567:             }
                   8568:             pclose($cpp);
                   8569:             unlink($tmpfile);
                   8570:         } // features.h
                   8571: 
                   8572:         if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
                   8573:             // Let's try reading the libc.so.6 symlink
                   8574:             if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
                   8575:                 list($major, $minor) = explode('.', $matches[1]);
                   8576:             }
                   8577:         }
                   8578: 
                   8579:         if (!($major && $minor)) {
                   8580:             return $glibc = '';
                   8581:         }
                   8582: 
                   8583:         return $glibc = "glibc{$major}.{$minor}";
                   8584:     }
                   8585: 
                   8586:     function getSignature()
                   8587:     {
                   8588:         if (empty($this->extra)) {
                   8589:             return "{$this->sysname}-{$this->release}-{$this->cpu}";
                   8590:         }
                   8591:         return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
                   8592:     }
                   8593: 
                   8594:     function getSysname()
                   8595:     {
                   8596:         return $this->sysname;
                   8597:     }
                   8598: 
                   8599:     function getNodename()
                   8600:     {
                   8601:         return $this->nodename;
                   8602:     }
                   8603: 
                   8604:     function getCpu()
                   8605:     {
                   8606:         return $this->cpu;
                   8607:     }
                   8608: 
                   8609:     function getRelease()
                   8610:     {
                   8611:         return $this->release;
                   8612:     }
                   8613: 
                   8614:     function getExtra()
                   8615:     {
                   8616:         return $this->extra;
                   8617:     }
                   8618: 
                   8619:     function matchSignature($match)
                   8620:     {
                   8621:         $fragments = is_array($match) ? $match : explode('-', $match);
                   8622:         $n = count($fragments);
                   8623:         $matches = 0;
                   8624:         if ($n > 0) {
                   8625:             $matches += $this->_matchFragment($fragments[0], $this->sysname);
                   8626:         }
                   8627:         if ($n > 1) {
                   8628:             $matches += $this->_matchFragment($fragments[1], $this->release);
                   8629:         }
                   8630:         if ($n > 2) {
                   8631:             $matches += $this->_matchFragment($fragments[2], $this->cpu);
                   8632:         }
                   8633:         if ($n > 3) {
                   8634:             $matches += $this->_matchFragment($fragments[3], $this->extra);
                   8635:         }
                   8636:         return ($matches == $n);
                   8637:     }
                   8638: 
                   8639:     function _matchFragment($fragment, $value)
                   8640:     {
                   8641:         if (strcspn($fragment, '*?') < strlen($fragment)) {
                   8642:             $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
                   8643:             return preg_match($reg, $value);
                   8644:         }
                   8645:         return ($fragment == '*' || !strcasecmp($fragment, $value));
                   8646:     }
                   8647: 
                   8648: }
                   8649: /*
                   8650:  * Local Variables:
                   8651:  * indent-tabs-mode: nil
                   8652:  * c-basic-offset: 4
                   8653:  * End:
                   8654:  */PEAR-1.9.4/PEAR/ChannelFile/Parser.php0000644000076500000240000000336211605156760016106 0ustar  helgistaff<?php
                   8655: /**
                   8656:  * PEAR_ChannelFile_Parser for parsing channel.xml
                   8657:  *
                   8658:  * PHP versions 4 and 5
                   8659:  *
                   8660:  * @category   pear
                   8661:  * @package    PEAR
                   8662:  * @author     Greg Beaver <cellog@php.net>
                   8663:  * @copyright  1997-2009 The Authors
                   8664:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8665:  * @version    CVS: $Id: Parser.php 313023 2011-07-06 19:17:11Z dufuz $
                   8666:  * @link       http://pear.php.net/package/PEAR
                   8667:  * @since      File available since Release 1.4.0a1
                   8668:  */
                   8669: 
                   8670: /**
                   8671:  * base xml parser class
                   8672:  */
                   8673: require_once 'PEAR/XMLParser.php';
                   8674: require_once 'PEAR/ChannelFile.php';
                   8675: /**
                   8676:  * Parser for channel.xml
                   8677:  * @category   pear
                   8678:  * @package    PEAR
                   8679:  * @author     Greg Beaver <cellog@php.net>
                   8680:  * @copyright  1997-2009 The Authors
                   8681:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8682:  * @version    Release: 1.9.4
                   8683:  * @link       http://pear.php.net/package/PEAR
                   8684:  * @since      Class available since Release 1.4.0a1
                   8685:  */
                   8686: class PEAR_ChannelFile_Parser extends PEAR_XMLParser
                   8687: {
                   8688:     var $_config;
                   8689:     var $_logger;
                   8690:     var $_registry;
                   8691: 
                   8692:     function setConfig(&$c)
                   8693:     {
                   8694:         $this->_config = &$c;
                   8695:         $this->_registry = &$c->getRegistry();
                   8696:     }
                   8697: 
                   8698:     function setLogger(&$l)
                   8699:     {
                   8700:         $this->_logger = &$l;
                   8701:     }
                   8702: 
                   8703:     function parse($data, $file)
                   8704:     {
                   8705:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   8706:             return $err;
                   8707:         }
                   8708: 
                   8709:         $ret = new PEAR_ChannelFile;
                   8710:         $ret->setConfig($this->_config);
                   8711:         if (isset($this->_logger)) {
                   8712:             $ret->setLogger($this->_logger);
                   8713:         }
                   8714: 
                   8715:         $ret->fromArray($this->_unserializedData);
                   8716:         // make sure the filelist is in the easy to read format needed
                   8717:         $ret->flattenFilelist();
                   8718:         $ret->setPackagefile($file, $archive);
                   8719:         return $ret;
                   8720:     }
                   8721: }PEAR-1.9.4/PEAR/Command/Auth.xml0000644000076500000240000000231411605156760014766 0ustar  helgistaff<commands version="1.0">
                   8722:  <login>
                   8723:   <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
                   8724:   <function>doLogin</function>
                   8725:   <shortcut>li</shortcut>
                   8726:   <options />
                   8727:   <doc>&lt;channel name&gt;
                   8728: WARNING: This function is deprecated in favor of using channel-login
                   8729: 
                   8730: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
                   8731: the default channel is used. To use remote functions in the installer
                   8732: that require any kind of privileges, you need to log in first.  The
                   8733: username and password you enter here will be stored in your per-user
                   8734: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   8735: in, your username and password will be sent along in subsequent
                   8736: operations on the remote server.</doc>
                   8737:  </login>
                   8738:  <logout>
                   8739:   <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
                   8740:   <function>doLogout</function>
                   8741:   <shortcut>lo</shortcut>
                   8742:   <options />
                   8743:   <doc>
                   8744: WARNING: This function is deprecated in favor of using channel-logout
                   8745: 
                   8746: Logs out from the remote server.  This command does not actually
                   8747: connect to the remote server, it only deletes the stored username and
                   8748: password from your user configuration.</doc>
                   8749:  </logout>
                   8750: </commands>PEAR-1.9.4/PEAR/Command/Auth.php0000644000076500000240000000513611605156760014762 0ustar  helgistaff<?php
                   8751: /**
                   8752:  * PEAR_Command_Auth (login, logout commands)
                   8753:  *
                   8754:  * PHP versions 4 and 5
                   8755:  *
                   8756:  * @category   pear
                   8757:  * @package    PEAR
                   8758:  * @author     Stig Bakken <ssb@php.net>
                   8759:  * @author     Greg Beaver <cellog@php.net>
                   8760:  * @copyright  1997-2009 The Authors
                   8761:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8762:  * @version    CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
                   8763:  * @link       http://pear.php.net/package/PEAR
                   8764:  * @since      File available since Release 0.1
                   8765:  * @deprecated since 1.8.0alpha1
                   8766:  */
                   8767: 
                   8768: /**
                   8769:  * base class
                   8770:  */
                   8771: require_once 'PEAR/Command/Channels.php';
                   8772: 
                   8773: /**
                   8774:  * PEAR commands for login/logout
                   8775:  *
                   8776:  * @category   pear
                   8777:  * @package    PEAR
                   8778:  * @author     Stig Bakken <ssb@php.net>
                   8779:  * @author     Greg Beaver <cellog@php.net>
                   8780:  * @copyright  1997-2009 The Authors
                   8781:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8782:  * @version    Release: 1.9.4
                   8783:  * @link       http://pear.php.net/package/PEAR
                   8784:  * @since      Class available since Release 0.1
                   8785:  * @deprecated since 1.8.0alpha1
                   8786:  */
                   8787: class PEAR_Command_Auth extends PEAR_Command_Channels
                   8788: {
                   8789:     var $commands = array(
                   8790:         'login' => array(
                   8791:             'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
                   8792:             'shortcut' => 'li',
                   8793:             'function' => 'doLogin',
                   8794:             'options' => array(),
                   8795:             'doc' => '<channel name>
                   8796: WARNING: This function is deprecated in favor of using channel-login
                   8797: 
                   8798: Log in to a remote channel server.  If <channel name> is not supplied,
                   8799: the default channel is used. To use remote functions in the installer
                   8800: that require any kind of privileges, you need to log in first.  The
                   8801: username and password you enter here will be stored in your per-user
                   8802: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   8803: in, your username and password will be sent along in subsequent
                   8804: operations on the remote server.',
                   8805:             ),
                   8806:         'logout' => array(
                   8807:             'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
                   8808:             'shortcut' => 'lo',
                   8809:             'function' => 'doLogout',
                   8810:             'options' => array(),
                   8811:             'doc' => '
                   8812: WARNING: This function is deprecated in favor of using channel-logout
                   8813: 
                   8814: Logs out from the remote server.  This command does not actually
                   8815: connect to the remote server, it only deletes the stored username and
                   8816: password from your user configuration.',
                   8817:             )
                   8818: 
                   8819:         );
                   8820: 
                   8821:     /**
                   8822:      * PEAR_Command_Auth constructor.
                   8823:      *
                   8824:      * @access public
                   8825:      */
                   8826:     function PEAR_Command_Auth(&$ui, &$config)
                   8827:     {
                   8828:         parent::PEAR_Command_Channels($ui, $config);
                   8829:     }
                   8830: }PEAR-1.9.4/PEAR/Command/Build.xml0000644000076500000240000000040411605156760015122 0ustar  helgistaff<commands version="1.0">
                   8831:  <build>
                   8832:   <summary>Build an Extension From C Source</summary>
                   8833:   <function>doBuild</function>
                   8834:   <shortcut>b</shortcut>
                   8835:   <options />
                   8836:   <doc>[package.xml]
                   8837: Builds one or more extensions contained in a package.</doc>
                   8838:  </build>
                   8839: </commands>PEAR-1.9.4/PEAR/Command/Build.php0000644000076500000240000000445311605156760015121 0ustar  helgistaff<?php
                   8840: /**
                   8841:  * PEAR_Command_Auth (build command)
                   8842:  *
                   8843:  * PHP versions 4 and 5
                   8844:  *
                   8845:  * @category   pear
                   8846:  * @package    PEAR
                   8847:  * @author     Stig Bakken <ssb@php.net>
                   8848:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   8849:  * @author     Greg Beaver <cellog@php.net>
                   8850:  * @copyright  1997-2009 The Authors
                   8851:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8852:  * @version    CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
                   8853:  * @link       http://pear.php.net/package/PEAR
                   8854:  * @since      File available since Release 0.1
                   8855:  */
                   8856: 
                   8857: /**
                   8858:  * base class
                   8859:  */
                   8860: require_once 'PEAR/Command/Common.php';
                   8861: 
                   8862: /**
                   8863:  * PEAR commands for building extensions.
                   8864:  *
                   8865:  * @category   pear
                   8866:  * @package    PEAR
                   8867:  * @author     Stig Bakken <ssb@php.net>
                   8868:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   8869:  * @author     Greg Beaver <cellog@php.net>
                   8870:  * @copyright  1997-2009 The Authors
                   8871:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8872:  * @version    Release: 1.9.4
                   8873:  * @link       http://pear.php.net/package/PEAR
                   8874:  * @since      Class available since Release 0.1
                   8875:  */
                   8876: class PEAR_Command_Build extends PEAR_Command_Common
                   8877: {
                   8878:     var $commands = array(
                   8879:         'build' => array(
                   8880:             'summary' => 'Build an Extension From C Source',
                   8881:             'function' => 'doBuild',
                   8882:             'shortcut' => 'b',
                   8883:             'options' => array(),
                   8884:             'doc' => '[package.xml]
                   8885: Builds one or more extensions contained in a package.'
                   8886:             ),
                   8887:         );
                   8888: 
                   8889:     /**
                   8890:      * PEAR_Command_Build constructor.
                   8891:      *
                   8892:      * @access public
                   8893:      */
                   8894:     function PEAR_Command_Build(&$ui, &$config)
                   8895:     {
                   8896:         parent::PEAR_Command_Common($ui, $config);
                   8897:     }
                   8898: 
                   8899:     function doBuild($command, $options, $params)
                   8900:     {
                   8901:         require_once 'PEAR/Builder.php';
                   8902:         if (sizeof($params) < 1) {
                   8903:             $params[0] = 'package.xml';
                   8904:         }
                   8905: 
                   8906:         $builder = &new PEAR_Builder($this->ui);
                   8907:         $this->debug = $this->config->get('verbose');
                   8908:         $err = $builder->build($params[0], array(&$this, 'buildCallback'));
                   8909:         if (PEAR::isError($err)) {
                   8910:             return $err;
                   8911:         }
                   8912: 
                   8913:         return true;
                   8914:     }
                   8915: 
                   8916:     function buildCallback($what, $data)
                   8917:     {
                   8918:         if (($what == 'cmdoutput' && $this->debug > 1) ||
                   8919:             ($what == 'output' && $this->debug > 0)) {
                   8920:             $this->ui->outputData(rtrim($data), 'build');
                   8921:         }
                   8922:     }
                   8923: }PEAR-1.9.4/PEAR/Command/Channels.xml0000644000076500000240000001017211605156760015621 0ustar  helgistaff<commands version="1.0">
                   8924:  <list-channels>
                   8925:   <summary>List Available Channels</summary>
                   8926:   <function>doList</function>
                   8927:   <shortcut>lc</shortcut>
                   8928:   <options />
                   8929:   <doc>
                   8930: List all available channels for installation.
                   8931: </doc>
                   8932:  </list-channels>
                   8933:  <update-channels>
                   8934:   <summary>Update the Channel List</summary>
                   8935:   <function>doUpdateAll</function>
                   8936:   <shortcut>uc</shortcut>
                   8937:   <options />
                   8938:   <doc>
                   8939: List all installed packages in all channels.
                   8940: </doc>
                   8941:  </update-channels>
                   8942:  <channel-delete>
                   8943:   <summary>Remove a Channel From the List</summary>
                   8944:   <function>doDelete</function>
                   8945:   <shortcut>cde</shortcut>
                   8946:   <options />
                   8947:   <doc>&lt;channel name&gt;
                   8948: Delete a channel from the registry.  You may not
                   8949: remove any channel that has installed packages.
                   8950: </doc>
                   8951:  </channel-delete>
                   8952:  <channel-add>
                   8953:   <summary>Add a Channel</summary>
                   8954:   <function>doAdd</function>
                   8955:   <shortcut>ca</shortcut>
                   8956:   <options />
                   8957:   <doc>&lt;channel.xml&gt;
                   8958: Add a private channel to the channel list.  Note that all
                   8959: public channels should be synced using &quot;update-channels&quot;.
                   8960: Parameter may be either a local file or remote URL to a
                   8961: channel.xml.
                   8962: </doc>
                   8963:  </channel-add>
                   8964:  <channel-update>
                   8965:   <summary>Update an Existing Channel</summary>
                   8966:   <function>doUpdate</function>
                   8967:   <shortcut>cu</shortcut>
                   8968:   <options>
                   8969:    <force>
                   8970:     <shortopt>f</shortopt>
                   8971:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
                   8972:    </force>
                   8973:    <channel>
                   8974:     <shortopt>c</shortopt>
                   8975:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
                   8976:     <arg>CHANNEL</arg>
                   8977:    </channel>
                   8978:   </options>
                   8979:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
                   8980: Update a channel in the channel list directly.  Note that all
                   8981: public channels can be synced using &quot;update-channels&quot;.
                   8982: Parameter may be a local or remote channel.xml, or the name of
                   8983: an existing channel.
                   8984: </doc>
                   8985:  </channel-update>
                   8986:  <channel-info>
                   8987:   <summary>Retrieve Information on a Channel</summary>
                   8988:   <function>doInfo</function>
                   8989:   <shortcut>ci</shortcut>
                   8990:   <options />
                   8991:   <doc>&lt;package&gt;
                   8992: List the files in an installed package.
                   8993: </doc>
                   8994:  </channel-info>
                   8995:  <channel-alias>
                   8996:   <summary>Specify an alias to a channel name</summary>
                   8997:   <function>doAlias</function>
                   8998:   <shortcut>cha</shortcut>
                   8999:   <options />
                   9000:   <doc>&lt;channel&gt; &lt;alias&gt;
                   9001: Specify a specific alias to use for a channel name.
                   9002: The alias may not be an existing channel name or
                   9003: alias.
                   9004: </doc>
                   9005:  </channel-alias>
                   9006:  <channel-discover>
                   9007:   <summary>Initialize a Channel from its server</summary>
                   9008:   <function>doDiscover</function>
                   9009:   <shortcut>di</shortcut>
                   9010:   <options />
                   9011:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
                   9012: Initialize a channel from its server and create a local channel.xml.
                   9013: If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
                   9014: &lt;username&gt; and &lt;password&gt; will be set as the login username/password for
                   9015: &lt;channel&gt;. Use caution when passing the username/password in this way, as
                   9016: it may allow other users on your computer to briefly view your username/
                   9017: password via the system&#039;s process list.
                   9018: </doc>
                   9019:  </channel-discover>
                   9020:  <channel-login>
                   9021:   <summary>Connects and authenticates to remote channel server</summary>
                   9022:   <function>doLogin</function>
                   9023:   <shortcut>cli</shortcut>
                   9024:   <options />
                   9025:   <doc>&lt;channel name&gt;
                   9026: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
                   9027: the default channel is used. To use remote functions in the installer
                   9028: that require any kind of privileges, you need to log in first.  The
                   9029: username and password you enter here will be stored in your per-user
                   9030: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9031: in, your username and password will be sent along in subsequent
                   9032: operations on the remote server.</doc>
                   9033:  </channel-login>
                   9034:  <channel-logout>
                   9035:   <summary>Logs out from the remote channel server</summary>
                   9036:   <function>doLogout</function>
                   9037:   <shortcut>clo</shortcut>
                   9038:   <options />
                   9039:   <doc>&lt;channel name&gt;
                   9040: Logs out from a remote channel server.  If &lt;channel name&gt; is not supplied,
                   9041: the default channel is used. This command does not actually connect to the
                   9042: remote server, it only deletes the stored username and password from your user
                   9043: configuration.</doc>
                   9044:  </channel-logout>
                   9045: </commands>PEAR-1.9.4/PEAR/Command/Channels.php0000644000076500000240000010137711605156760015620 0ustar  helgistaff<?php
                   9046: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   9047: /**
                   9048:  * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
                   9049:  * channel-update, channel-info, channel-alias, channel-discover commands)
                   9050:  *
                   9051:  * PHP versions 4 and 5
                   9052:  *
                   9053:  * @category   pear
                   9054:  * @package    PEAR
                   9055:  * @author     Stig Bakken <ssb@php.net>
                   9056:  * @author     Greg Beaver <cellog@php.net>
                   9057:  * @copyright  1997-2009 The Authors
                   9058:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9059:  * @version    CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
                   9060:  * @link       http://pear.php.net/package/PEAR
                   9061:  * @since      File available since Release 1.4.0a1
                   9062:  */
                   9063: 
                   9064: /**
                   9065:  * base class
                   9066:  */
                   9067: require_once 'PEAR/Command/Common.php';
                   9068: 
                   9069: define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
                   9070: 
                   9071: /**
                   9072:  * PEAR commands for managing channels.
                   9073:  *
                   9074:  * @category   pear
                   9075:  * @package    PEAR
                   9076:  * @author     Greg Beaver <cellog@php.net>
                   9077:  * @copyright  1997-2009 The Authors
                   9078:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9079:  * @version    Release: 1.9.4
                   9080:  * @link       http://pear.php.net/package/PEAR
                   9081:  * @since      Class available since Release 1.4.0a1
                   9082:  */
                   9083: class PEAR_Command_Channels extends PEAR_Command_Common
                   9084: {
                   9085:     var $commands = array(
                   9086:         'list-channels' => array(
                   9087:             'summary' => 'List Available Channels',
                   9088:             'function' => 'doList',
                   9089:             'shortcut' => 'lc',
                   9090:             'options' => array(),
                   9091:             'doc' => '
                   9092: List all available channels for installation.
                   9093: ',
                   9094:             ),
                   9095:         'update-channels' => array(
                   9096:             'summary' => 'Update the Channel List',
                   9097:             'function' => 'doUpdateAll',
                   9098:             'shortcut' => 'uc',
                   9099:             'options' => array(),
                   9100:             'doc' => '
                   9101: List all installed packages in all channels.
                   9102: '
                   9103:             ),
                   9104:         'channel-delete' => array(
                   9105:             'summary' => 'Remove a Channel From the List',
                   9106:             'function' => 'doDelete',
                   9107:             'shortcut' => 'cde',
                   9108:             'options' => array(),
                   9109:             'doc' => '<channel name>
                   9110: Delete a channel from the registry.  You may not
                   9111: remove any channel that has installed packages.
                   9112: '
                   9113:             ),
                   9114:         'channel-add' => array(
                   9115:             'summary' => 'Add a Channel',
                   9116:             'function' => 'doAdd',
                   9117:             'shortcut' => 'ca',
                   9118:             'options' => array(),
                   9119:             'doc' => '<channel.xml>
                   9120: Add a private channel to the channel list.  Note that all
                   9121: public channels should be synced using "update-channels".
                   9122: Parameter may be either a local file or remote URL to a
                   9123: channel.xml.
                   9124: '
                   9125:             ),
                   9126:         'channel-update' => array(
                   9127:             'summary' => 'Update an Existing Channel',
                   9128:             'function' => 'doUpdate',
                   9129:             'shortcut' => 'cu',
                   9130:             'options' => array(
                   9131:                 'force' => array(
                   9132:                     'shortopt' => 'f',
                   9133:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
                   9134:                     ),
                   9135:                 'channel' => array(
                   9136:                     'shortopt' => 'c',
                   9137:                     'arg' => 'CHANNEL',
                   9138:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
                   9139:                     ),
                   9140: ),
                   9141:             'doc' => '[<channel.xml>|<channel name>]
                   9142: Update a channel in the channel list directly.  Note that all
                   9143: public channels can be synced using "update-channels".
                   9144: Parameter may be a local or remote channel.xml, or the name of
                   9145: an existing channel.
                   9146: '
                   9147:             ),
                   9148:         'channel-info' => array(
                   9149:             'summary' => 'Retrieve Information on a Channel',
                   9150:             'function' => 'doInfo',
                   9151:             'shortcut' => 'ci',
                   9152:             'options' => array(),
                   9153:             'doc' => '<package>
                   9154: List the files in an installed package.
                   9155: '
                   9156:             ),
                   9157:         'channel-alias' => array(
                   9158:             'summary' => 'Specify an alias to a channel name',
                   9159:             'function' => 'doAlias',
                   9160:             'shortcut' => 'cha',
                   9161:             'options' => array(),
                   9162:             'doc' => '<channel> <alias>
                   9163: Specify a specific alias to use for a channel name.
                   9164: The alias may not be an existing channel name or
                   9165: alias.
                   9166: '
                   9167:             ),
                   9168:         'channel-discover' => array(
                   9169:             'summary' => 'Initialize a Channel from its server',
                   9170:             'function' => 'doDiscover',
                   9171:             'shortcut' => 'di',
                   9172:             'options' => array(),
                   9173:             'doc' => '[<channel.xml>|<channel name>]
                   9174: Initialize a channel from its server and create a local channel.xml.
                   9175: If <channel name> is in the format "<username>:<password>@<channel>" then
                   9176: <username> and <password> will be set as the login username/password for
                   9177: <channel>. Use caution when passing the username/password in this way, as
                   9178: it may allow other users on your computer to briefly view your username/
                   9179: password via the system\'s process list.
                   9180: '
                   9181:             ),
                   9182:         'channel-login' => array(
                   9183:             'summary' => 'Connects and authenticates to remote channel server',
                   9184:             'shortcut' => 'cli',
                   9185:             'function' => 'doLogin',
                   9186:             'options' => array(),
                   9187:             'doc' => '<channel name>
                   9188: Log in to a remote channel server.  If <channel name> is not supplied,
                   9189: the default channel is used. To use remote functions in the installer
                   9190: that require any kind of privileges, you need to log in first.  The
                   9191: username and password you enter here will be stored in your per-user
                   9192: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9193: in, your username and password will be sent along in subsequent
                   9194: operations on the remote server.',
                   9195:             ),
                   9196:         'channel-logout' => array(
                   9197:             'summary' => 'Logs out from the remote channel server',
                   9198:             'shortcut' => 'clo',
                   9199:             'function' => 'doLogout',
                   9200:             'options' => array(),
                   9201:             'doc' => '<channel name>
                   9202: Logs out from a remote channel server.  If <channel name> is not supplied,
                   9203: the default channel is used. This command does not actually connect to the
                   9204: remote server, it only deletes the stored username and password from your user
                   9205: configuration.',
                   9206:             ),
                   9207:         );
                   9208: 
                   9209:     /**
                   9210:      * PEAR_Command_Registry constructor.
                   9211:      *
                   9212:      * @access public
                   9213:      */
                   9214:     function PEAR_Command_Channels(&$ui, &$config)
                   9215:     {
                   9216:         parent::PEAR_Command_Common($ui, $config);
                   9217:     }
                   9218: 
                   9219:     function _sortChannels($a, $b)
                   9220:     {
                   9221:         return strnatcasecmp($a->getName(), $b->getName());
                   9222:     }
                   9223: 
                   9224:     function doList($command, $options, $params)
                   9225:     {
                   9226:         $reg = &$this->config->getRegistry();
                   9227:         $registered = $reg->getChannels();
                   9228:         usort($registered, array(&$this, '_sortchannels'));
                   9229:         $i = $j = 0;
                   9230:         $data = array(
                   9231:             'caption' => 'Registered Channels:',
                   9232:             'border' => true,
                   9233:             'headline' => array('Channel', 'Alias', 'Summary')
                   9234:             );
                   9235:         foreach ($registered as $channel) {
                   9236:             $data['data'][] = array($channel->getName(),
                   9237:                                     $channel->getAlias(),
                   9238:                                     $channel->getSummary());
                   9239:         }
                   9240: 
                   9241:         if (count($registered) === 0) {
                   9242:             $data = '(no registered channels)';
                   9243:         }
                   9244:         $this->ui->outputData($data, $command);
                   9245:         return true;
                   9246:     }
                   9247: 
                   9248:     function doUpdateAll($command, $options, $params)
                   9249:     {
                   9250:         $reg = &$this->config->getRegistry();
                   9251:         $channels = $reg->getChannels();
                   9252: 
                   9253:         $success = true;
                   9254:         foreach ($channels as $channel) {
                   9255:             if ($channel->getName() != '__uri') {
                   9256:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9257:                 $err = $this->doUpdate('channel-update',
                   9258:                                           $options,
                   9259:                                           array($channel->getName()));
                   9260:                 if (PEAR::isError($err)) {
                   9261:                     $this->ui->outputData($err->getMessage(), $command);
                   9262:                     $success = false;
                   9263:                 } else {
                   9264:                     $success &= $err;
                   9265:                 }
                   9266:             }
                   9267:         }
                   9268:         return $success;
                   9269:     }
                   9270: 
                   9271:     function doInfo($command, $options, $params)
                   9272:     {
                   9273:         if (count($params) !== 1) {
                   9274:             return $this->raiseError("No channel specified");
                   9275:         }
                   9276: 
                   9277:         $reg     = &$this->config->getRegistry();
                   9278:         $channel = strtolower($params[0]);
                   9279:         if ($reg->channelExists($channel)) {
                   9280:             $chan = $reg->getChannel($channel);
                   9281:             if (PEAR::isError($chan)) {
                   9282:                 return $this->raiseError($chan);
                   9283:             }
                   9284:         } else {
                   9285:             if (strpos($channel, '://')) {
                   9286:                 $downloader = &$this->getDownloader();
                   9287:                 $tmpdir = $this->config->get('temp_dir');
                   9288:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9289:                 $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
                   9290:                 PEAR::staticPopErrorHandling();
                   9291:                 if (PEAR::isError($loc)) {
                   9292:                     return $this->raiseError('Cannot open "' . $channel .
                   9293:                         '" (' . $loc->getMessage() . ')');
                   9294:                 } else {
                   9295:                     $contents = implode('', file($loc));
                   9296:                 }
                   9297:             } else {
                   9298:                 if (!file_exists($params[0])) {
                   9299:                     return $this->raiseError('Unknown channel "' . $channel . '"');
                   9300:                 }
                   9301: 
                   9302:                 $fp = fopen($params[0], 'r');
                   9303:                 if (!$fp) {
                   9304:                     return $this->raiseError('Cannot open "' . $params[0] . '"');
                   9305:                 }
                   9306: 
                   9307:                 $contents = '';
                   9308:                 while (!feof($fp)) {
                   9309:                     $contents .= fread($fp, 1024);
                   9310:                 }
                   9311:                 fclose($fp);
                   9312:             }
                   9313: 
                   9314:             if (!class_exists('PEAR_ChannelFile')) {
                   9315:                 require_once 'PEAR/ChannelFile.php';
                   9316:             }
                   9317: 
                   9318:             $chan = new PEAR_ChannelFile;
                   9319:             $chan->fromXmlString($contents);
                   9320:             $chan->validate();
                   9321:             if ($errs = $chan->getErrors(true)) {
                   9322:                 foreach ($errs as $err) {
                   9323:                     $this->ui->outputData($err['level'] . ': ' . $err['message']);
                   9324:                 }
                   9325:                 return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
                   9326:             }
                   9327:         }
                   9328: 
                   9329:         if (!$chan) {
                   9330:             return $this->raiseError('Serious error: Channel "' . $params[0] .
                   9331:                 '" has a corrupted registry entry');
                   9332:         }
                   9333: 
                   9334:         $channel = $chan->getName();
                   9335:         $caption = 'Channel ' . $channel . ' Information:';
                   9336:         $data1 = array(
                   9337:             'caption' => $caption,
                   9338:             'border' => true);
                   9339:         $data1['data']['server'] = array('Name and Server', $chan->getName());
                   9340:         if ($chan->getAlias() != $chan->getName()) {
                   9341:             $data1['data']['alias'] = array('Alias', $chan->getAlias());
                   9342:         }
                   9343: 
                   9344:         $data1['data']['summary'] = array('Summary', $chan->getSummary());
                   9345:         $validate = $chan->getValidationPackage();
                   9346:         $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
                   9347:         $data1['data']['vpackageversion'] =
                   9348:             array('Validation Package Version', $validate['attribs']['version']);
                   9349:         $d = array();
                   9350:         $d['main'] = $data1;
                   9351: 
                   9352:         $data['data'] = array();
                   9353:         $data['caption'] = 'Server Capabilities';
                   9354:         $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
                   9355:         if ($chan->supportsREST()) {
                   9356:             if ($chan->supportsREST()) {
                   9357:                 $funcs = $chan->getFunctions('rest');
                   9358:                 if (!isset($funcs[0])) {
                   9359:                     $funcs = array($funcs);
                   9360:                 }
                   9361:                 foreach ($funcs as $protocol) {
                   9362:                     $data['data'][] = array('rest', $protocol['attribs']['type'],
                   9363:                         $protocol['_content']);
                   9364:                 }
                   9365:             }
                   9366:         } else {
                   9367:             $data['data'][] = array('No supported protocols');
                   9368:         }
                   9369: 
                   9370:         $d['protocols'] = $data;
                   9371:         $data['data'] = array();
                   9372:         $mirrors = $chan->getMirrors();
                   9373:         if ($mirrors) {
                   9374:             $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
                   9375:             unset($data['headline']);
                   9376:             foreach ($mirrors as $mirror) {
                   9377:                 $data['data'][] = array($mirror['attribs']['host']);
                   9378:                 $d['mirrors'] = $data;
                   9379:             }
                   9380: 
                   9381:             foreach ($mirrors as $i => $mirror) {
                   9382:                 $data['data'] = array();
                   9383:                 $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
                   9384:                 $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
                   9385:                 if ($chan->supportsREST($mirror['attribs']['host'])) {
                   9386:                     if ($chan->supportsREST($mirror['attribs']['host'])) {
                   9387:                         $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
                   9388:                         if (!isset($funcs[0])) {
                   9389:                             $funcs = array($funcs);
                   9390:                         }
                   9391: 
                   9392:                         foreach ($funcs as $protocol) {
                   9393:                             $data['data'][] = array('rest', $protocol['attribs']['type'],
                   9394:                                 $protocol['_content']);
                   9395:                         }
                   9396:                     }
                   9397:                 } else {
                   9398:                     $data['data'][] = array('No supported protocols');
                   9399:                 }
                   9400:                 $d['mirrorprotocols' . $i] = $data;
                   9401:             }
                   9402:         }
                   9403:         $this->ui->outputData($d, 'channel-info');
                   9404:     }
                   9405: 
                   9406:     // }}}
                   9407: 
                   9408:     function doDelete($command, $options, $params)
                   9409:     {
                   9410:         if (count($params) !== 1) {
                   9411:             return $this->raiseError('channel-delete: no channel specified');
                   9412:         }
                   9413: 
                   9414:         $reg = &$this->config->getRegistry();
                   9415:         if (!$reg->channelExists($params[0])) {
                   9416:             return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
                   9417:         }
                   9418: 
                   9419:         $channel = $reg->channelName($params[0]);
                   9420:         if ($channel == 'pear.php.net') {
                   9421:             return $this->raiseError('Cannot delete the pear.php.net channel');
                   9422:         }
                   9423: 
                   9424:         if ($channel == 'pecl.php.net') {
                   9425:             return $this->raiseError('Cannot delete the pecl.php.net channel');
                   9426:         }
                   9427: 
                   9428:         if ($channel == 'doc.php.net') {
                   9429:             return $this->raiseError('Cannot delete the doc.php.net channel');
                   9430:         }
                   9431: 
                   9432:         if ($channel == '__uri') {
                   9433:             return $this->raiseError('Cannot delete the __uri pseudo-channel');
                   9434:         }
                   9435: 
                   9436:         if (PEAR::isError($err = $reg->listPackages($channel))) {
                   9437:             return $err;
                   9438:         }
                   9439: 
                   9440:         if (count($err)) {
                   9441:             return $this->raiseError('Channel "' . $channel .
                   9442:                 '" has installed packages, cannot delete');
                   9443:         }
                   9444: 
                   9445:         if (!$reg->deleteChannel($channel)) {
                   9446:             return $this->raiseError('Channel "' . $channel . '" deletion failed');
                   9447:         } else {
                   9448:             $this->config->deleteChannel($channel);
                   9449:             $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
                   9450:         }
                   9451:     }
                   9452: 
                   9453:     function doAdd($command, $options, $params)
                   9454:     {
                   9455:         if (count($params) !== 1) {
                   9456:             return $this->raiseError('channel-add: no channel file specified');
                   9457:         }
                   9458: 
                   9459:         if (strpos($params[0], '://')) {
                   9460:             $downloader = &$this->getDownloader();
                   9461:             $tmpdir = $this->config->get('temp_dir');
                   9462:             if (!file_exists($tmpdir)) {
                   9463:                 require_once 'System.php';
                   9464:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9465:                 $err = System::mkdir(array('-p', $tmpdir));
                   9466:                 PEAR::staticPopErrorHandling();
                   9467:                 if (PEAR::isError($err)) {
                   9468:                     return $this->raiseError('channel-add: temp_dir does not exist: "' .
                   9469:                         $tmpdir .
                   9470:                         '" - You can change this location with "pear config-set temp_dir"');
                   9471:                 }
                   9472:             }
                   9473: 
                   9474:             if (!is_writable($tmpdir)) {
                   9475:                 return $this->raiseError('channel-add: temp_dir is not writable: "' .
                   9476:                     $tmpdir .
                   9477:                     '" - You can change this location with "pear config-set temp_dir"');
                   9478:             }
                   9479: 
                   9480:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9481:             $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
                   9482:             PEAR::staticPopErrorHandling();
                   9483:             if (PEAR::isError($loc)) {
                   9484:                 return $this->raiseError('channel-add: Cannot open "' . $params[0] .
                   9485:                     '" (' . $loc->getMessage() . ')');
                   9486:             }
                   9487: 
                   9488:             list($loc, $lastmodified) = $loc;
                   9489:             $contents = implode('', file($loc));
                   9490:         } else {
                   9491:             $lastmodified = $fp = false;
                   9492:             if (file_exists($params[0])) {
                   9493:                 $fp = fopen($params[0], 'r');
                   9494:             }
                   9495: 
                   9496:             if (!$fp) {
                   9497:                 return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
                   9498:             }
                   9499: 
                   9500:             $contents = '';
                   9501:             while (!feof($fp)) {
                   9502:                 $contents .= fread($fp, 1024);
                   9503:             }
                   9504:             fclose($fp);
                   9505:         }
                   9506: 
                   9507:         if (!class_exists('PEAR_ChannelFile')) {
                   9508:             require_once 'PEAR/ChannelFile.php';
                   9509:         }
                   9510: 
                   9511:         $channel = new PEAR_ChannelFile;
                   9512:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9513:         $result = $channel->fromXmlString($contents);
                   9514:         PEAR::staticPopErrorHandling();
                   9515:         if (!$result) {
                   9516:             $exit = false;
                   9517:             if (count($errors = $channel->getErrors(true))) {
                   9518:                 foreach ($errors as $error) {
                   9519:                     $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                   9520:                     if (!$exit) {
                   9521:                         $exit = $error['level'] == 'error' ? true : false;
                   9522:                     }
                   9523:                 }
                   9524:                 if ($exit) {
                   9525:                     return $this->raiseError('channel-add: invalid channel.xml file');
                   9526:                 }
                   9527:             }
                   9528:         }
                   9529: 
                   9530:         $reg = &$this->config->getRegistry();
                   9531:         if ($reg->channelExists($channel->getName())) {
                   9532:             return $this->raiseError('channel-add: Channel "' . $channel->getName() .
                   9533:                 '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
                   9534:         }
                   9535: 
                   9536:         $ret = $reg->addChannel($channel, $lastmodified);
                   9537:         if (PEAR::isError($ret)) {
                   9538:             return $ret;
                   9539:         }
                   9540: 
                   9541:         if (!$ret) {
                   9542:             return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
                   9543:                 '" to registry failed');
                   9544:         }
                   9545: 
                   9546:         $this->config->setChannels($reg->listChannels());
                   9547:         $this->config->writeConfigFile();
                   9548:         $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
                   9549:     }
                   9550: 
                   9551:     function doUpdate($command, $options, $params)
                   9552:     {
                   9553:         if (count($params) !== 1) {
                   9554:             return $this->raiseError("No channel file specified");
                   9555:         }
                   9556: 
                   9557:         $tmpdir = $this->config->get('temp_dir');
                   9558:         if (!file_exists($tmpdir)) {
                   9559:             require_once 'System.php';
                   9560:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9561:             $err = System::mkdir(array('-p', $tmpdir));
                   9562:             PEAR::staticPopErrorHandling();
                   9563:             if (PEAR::isError($err)) {
                   9564:                 return $this->raiseError('channel-add: temp_dir does not exist: "' .
                   9565:                     $tmpdir .
                   9566:                     '" - You can change this location with "pear config-set temp_dir"');
                   9567:             }
                   9568:         }
                   9569: 
                   9570:         if (!is_writable($tmpdir)) {
                   9571:             return $this->raiseError('channel-add: temp_dir is not writable: "' .
                   9572:                 $tmpdir .
                   9573:                 '" - You can change this location with "pear config-set temp_dir"');
                   9574:         }
                   9575: 
                   9576:         $reg = &$this->config->getRegistry();
                   9577:         $lastmodified = false;
                   9578:         if ((!file_exists($params[0]) || is_dir($params[0]))
                   9579:               && $reg->channelExists(strtolower($params[0]))) {
                   9580:             $c = $reg->getChannel(strtolower($params[0]));
                   9581:             if (PEAR::isError($c)) {
                   9582:                 return $this->raiseError($c);
                   9583:             }
                   9584: 
                   9585:             $this->ui->outputData("Updating channel \"$params[0]\"", $command);
                   9586:             $dl = &$this->getDownloader(array());
                   9587:             // if force is specified, use a timestamp of "1" to force retrieval
                   9588:             $lastmodified = isset($options['force']) ? false : $c->lastModified();
                   9589:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9590:             $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
                   9591:                 $this->ui, $tmpdir, null, $lastmodified);
                   9592:             PEAR::staticPopErrorHandling();
                   9593:             if (PEAR::isError($contents)) {
                   9594:                 // Attempt to fall back to https
                   9595:                 $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
                   9596:                 $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
                   9597:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9598:                 $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
                   9599:                     $this->ui, $tmpdir, null, $lastmodified);
                   9600:                 PEAR::staticPopErrorHandling();
                   9601:                 if (PEAR::isError($contents)) {
                   9602:                     return $this->raiseError('Cannot retrieve channel.xml for channel "' .
                   9603:                         $c->getName() . '" (' . $contents->getMessage() . ')');
                   9604:                 }
                   9605:             }
                   9606: 
                   9607:             list($contents, $lastmodified) = $contents;
                   9608:             if (!$contents) {
                   9609:                 $this->ui->outputData("Channel \"$params[0]\" is up to date");
                   9610:                 return;
                   9611:             }
                   9612: 
                   9613:             $contents = implode('', file($contents));
                   9614:             if (!class_exists('PEAR_ChannelFile')) {
                   9615:                 require_once 'PEAR/ChannelFile.php';
                   9616:             }
                   9617: 
                   9618:             $channel = new PEAR_ChannelFile;
                   9619:             $channel->fromXmlString($contents);
                   9620:             if (!$channel->getErrors()) {
                   9621:                 // security check: is the downloaded file for the channel we got it from?
                   9622:                 if (strtolower($channel->getName()) != strtolower($c->getName())) {
                   9623:                     if (!isset($options['force'])) {
                   9624:                         return $this->raiseError('ERROR: downloaded channel definition file' .
                   9625:                             ' for channel "' . $channel->getName() . '" from channel "' .
                   9626:                             strtolower($c->getName()) . '"');
                   9627:                     }
                   9628: 
                   9629:                     $this->ui->log(0, 'WARNING: downloaded channel definition file' .
                   9630:                         ' for channel "' . $channel->getName() . '" from channel "' .
                   9631:                         strtolower($c->getName()) . '"');
                   9632:                 }
                   9633:             }
                   9634:         } else {
                   9635:             if (strpos($params[0], '://')) {
                   9636:                 $dl = &$this->getDownloader();
                   9637:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9638:                 $loc = $dl->downloadHttp($params[0],
                   9639:                     $this->ui, $tmpdir, null, $lastmodified);
                   9640:                 PEAR::staticPopErrorHandling();
                   9641:                 if (PEAR::isError($loc)) {
                   9642:                     return $this->raiseError("Cannot open " . $params[0] .
                   9643:                          ' (' . $loc->getMessage() . ')');
                   9644:                 }
                   9645: 
                   9646:                 list($loc, $lastmodified) = $loc;
                   9647:                 $contents = implode('', file($loc));
                   9648:             } else {
                   9649:                 $fp = false;
                   9650:                 if (file_exists($params[0])) {
                   9651:                     $fp = fopen($params[0], 'r');
                   9652:                 }
                   9653: 
                   9654:                 if (!$fp) {
                   9655:                     return $this->raiseError("Cannot open " . $params[0]);
                   9656:                 }
                   9657: 
                   9658:                 $contents = '';
                   9659:                 while (!feof($fp)) {
                   9660:                     $contents .= fread($fp, 1024);
                   9661:                 }
                   9662:                 fclose($fp);
                   9663:             }
                   9664: 
                   9665:             if (!class_exists('PEAR_ChannelFile')) {
                   9666:                 require_once 'PEAR/ChannelFile.php';
                   9667:             }
                   9668: 
                   9669:             $channel = new PEAR_ChannelFile;
                   9670:             $channel->fromXmlString($contents);
                   9671:         }
                   9672: 
                   9673:         $exit = false;
                   9674:         if (count($errors = $channel->getErrors(true))) {
                   9675:             foreach ($errors as $error) {
                   9676:                 $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                   9677:                 if (!$exit) {
                   9678:                     $exit = $error['level'] == 'error' ? true : false;
                   9679:                 }
                   9680:             }
                   9681:             if ($exit) {
                   9682:                 return $this->raiseError('Invalid channel.xml file');
                   9683:             }
                   9684:         }
                   9685: 
                   9686:         if (!$reg->channelExists($channel->getName())) {
                   9687:             return $this->raiseError('Error: Channel "' . $channel->getName() .
                   9688:                 '" does not exist, use channel-add to add an entry');
                   9689:         }
                   9690: 
                   9691:         $ret = $reg->updateChannel($channel, $lastmodified);
                   9692:         if (PEAR::isError($ret)) {
                   9693:             return $ret;
                   9694:         }
                   9695: 
                   9696:         if (!$ret) {
                   9697:             return $this->raiseError('Updating Channel "' . $channel->getName() .
                   9698:                 '" in registry failed');
                   9699:         }
                   9700: 
                   9701:         $this->config->setChannels($reg->listChannels());
                   9702:         $this->config->writeConfigFile();
                   9703:         $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
                   9704:     }
                   9705: 
                   9706:     function &getDownloader()
                   9707:     {
                   9708:         if (!class_exists('PEAR_Downloader')) {
                   9709:             require_once 'PEAR/Downloader.php';
                   9710:         }
                   9711:         $a = new PEAR_Downloader($this->ui, array(), $this->config);
                   9712:         return $a;
                   9713:     }
                   9714: 
                   9715:     function doAlias($command, $options, $params)
                   9716:     {
                   9717:         if (count($params) === 1) {
                   9718:             return $this->raiseError('No channel alias specified');
                   9719:         }
                   9720: 
                   9721:         if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
                   9722:             return $this->raiseError(
                   9723:                 'Invalid format, correct is: channel-alias channel alias');
                   9724:         }
                   9725: 
                   9726:         $reg = &$this->config->getRegistry();
                   9727:         if (!$reg->channelExists($params[0], true)) {
                   9728:             $extra = '';
                   9729:             if ($reg->isAlias($params[0])) {
                   9730:                 $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
                   9731:                     strtolower($params[1]) . '")';
                   9732:             }
                   9733: 
                   9734:             return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
                   9735:         }
                   9736: 
                   9737:         if ($reg->isAlias($params[1])) {
                   9738:             return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
                   9739:                 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
                   9740:         }
                   9741: 
                   9742:         $chan = &$reg->getChannel($params[0]);
                   9743:         if (PEAR::isError($chan)) {
                   9744:             return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
                   9745:                 '" information (' . $chan->getMessage() . ')');
                   9746:         }
                   9747: 
                   9748:         // make it a local alias
                   9749:         if (!$chan->setAlias(strtolower($params[1]), true)) {
                   9750:             return $this->raiseError('Alias "' . strtolower($params[1]) .
                   9751:                 '" is not a valid channel alias');
                   9752:         }
                   9753: 
                   9754:         $reg->updateChannel($chan);
                   9755:         $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
                   9756:             strtolower($params[1]) . '"');
                   9757:     }
                   9758: 
                   9759:     /**
                   9760:      * The channel-discover command
                   9761:      *
                   9762:      * @param string $command command name
                   9763:      * @param array  $options option_name => value
                   9764:      * @param array  $params  list of additional parameters.
                   9765:      *               $params[0] should contain a string with either:
                   9766:      *               - <channel name> or
                   9767:      *               - <username>:<password>@<channel name>
                   9768:      * @return null|PEAR_Error
                   9769:      */
                   9770:     function doDiscover($command, $options, $params)
                   9771:     {
                   9772:         if (count($params) !== 1) {
                   9773:             return $this->raiseError("No channel server specified");
                   9774:         }
                   9775: 
                   9776:         // Look for the possible input format "<username>:<password>@<channel>"
                   9777:         if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
                   9778:             $username = $matches[1];
                   9779:             $password = $matches[2];
                   9780:             $channel  = $matches[3];
                   9781:         } else {
                   9782:             $channel = $params[0];
                   9783:         }
                   9784: 
                   9785:         $reg = &$this->config->getRegistry();
                   9786:         if ($reg->channelExists($channel)) {
                   9787:             if (!$reg->isAlias($channel)) {
                   9788:                 return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
                   9789:             }
                   9790: 
                   9791:             return $this->raiseError("A channel alias named \"$channel\" " .
                   9792:                 'already exists, aliasing channel "' . $reg->channelName($channel)
                   9793:                 . '"');
                   9794:         }
                   9795: 
                   9796:         $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   9797:         $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
                   9798:         $this->popErrorHandling();
                   9799:         if (PEAR::isError($err)) {
                   9800:             if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
                   9801:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                   9802:                     $err->getMessage() . ')');
                   9803:             }
                   9804:             // Attempt fetch via https
                   9805:             $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
                   9806:             $this->ui->outputData("Trying to discover channel $channel over https:// instead");
                   9807:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   9808:             $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
                   9809:             $this->popErrorHandling();
                   9810:             if (PEAR::isError($err)) {
                   9811:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                   9812:                     $err->getMessage() . ')');
                   9813:             }
                   9814:         }
                   9815: 
                   9816:         // Store username/password if they were given
                   9817:         // Arguably we should do a logintest on the channel here, but since
                   9818:         // that's awkward on a REST-based channel (even "pear login" doesn't
                   9819:         // do it for those), and XML-RPC is deprecated, it's fairly pointless.
                   9820:         if (isset($username)) {
                   9821:             $this->config->set('username', $username, 'user', $channel);
                   9822:             $this->config->set('password', $password, 'user', $channel);
                   9823:             $this->config->store();
                   9824:             $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
                   9825:         }
                   9826: 
                   9827:         $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
                   9828:     }
                   9829: 
                   9830:     /**
                   9831:      * Execute the 'login' command.
                   9832:      *
                   9833:      * @param string $command command name
                   9834:      * @param array $options option_name => value
                   9835:      * @param array $params list of additional parameters
                   9836:      *
                   9837:      * @return bool TRUE on success or
                   9838:      * a PEAR error on failure
                   9839:      *
                   9840:      * @access public
                   9841:      */
                   9842:     function doLogin($command, $options, $params)
                   9843:     {
                   9844:         $reg = &$this->config->getRegistry();
                   9845: 
                   9846:         // If a parameter is supplied, use that as the channel to log in to
                   9847:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
                   9848: 
                   9849:         $chan = $reg->getChannel($channel);
                   9850:         if (PEAR::isError($chan)) {
                   9851:             return $this->raiseError($chan);
                   9852:         }
                   9853: 
                   9854:         $server   = $this->config->get('preferred_mirror', null, $channel);
                   9855:         $username = $this->config->get('username',         null, $channel);
                   9856:         if (empty($username)) {
                   9857:             $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
                   9858:         }
                   9859:         $this->ui->outputData("Logging in to $server.", $command);
                   9860: 
                   9861:         list($username, $password) = $this->ui->userDialog(
                   9862:             $command,
                   9863:             array('Username', 'Password'),
                   9864:             array('text',     'password'),
                   9865:             array($username,  '')
                   9866:             );
                   9867:         $username = trim($username);
                   9868:         $password = trim($password);
                   9869: 
                   9870:         $ourfile = $this->config->getConfFile('user');
                   9871:         if (!$ourfile) {
                   9872:             $ourfile = $this->config->getConfFile('system');
                   9873:         }
                   9874: 
                   9875:         $this->config->set('username', $username, 'user', $channel);
                   9876:         $this->config->set('password', $password, 'user', $channel);
                   9877: 
                   9878:         if ($chan->supportsREST()) {
                   9879:             $ok = true;
                   9880:         }
                   9881: 
                   9882:         if ($ok !== true) {
                   9883:             return $this->raiseError('Login failed!');
                   9884:         }
                   9885: 
                   9886:         $this->ui->outputData("Logged in.", $command);
                   9887:         // avoid changing any temporary settings changed with -d
                   9888:         $ourconfig = new PEAR_Config($ourfile, $ourfile);
                   9889:         $ourconfig->set('username', $username, 'user', $channel);
                   9890:         $ourconfig->set('password', $password, 'user', $channel);
                   9891:         $ourconfig->store();
                   9892: 
                   9893:         return true;
                   9894:     }
                   9895: 
                   9896:     /**
                   9897:      * Execute the 'logout' command.
                   9898:      *
                   9899:      * @param string $command command name
                   9900:      * @param array $options option_name => value
                   9901:      * @param array $params list of additional parameters
                   9902:      *
                   9903:      * @return bool TRUE on success or
                   9904:      * a PEAR error on failure
                   9905:      *
                   9906:      * @access public
                   9907:      */
                   9908:     function doLogout($command, $options, $params)
                   9909:     {
                   9910:         $reg     = &$this->config->getRegistry();
                   9911: 
                   9912:         // If a parameter is supplied, use that as the channel to log in to
                   9913:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
                   9914: 
                   9915:         $chan    = $reg->getChannel($channel);
                   9916:         if (PEAR::isError($chan)) {
                   9917:             return $this->raiseError($chan);
                   9918:         }
                   9919: 
                   9920:         $server = $this->config->get('preferred_mirror', null, $channel);
                   9921:         $this->ui->outputData("Logging out from $server.", $command);
                   9922:         $this->config->remove('username', 'user', $channel);
                   9923:         $this->config->remove('password', 'user', $channel);
                   9924:         $this->config->store();
                   9925:         return true;
                   9926:     }
                   9927: }PEAR-1.9.4/PEAR/Command/Common.php0000644000076500000240000002014411605156760015305 0ustar  helgistaff<?php
                   9928: /**
                   9929:  * PEAR_Command_Common base class
                   9930:  *
                   9931:  * PHP versions 4 and 5
                   9932:  *
                   9933:  * @category   pear
                   9934:  * @package    PEAR
                   9935:  * @author     Stig Bakken <ssb@php.net>
                   9936:  * @author     Greg Beaver <cellog@php.net>
                   9937:  * @copyright  1997-2009 The Authors
                   9938:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9939:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   9940:  * @link       http://pear.php.net/package/PEAR
                   9941:  * @since      File available since Release 0.1
                   9942:  */
                   9943: 
                   9944: /**
                   9945:  * base class
                   9946:  */
                   9947: require_once 'PEAR.php';
                   9948: 
                   9949: /**
                   9950:  * PEAR commands base class
                   9951:  *
                   9952:  * @category   pear
                   9953:  * @package    PEAR
                   9954:  * @author     Stig Bakken <ssb@php.net>
                   9955:  * @author     Greg Beaver <cellog@php.net>
                   9956:  * @copyright  1997-2009 The Authors
                   9957:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9958:  * @version    Release: 1.9.4
                   9959:  * @link       http://pear.php.net/package/PEAR
                   9960:  * @since      Class available since Release 0.1
                   9961:  */
                   9962: class PEAR_Command_Common extends PEAR
                   9963: {
                   9964:     /**
                   9965:      * PEAR_Config object used to pass user system and configuration
                   9966:      * on when executing commands
                   9967:      *
                   9968:      * @var PEAR_Config
                   9969:      */
                   9970:     var $config;
                   9971:     /**
                   9972:      * @var PEAR_Registry
                   9973:      * @access protected
                   9974:      */
                   9975:     var $_registry;
                   9976: 
                   9977:     /**
                   9978:      * User Interface object, for all interaction with the user.
                   9979:      * @var object
                   9980:      */
                   9981:     var $ui;
                   9982: 
                   9983:     var $_deps_rel_trans = array(
                   9984:                                  'lt' => '<',
                   9985:                                  'le' => '<=',
                   9986:                                  'eq' => '=',
                   9987:                                  'ne' => '!=',
                   9988:                                  'gt' => '>',
                   9989:                                  'ge' => '>=',
                   9990:                                  'has' => '=='
                   9991:                                  );
                   9992: 
                   9993:     var $_deps_type_trans = array(
                   9994:                                   'pkg' => 'package',
                   9995:                                   'ext' => 'extension',
                   9996:                                   'php' => 'PHP',
                   9997:                                   'prog' => 'external program',
                   9998:                                   'ldlib' => 'external library for linking',
                   9999:                                   'rtlib' => 'external runtime library',
                   10000:                                   'os' => 'operating system',
                   10001:                                   'websrv' => 'web server',
                   10002:                                   'sapi' => 'SAPI backend'
                   10003:                                   );
                   10004: 
                   10005:     /**
                   10006:      * PEAR_Command_Common constructor.
                   10007:      *
                   10008:      * @access public
                   10009:      */
                   10010:     function PEAR_Command_Common(&$ui, &$config)
                   10011:     {
                   10012:         parent::PEAR();
                   10013:         $this->config = &$config;
                   10014:         $this->ui = &$ui;
                   10015:     }
                   10016: 
                   10017:     /**
                   10018:      * Return a list of all the commands defined by this class.
                   10019:      * @return array list of commands
                   10020:      * @access public
                   10021:      */
                   10022:     function getCommands()
                   10023:     {
                   10024:         $ret = array();
                   10025:         foreach (array_keys($this->commands) as $command) {
                   10026:             $ret[$command] = $this->commands[$command]['summary'];
                   10027:         }
                   10028: 
                   10029:         return $ret;
                   10030:     }
                   10031: 
                   10032:     /**
                   10033:      * Return a list of all the command shortcuts defined by this class.
                   10034:      * @return array shortcut => command
                   10035:      * @access public
                   10036:      */
                   10037:     function getShortcuts()
                   10038:     {
                   10039:         $ret = array();
                   10040:         foreach (array_keys($this->commands) as $command) {
                   10041:             if (isset($this->commands[$command]['shortcut'])) {
                   10042:                 $ret[$this->commands[$command]['shortcut']] = $command;
                   10043:             }
                   10044:         }
                   10045: 
                   10046:         return $ret;
                   10047:     }
                   10048: 
                   10049:     function getOptions($command)
                   10050:     {
                   10051:         $shortcuts = $this->getShortcuts();
                   10052:         if (isset($shortcuts[$command])) {
                   10053:             $command = $shortcuts[$command];
                   10054:         }
                   10055: 
                   10056:         if (isset($this->commands[$command]) &&
                   10057:               isset($this->commands[$command]['options'])) {
                   10058:             return $this->commands[$command]['options'];
                   10059:         }
                   10060: 
                   10061:         return null;
                   10062:     }
                   10063: 
                   10064:     function getGetoptArgs($command, &$short_args, &$long_args)
                   10065:     {
                   10066:         $short_args = '';
                   10067:         $long_args = array();
                   10068:         if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
                   10069:             return;
                   10070:         }
                   10071: 
                   10072:         reset($this->commands[$command]['options']);
                   10073:         while (list($option, $info) = each($this->commands[$command]['options'])) {
                   10074:             $larg = $sarg = '';
                   10075:             if (isset($info['arg'])) {
                   10076:                 if ($info['arg']{0} == '(') {
                   10077:                     $larg = '==';
                   10078:                     $sarg = '::';
                   10079:                     $arg = substr($info['arg'], 1, -1);
                   10080:                 } else {
                   10081:                     $larg = '=';
                   10082:                     $sarg = ':';
                   10083:                     $arg = $info['arg'];
                   10084:                 }
                   10085:             }
                   10086: 
                   10087:             if (isset($info['shortopt'])) {
                   10088:                 $short_args .= $info['shortopt'] . $sarg;
                   10089:             }
                   10090: 
                   10091:             $long_args[] = $option . $larg;
                   10092:         }
                   10093:     }
                   10094: 
                   10095:     /**
                   10096:     * Returns the help message for the given command
                   10097:     *
                   10098:     * @param string $command The command
                   10099:     * @return mixed A fail string if the command does not have help or
                   10100:     *               a two elements array containing [0]=>help string,
                   10101:     *               [1]=> help string for the accepted cmd args
                   10102:     */
                   10103:     function getHelp($command)
                   10104:     {
                   10105:         $config = &PEAR_Config::singleton();
                   10106:         if (!isset($this->commands[$command])) {
                   10107:             return "No such command \"$command\"";
                   10108:         }
                   10109: 
                   10110:         $help = null;
                   10111:         if (isset($this->commands[$command]['doc'])) {
                   10112:             $help = $this->commands[$command]['doc'];
                   10113:         }
                   10114: 
                   10115:         if (empty($help)) {
                   10116:             // XXX (cox) Fallback to summary if there is no doc (show both?)
                   10117:             if (!isset($this->commands[$command]['summary'])) {
                   10118:                 return "No help for command \"$command\"";
                   10119:             }
                   10120:             $help = $this->commands[$command]['summary'];
                   10121:         }
                   10122: 
                   10123:         if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
                   10124:             foreach($matches[0] as $k => $v) {
                   10125:                 $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
                   10126:             }
                   10127:         }
                   10128: 
                   10129:         return array($help, $this->getHelpArgs($command));
                   10130:     }
                   10131: 
                   10132:     /**
                   10133:      * Returns the help for the accepted arguments of a command
                   10134:      *
                   10135:      * @param  string $command
                   10136:      * @return string The help string
                   10137:      */
                   10138:     function getHelpArgs($command)
                   10139:     {
                   10140:         if (isset($this->commands[$command]['options']) &&
                   10141:             count($this->commands[$command]['options']))
                   10142:         {
                   10143:             $help = "Options:\n";
                   10144:             foreach ($this->commands[$command]['options'] as $k => $v) {
                   10145:                 if (isset($v['arg'])) {
                   10146:                     if ($v['arg'][0] == '(') {
                   10147:                         $arg = substr($v['arg'], 1, -1);
                   10148:                         $sapp = " [$arg]";
                   10149:                         $lapp = "[=$arg]";
                   10150:                     } else {
                   10151:                         $sapp = " $v[arg]";
                   10152:                         $lapp = "=$v[arg]";
                   10153:                     }
                   10154:                 } else {
                   10155:                     $sapp = $lapp = "";
                   10156:                 }
                   10157: 
                   10158:                 if (isset($v['shortopt'])) {
                   10159:                     $s = $v['shortopt'];
                   10160:                     $help .= "  -$s$sapp, --$k$lapp\n";
                   10161:                 } else {
                   10162:                     $help .= "  --$k$lapp\n";
                   10163:                 }
                   10164: 
                   10165:                 $p = "        ";
                   10166:                 $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
                   10167:                 $help .= "        $doc\n";
                   10168:             }
                   10169: 
                   10170:             return $help;
                   10171:         }
                   10172: 
                   10173:         return null;
                   10174:     }
                   10175: 
                   10176:     function run($command, $options, $params)
                   10177:     {
                   10178:         if (empty($this->commands[$command]['function'])) {
                   10179:             // look for shortcuts
                   10180:             foreach (array_keys($this->commands) as $cmd) {
                   10181:                 if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
                   10182:                     if (empty($this->commands[$cmd]['function'])) {
                   10183:                         return $this->raiseError("unknown command `$command'");
                   10184:                     } else {
                   10185:                         $func = $this->commands[$cmd]['function'];
                   10186:                     }
                   10187:                     $command = $cmd;
                   10188: 
                   10189:                     //$command = $this->commands[$cmd]['function'];
                   10190:                     break;
                   10191:                 }
                   10192:             }
                   10193:         } else {
                   10194:             $func = $this->commands[$command]['function'];
                   10195:         }
                   10196: 
                   10197:         return $this->$func($command, $options, $params);
                   10198:     }
                   10199: }PEAR-1.9.4/PEAR/Command/Config.xml0000644000076500000240000000646611605156760015306 0ustar  helgistaff<commands version="1.0">
                   10200:  <config-show>
                   10201:   <summary>Show All Settings</summary>
                   10202:   <function>doConfigShow</function>
                   10203:   <shortcut>csh</shortcut>
                   10204:   <options>
                   10205:    <channel>
                   10206:     <shortopt>c</shortopt>
                   10207:     <doc>show configuration variables for another channel</doc>
                   10208:     <arg>CHAN</arg>
                   10209:    </channel>
                   10210:   </options>
                   10211:   <doc>[layer]
                   10212: Displays all configuration values.  An optional argument
                   10213: may be used to tell which configuration layer to display.  Valid
                   10214: configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
                   10215: configurations for different channels, set the default_channel
                   10216: configuration variable and run config-show again.
                   10217: </doc>
                   10218:  </config-show>
                   10219:  <config-get>
                   10220:   <summary>Show One Setting</summary>
                   10221:   <function>doConfigGet</function>
                   10222:   <shortcut>cg</shortcut>
                   10223:   <options>
                   10224:    <channel>
                   10225:     <shortopt>c</shortopt>
                   10226:     <doc>show configuration variables for another channel</doc>
                   10227:     <arg>CHAN</arg>
                   10228:    </channel>
                   10229:   </options>
                   10230:   <doc>&lt;parameter&gt; [layer]
                   10231: Displays the value of one configuration parameter.  The
                   10232: first argument is the name of the parameter, an optional second argument
                   10233: may be used to tell which configuration layer to look in.  Valid configuration
                   10234: layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;.  If no layer is specified, a value
                   10235: will be picked from the first layer that defines the parameter, in the order
                   10236: just specified.  The configuration value will be retrieved for the channel
                   10237: specified by the default_channel configuration variable.
                   10238: </doc>
                   10239:  </config-get>
                   10240:  <config-set>
                   10241:   <summary>Change Setting</summary>
                   10242:   <function>doConfigSet</function>
                   10243:   <shortcut>cs</shortcut>
                   10244:   <options>
                   10245:    <channel>
                   10246:     <shortopt>c</shortopt>
                   10247:     <doc>show configuration variables for another channel</doc>
                   10248:     <arg>CHAN</arg>
                   10249:    </channel>
                   10250:   </options>
                   10251:   <doc>&lt;parameter&gt; &lt;value&gt; [layer]
                   10252: Sets the value of one configuration parameter.  The first argument is
                   10253: the name of the parameter, the second argument is the new value.  Some
                   10254: parameters are subject to validation, and the command will fail with
                   10255: an error message if the new value does not make sense.  An optional
                   10256: third argument may be used to specify in which layer to set the
                   10257: configuration parameter.  The default layer is &quot;user&quot;.  The
                   10258: configuration value will be set for the current channel, which
                   10259: is controlled by the default_channel configuration variable.
                   10260: </doc>
                   10261:  </config-set>
                   10262:  <config-help>
                   10263:   <summary>Show Information About Setting</summary>
                   10264:   <function>doConfigHelp</function>
                   10265:   <shortcut>ch</shortcut>
                   10266:   <options />
                   10267:   <doc>[parameter]
                   10268: Displays help for a configuration parameter.  Without arguments it
                   10269: displays help for all configuration parameters.
                   10270: </doc>
                   10271:  </config-help>
                   10272:  <config-create>
                   10273:   <summary>Create a Default configuration file</summary>
                   10274:   <function>doConfigCreate</function>
                   10275:   <shortcut>coc</shortcut>
                   10276:   <options>
                   10277:    <windows>
                   10278:     <shortopt>w</shortopt>
                   10279:     <doc>create a config file for a windows install</doc>
                   10280:    </windows>
                   10281:   </options>
                   10282:   <doc>&lt;root path&gt; &lt;filename&gt;
                   10283: Create a default configuration file with all directory configuration
                   10284: variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
                   10285: This is useful especially for creating a configuration file for a remote
                   10286: PEAR installation (using the --remoteconfig option of install, upgrade,
                   10287: and uninstall).
                   10288: </doc>
                   10289:  </config-create>
                   10290: </commands>PEAR-1.9.4/PEAR/Command/Config.php0000644000076500000240000003615611605156760015274 0ustar  helgistaff<?php
                   10291: /**
                   10292:  * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
                   10293:  *
                   10294:  * PHP versions 4 and 5
                   10295:  *
                   10296:  * @category   pear
                   10297:  * @package    PEAR
                   10298:  * @author     Stig Bakken <ssb@php.net>
                   10299:  * @author     Greg Beaver <cellog@php.net>
                   10300:  * @copyright  1997-2009 The Authors
                   10301:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10302:  * @version    CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
                   10303:  * @link       http://pear.php.net/package/PEAR
                   10304:  * @since      File available since Release 0.1
                   10305:  */
                   10306: 
                   10307: /**
                   10308:  * base class
                   10309:  */
                   10310: require_once 'PEAR/Command/Common.php';
                   10311: 
                   10312: /**
                   10313:  * PEAR commands for managing configuration data.
                   10314:  *
                   10315:  * @category   pear
                   10316:  * @package    PEAR
                   10317:  * @author     Stig Bakken <ssb@php.net>
                   10318:  * @author     Greg Beaver <cellog@php.net>
                   10319:  * @copyright  1997-2009 The Authors
                   10320:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10321:  * @version    Release: 1.9.4
                   10322:  * @link       http://pear.php.net/package/PEAR
                   10323:  * @since      Class available since Release 0.1
                   10324:  */
                   10325: class PEAR_Command_Config extends PEAR_Command_Common
                   10326: {
                   10327:     var $commands = array(
                   10328:         'config-show' => array(
                   10329:             'summary' => 'Show All Settings',
                   10330:             'function' => 'doConfigShow',
                   10331:             'shortcut' => 'csh',
                   10332:             'options' => array(
                   10333:                 'channel' => array(
                   10334:                     'shortopt' => 'c',
                   10335:                     'doc' => 'show configuration variables for another channel',
                   10336:                     'arg' => 'CHAN',
                   10337:                     ),
                   10338: ),
                   10339:             'doc' => '[layer]
                   10340: Displays all configuration values.  An optional argument
                   10341: may be used to tell which configuration layer to display.  Valid
                   10342: configuration layers are "user", "system" and "default". To display
                   10343: configurations for different channels, set the default_channel
                   10344: configuration variable and run config-show again.
                   10345: ',
                   10346:             ),
                   10347:         'config-get' => array(
                   10348:             'summary' => 'Show One Setting',
                   10349:             'function' => 'doConfigGet',
                   10350:             'shortcut' => 'cg',
                   10351:             'options' => array(
                   10352:                 'channel' => array(
                   10353:                     'shortopt' => 'c',
                   10354:                     'doc' => 'show configuration variables for another channel',
                   10355:                     'arg' => 'CHAN',
                   10356:                     ),
                   10357: ),
                   10358:             'doc' => '<parameter> [layer]
                   10359: Displays the value of one configuration parameter.  The
                   10360: first argument is the name of the parameter, an optional second argument
                   10361: may be used to tell which configuration layer to look in.  Valid configuration
                   10362: layers are "user", "system" and "default".  If no layer is specified, a value
                   10363: will be picked from the first layer that defines the parameter, in the order
                   10364: just specified.  The configuration value will be retrieved for the channel
                   10365: specified by the default_channel configuration variable.
                   10366: ',
                   10367:             ),
                   10368:         'config-set' => array(
                   10369:             'summary' => 'Change Setting',
                   10370:             'function' => 'doConfigSet',
                   10371:             'shortcut' => 'cs',
                   10372:             'options' => array(
                   10373:                 'channel' => array(
                   10374:                     'shortopt' => 'c',
                   10375:                     'doc' => 'show configuration variables for another channel',
                   10376:                     'arg' => 'CHAN',
                   10377:                     ),
                   10378: ),
                   10379:             'doc' => '<parameter> <value> [layer]
                   10380: Sets the value of one configuration parameter.  The first argument is
                   10381: the name of the parameter, the second argument is the new value.  Some
                   10382: parameters are subject to validation, and the command will fail with
                   10383: an error message if the new value does not make sense.  An optional
                   10384: third argument may be used to specify in which layer to set the
                   10385: configuration parameter.  The default layer is "user".  The
                   10386: configuration value will be set for the current channel, which
                   10387: is controlled by the default_channel configuration variable.
                   10388: ',
                   10389:             ),
                   10390:         'config-help' => array(
                   10391:             'summary' => 'Show Information About Setting',
                   10392:             'function' => 'doConfigHelp',
                   10393:             'shortcut' => 'ch',
                   10394:             'options' => array(),
                   10395:             'doc' => '[parameter]
                   10396: Displays help for a configuration parameter.  Without arguments it
                   10397: displays help for all configuration parameters.
                   10398: ',
                   10399:            ),
                   10400:         'config-create' => array(
                   10401:             'summary' => 'Create a Default configuration file',
                   10402:             'function' => 'doConfigCreate',
                   10403:             'shortcut' => 'coc',
                   10404:             'options' => array(
                   10405:                 'windows' => array(
                   10406:                     'shortopt' => 'w',
                   10407:                     'doc' => 'create a config file for a windows install',
                   10408:                     ),
                   10409:             ),
                   10410:             'doc' => '<root path> <filename>
                   10411: Create a default configuration file with all directory configuration
                   10412: variables set to subdirectories of <root path>, and save it as <filename>.
                   10413: This is useful especially for creating a configuration file for a remote
                   10414: PEAR installation (using the --remoteconfig option of install, upgrade,
                   10415: and uninstall).
                   10416: ',
                   10417:             ),
                   10418:         );
                   10419: 
                   10420:     /**
                   10421:      * PEAR_Command_Config constructor.
                   10422:      *
                   10423:      * @access public
                   10424:      */
                   10425:     function PEAR_Command_Config(&$ui, &$config)
                   10426:     {
                   10427:         parent::PEAR_Command_Common($ui, $config);
                   10428:     }
                   10429: 
                   10430:     function doConfigShow($command, $options, $params)
                   10431:     {
                   10432:         $layer = null;
                   10433:         if (is_array($params)) {
                   10434:             $layer = isset($params[0]) ? $params[0] : null;
                   10435:         }
                   10436: 
                   10437:         // $params[0] -> the layer
                   10438:         if ($error = $this->_checkLayer($layer)) {
                   10439:             return $this->raiseError("config-show:$error");
                   10440:         }
                   10441: 
                   10442:         $keys = $this->config->getKeys();
                   10443:         sort($keys);
                   10444:         $channel = isset($options['channel']) ? $options['channel'] :
                   10445:             $this->config->get('default_channel');
                   10446:         $reg = &$this->config->getRegistry();
                   10447:         if (!$reg->channelExists($channel)) {
                   10448:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10449:         }
                   10450: 
                   10451:         $channel = $reg->channelName($channel);
                   10452:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
                   10453:         foreach ($keys as $key) {
                   10454:             $type = $this->config->getType($key);
                   10455:             $value = $this->config->get($key, $layer, $channel);
                   10456:             if ($type == 'password' && $value) {
                   10457:                 $value = '********';
                   10458:             }
                   10459: 
                   10460:             if ($value === false) {
                   10461:                 $value = 'false';
                   10462:             } elseif ($value === true) {
                   10463:                 $value = 'true';
                   10464:             }
                   10465: 
                   10466:             $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
                   10467:         }
                   10468: 
                   10469:         foreach ($this->config->getLayers() as $layer) {
                   10470:             $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
                   10471:         }
                   10472: 
                   10473:         $this->ui->outputData($data, $command);
                   10474:         return true;
                   10475:     }
                   10476: 
                   10477:     function doConfigGet($command, $options, $params)
                   10478:     {
                   10479:         $args_cnt = is_array($params) ? count($params) : 0;
                   10480:         switch ($args_cnt) {
                   10481:             case 1:
                   10482:                 $config_key = $params[0];
                   10483:                 $layer = null;
                   10484:                 break;
                   10485:             case 2:
                   10486:                 $config_key = $params[0];
                   10487:                 $layer = $params[1];
                   10488:                 if ($error = $this->_checkLayer($layer)) {
                   10489:                     return $this->raiseError("config-get:$error");
                   10490:                 }
                   10491:                 break;
                   10492:             case 0:
                   10493:             default:
                   10494:                 return $this->raiseError("config-get expects 1 or 2 parameters");
                   10495:         }
                   10496: 
                   10497:         $reg = &$this->config->getRegistry();
                   10498:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   10499:         if (!$reg->channelExists($channel)) {
                   10500:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10501:         }
                   10502: 
                   10503:         $channel = $reg->channelName($channel);
                   10504:         $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
                   10505:         return true;
                   10506:     }
                   10507: 
                   10508:     function doConfigSet($command, $options, $params)
                   10509:     {
                   10510:         // $param[0] -> a parameter to set
                   10511:         // $param[1] -> the value for the parameter
                   10512:         // $param[2] -> the layer
                   10513:         $failmsg = '';
                   10514:         if (count($params) < 2 || count($params) > 3) {
                   10515:             $failmsg .= "config-set expects 2 or 3 parameters";
                   10516:             return PEAR::raiseError($failmsg);
                   10517:         }
                   10518: 
                   10519:         if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
                   10520:             $failmsg .= $error;
                   10521:             return PEAR::raiseError("config-set:$failmsg");
                   10522:         }
                   10523: 
                   10524:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   10525:         $reg = &$this->config->getRegistry();
                   10526:         if (!$reg->channelExists($channel)) {
                   10527:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10528:         }
                   10529: 
                   10530:         $channel = $reg->channelName($channel);
                   10531:         if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
                   10532:             return $this->raiseError('Channel "' . $params[1] . '" does not exist');
                   10533:         }
                   10534: 
                   10535:         if ($params[0] == 'preferred_mirror'
                   10536:             && (
                   10537:                 !$reg->mirrorExists($channel, $params[1]) &&
                   10538:                 (!$reg->channelExists($params[1]) || $channel != $params[1])
                   10539:             )
                   10540:         ) {
                   10541:             $msg  = 'Channel Mirror "' . $params[1] . '" does not exist';
                   10542:             $msg .= ' in your registry for channel "' . $channel . '".';
                   10543:             $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
                   10544:             $msg .= ' if you believe this mirror should exist as you may';
                   10545:             $msg .= ' have outdated channel information.';
                   10546:             return $this->raiseError($msg);
                   10547:         }
                   10548: 
                   10549:         if (count($params) == 2) {
                   10550:             array_push($params, 'user');
                   10551:             $layer = 'user';
                   10552:         } else {
                   10553:             $layer = $params[2];
                   10554:         }
                   10555: 
                   10556:         array_push($params, $channel);
                   10557:         if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
                   10558:             array_pop($params);
                   10559:             $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
                   10560:         } else {
                   10561:             $this->config->store($layer);
                   10562:         }
                   10563: 
                   10564:         if ($failmsg) {
                   10565:             return $this->raiseError($failmsg);
                   10566:         }
                   10567: 
                   10568:         $this->ui->outputData('config-set succeeded', $command);
                   10569:         return true;
                   10570:     }
                   10571: 
                   10572:     function doConfigHelp($command, $options, $params)
                   10573:     {
                   10574:         if (empty($params)) {
                   10575:             $params = $this->config->getKeys();
                   10576:         }
                   10577: 
                   10578:         $data['caption']  = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
                   10579:         $data['headline'] = array('Name', 'Type', 'Description');
                   10580:         $data['border']   = true;
                   10581:         foreach ($params as $name) {
                   10582:             $type = $this->config->getType($name);
                   10583:             $docs = $this->config->getDocs($name);
                   10584:             if ($type == 'set') {
                   10585:                 $docs = rtrim($docs) . "\nValid set: " .
                   10586:                     implode(' ', $this->config->getSetValues($name));
                   10587:             }
                   10588: 
                   10589:             $data['data'][] = array($name, $type, $docs);
                   10590:         }
                   10591: 
                   10592:         $this->ui->outputData($data, $command);
                   10593:     }
                   10594: 
                   10595:     function doConfigCreate($command, $options, $params)
                   10596:     {
                   10597:         if (count($params) != 2) {
                   10598:             return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
                   10599:                 'filename to save as');
                   10600:         }
                   10601: 
                   10602:         $root = $params[0];
                   10603:         // Clean up the DIRECTORY_SEPARATOR mess
                   10604:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   10605:         $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
                   10606:                              array('/', '/', '/'),
                   10607:                             $root);
                   10608:         if ($root{0} != '/') {
                   10609:             if (!isset($options['windows'])) {
                   10610:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                   10611:                     'with "/", was: "' . $root . '"');
                   10612:             }
                   10613: 
                   10614:             if (!preg_match('/^[A-Za-z]:/', $root)) {
                   10615:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                   10616:                     'with "\\" or "C:\\", was: "' . $root . '"');
                   10617:             }
                   10618:         }
                   10619: 
                   10620:         $windows = isset($options['windows']);
                   10621:         if ($windows) {
                   10622:             $root = str_replace('/', '\\', $root);
                   10623:         }
                   10624: 
                   10625:         if (!file_exists($params[1]) && !@touch($params[1])) {
                   10626:             return PEAR::raiseError('Could not create "' . $params[1] . '"');
                   10627:         }
                   10628: 
                   10629:         $params[1] = realpath($params[1]);
                   10630:         $config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
                   10631:         if ($root{strlen($root) - 1} == '/') {
                   10632:             $root = substr($root, 0, strlen($root) - 1);
                   10633:         }
                   10634: 
                   10635:         $config->noRegistry();
                   10636:         $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
                   10637:         $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
                   10638:         $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
                   10639:         $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
                   10640:         $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
                   10641:         $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
                   10642:         $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
                   10643:         $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
                   10644:         $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
                   10645:         $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
                   10646:         $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
                   10647:         $config->writeConfigFile();
                   10648:         $this->_showConfig($config);
                   10649:         $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
                   10650:             $command);
                   10651:     }
                   10652: 
                   10653:     function _showConfig(&$config)
                   10654:     {
                   10655:         $params = array('user');
                   10656:         $keys = $config->getKeys();
                   10657:         sort($keys);
                   10658:         $channel = 'pear.php.net';
                   10659:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
                   10660:         foreach ($keys as $key) {
                   10661:             $type = $config->getType($key);
                   10662:             $value = $config->get($key, 'user', $channel);
                   10663:             if ($type == 'password' && $value) {
                   10664:                 $value = '********';
                   10665:             }
                   10666: 
                   10667:             if ($value === false) {
                   10668:                 $value = 'false';
                   10669:             } elseif ($value === true) {
                   10670:                 $value = 'true';
                   10671:             }
                   10672:             $data['data'][$config->getGroup($key)][] =
                   10673:                 array($config->getPrompt($key) , $key, $value);
                   10674:         }
                   10675: 
                   10676:         foreach ($config->getLayers() as $layer) {
                   10677:             $data['data']['Config Files'][] =
                   10678:                 array(ucfirst($layer) . ' Configuration File', 'Filename' ,
                   10679:                     $config->getConfFile($layer));
                   10680:         }
                   10681: 
                   10682:         $this->ui->outputData($data, 'config-show');
                   10683:         return true;
                   10684:     }
                   10685: 
                   10686:     /**
                   10687:      * Checks if a layer is defined or not
                   10688:      *
                   10689:      * @param string $layer The layer to search for
                   10690:      * @return mixed False on no error or the error message
                   10691:      */
                   10692:     function _checkLayer($layer = null)
                   10693:     {
                   10694:         if (!empty($layer) && $layer != 'default') {
                   10695:             $layers = $this->config->getLayers();
                   10696:             if (!in_array($layer, $layers)) {
                   10697:                 return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
                   10698:             }
                   10699:         }
                   10700: 
                   10701:         return false;
                   10702:     }
                   10703: }PEAR-1.9.4/PEAR/Command/Install.xml0000644000076500000240000002057611605156760015505 0ustar  helgistaff<commands version="1.0">
                   10704:  <install>
                   10705:   <summary>Install Package</summary>
                   10706:   <function>doInstall</function>
                   10707:   <shortcut>i</shortcut>
                   10708:   <options>
                   10709:    <force>
                   10710:     <shortopt>f</shortopt>
                   10711:     <doc>will overwrite newer installed packages</doc>
                   10712:    </force>
                   10713:    <loose>
                   10714:     <shortopt>l</shortopt>
                   10715:     <doc>do not check for recommended dependency version</doc>
                   10716:    </loose>
                   10717:    <nodeps>
                   10718:     <shortopt>n</shortopt>
                   10719:     <doc>ignore dependencies, install anyway</doc>
                   10720:    </nodeps>
                   10721:    <register-only>
                   10722:     <shortopt>r</shortopt>
                   10723:     <doc>do not install files, only register the package as installed</doc>
                   10724:    </register-only>
                   10725:    <soft>
                   10726:     <shortopt>s</shortopt>
                   10727:     <doc>soft install, fail silently, or upgrade if already installed</doc>
                   10728:    </soft>
                   10729:    <nobuild>
                   10730:     <shortopt>B</shortopt>
                   10731:     <doc>don&#039;t build C extensions</doc>
                   10732:    </nobuild>
                   10733:    <nocompress>
                   10734:     <shortopt>Z</shortopt>
                   10735:     <doc>request uncompressed files when downloading</doc>
                   10736:    </nocompress>
                   10737:    <installroot>
                   10738:     <shortopt>R</shortopt>
                   10739:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   10740:     <arg>DIR</arg>
                   10741:    </installroot>
                   10742:    <packagingroot>
                   10743:     <shortopt>P</shortopt>
                   10744:     <doc>root directory used when packaging files, like RPM packaging</doc>
                   10745:     <arg>DIR</arg>
                   10746:    </packagingroot>
                   10747:    <ignore-errors>
                   10748:     <shortopt></shortopt>
                   10749:     <doc>force install even if there were errors</doc>
                   10750:    </ignore-errors>
                   10751:    <alldeps>
                   10752:     <shortopt>a</shortopt>
                   10753:     <doc>install all required and optional dependencies</doc>
                   10754:    </alldeps>
                   10755:    <onlyreqdeps>
                   10756:     <shortopt>o</shortopt>
                   10757:     <doc>install all required dependencies</doc>
                   10758:    </onlyreqdeps>
                   10759:    <offline>
                   10760:     <shortopt>O</shortopt>
                   10761:     <doc>do not attempt to download any urls or contact channels</doc>
                   10762:    </offline>
                   10763:    <pretend>
                   10764:     <shortopt>p</shortopt>
                   10765:     <doc>Only list the packages that would be downloaded</doc>
                   10766:    </pretend>
                   10767:   </options>
                   10768:   <doc>[channel/]&lt;package&gt; ...
                   10769: Installs one or more PEAR packages.  You can specify a package to
                   10770: install in four ways:
                   10771: 
                   10772: &quot;Package-1.0.tgz&quot; : installs from a local file
                   10773: 
                   10774: &quot;http://example.com/Package-1.0.tgz&quot; : installs from
                   10775: anywhere on the net.
                   10776: 
                   10777: &quot;package.xml&quot; : installs the package described in
                   10778: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   10779: another package manager such as RPM.
                   10780: 
                   10781: &quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
                   10782: ({config master_server}) and downloads the newest package with
                   10783: the preferred quality/state ({config preferred_state}).
                   10784: 
                   10785: To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
                   10786: Package state beta, use &quot;Package-beta.&quot;  To retrieve an uncompressed
                   10787: file, append .tar (make sure there is no file by the same name first)
                   10788: 
                   10789: To download a package from another channel, prefix with the channel name like
                   10790: &quot;channel/Package&quot;
                   10791: 
                   10792: More than one package may be specified at once.  It is ok to mix these
                   10793: four ways of specifying packages.
                   10794: </doc>
                   10795:  </install>
                   10796:  <upgrade>
                   10797:   <summary>Upgrade Package</summary>
                   10798:   <function>doInstall</function>
                   10799:   <shortcut>up</shortcut>
                   10800:   <options>
                   10801:    <channel>
                   10802:     <shortopt>c</shortopt>
                   10803:     <doc>upgrade packages from a specific channel</doc>
                   10804:     <arg>CHAN</arg>
                   10805:    </channel>
                   10806:    <force>
                   10807:     <shortopt>f</shortopt>
                   10808:     <doc>overwrite newer installed packages</doc>
                   10809:    </force>
                   10810:    <loose>
                   10811:     <shortopt>l</shortopt>
                   10812:     <doc>do not check for recommended dependency version</doc>
                   10813:    </loose>
                   10814:    <nodeps>
                   10815:     <shortopt>n</shortopt>
                   10816:     <doc>ignore dependencies, upgrade anyway</doc>
                   10817:    </nodeps>
                   10818:    <register-only>
                   10819:     <shortopt>r</shortopt>
                   10820:     <doc>do not install files, only register the package as upgraded</doc>
                   10821:    </register-only>
                   10822:    <nobuild>
                   10823:     <shortopt>B</shortopt>
                   10824:     <doc>don&#039;t build C extensions</doc>
                   10825:    </nobuild>
                   10826:    <nocompress>
                   10827:     <shortopt>Z</shortopt>
                   10828:     <doc>request uncompressed files when downloading</doc>
                   10829:    </nocompress>
                   10830:    <installroot>
                   10831:     <shortopt>R</shortopt>
                   10832:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   10833:     <arg>DIR</arg>
                   10834:    </installroot>
                   10835:    <ignore-errors>
                   10836:     <shortopt></shortopt>
                   10837:     <doc>force install even if there were errors</doc>
                   10838:    </ignore-errors>
                   10839:    <alldeps>
                   10840:     <shortopt>a</shortopt>
                   10841:     <doc>install all required and optional dependencies</doc>
                   10842:    </alldeps>
                   10843:    <onlyreqdeps>
                   10844:     <shortopt>o</shortopt>
                   10845:     <doc>install all required dependencies</doc>
                   10846:    </onlyreqdeps>
                   10847:    <offline>
                   10848:     <shortopt>O</shortopt>
                   10849:     <doc>do not attempt to download any urls or contact channels</doc>
                   10850:    </offline>
                   10851:    <pretend>
                   10852:     <shortopt>p</shortopt>
                   10853:     <doc>Only list the packages that would be downloaded</doc>
                   10854:    </pretend>
                   10855:   </options>
                   10856:   <doc>&lt;package&gt; ...
                   10857: Upgrades one or more PEAR packages.  See documentation for the
                   10858: &quot;install&quot; command for ways to specify a package.
                   10859: 
                   10860: When upgrading, your package will be updated if the provided new
                   10861: package has a higher version number (use the -f option if you need to
                   10862: upgrade anyway).
                   10863: 
                   10864: More than one package may be specified at once.
                   10865: </doc>
                   10866:  </upgrade>
                   10867:  <upgrade-all>
                   10868:   <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
                   10869:   <function>doUpgradeAll</function>
                   10870:   <shortcut>ua</shortcut>
                   10871:   <options>
                   10872:    <channel>
                   10873:     <shortopt>c</shortopt>
                   10874:     <doc>upgrade packages from a specific channel</doc>
                   10875:     <arg>CHAN</arg>
                   10876:    </channel>
                   10877:    <nodeps>
                   10878:     <shortopt>n</shortopt>
                   10879:     <doc>ignore dependencies, upgrade anyway</doc>
                   10880:    </nodeps>
                   10881:    <register-only>
                   10882:     <shortopt>r</shortopt>
                   10883:     <doc>do not install files, only register the package as upgraded</doc>
                   10884:    </register-only>
                   10885:    <nobuild>
                   10886:     <shortopt>B</shortopt>
                   10887:     <doc>don&#039;t build C extensions</doc>
                   10888:    </nobuild>
                   10889:    <nocompress>
                   10890:     <shortopt>Z</shortopt>
                   10891:     <doc>request uncompressed files when downloading</doc>
                   10892:    </nocompress>
                   10893:    <installroot>
                   10894:     <shortopt>R</shortopt>
                   10895:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   10896:     <arg>DIR</arg>
                   10897:    </installroot>
                   10898:    <ignore-errors>
                   10899:     <shortopt></shortopt>
                   10900:     <doc>force install even if there were errors</doc>
                   10901:    </ignore-errors>
                   10902:    <loose>
                   10903:     <shortopt></shortopt>
                   10904:     <doc>do not check for recommended dependency version</doc>
                   10905:    </loose>
                   10906:   </options>
                   10907:   <doc>
                   10908: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   10909: 
                   10910: Upgrades all packages that have a newer release available.  Upgrades are
                   10911: done only if there is a release available of the state specified in
                   10912: &quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
                   10913: more stable.
                   10914: </doc>
                   10915:  </upgrade-all>
                   10916:  <uninstall>
                   10917:   <summary>Un-install Package</summary>
                   10918:   <function>doUninstall</function>
                   10919:   <shortcut>un</shortcut>
                   10920:   <options>
                   10921:    <nodeps>
                   10922:     <shortopt>n</shortopt>
                   10923:     <doc>ignore dependencies, uninstall anyway</doc>
                   10924:    </nodeps>
                   10925:    <register-only>
                   10926:     <shortopt>r</shortopt>
                   10927:     <doc>do not remove files, only register the packages as not installed</doc>
                   10928:    </register-only>
                   10929:    <installroot>
                   10930:     <shortopt>R</shortopt>
                   10931:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   10932:     <arg>DIR</arg>
                   10933:    </installroot>
                   10934:    <ignore-errors>
                   10935:     <shortopt></shortopt>
                   10936:     <doc>force install even if there were errors</doc>
                   10937:    </ignore-errors>
                   10938:    <offline>
                   10939:     <shortopt>O</shortopt>
                   10940:     <doc>do not attempt to uninstall remotely</doc>
                   10941:    </offline>
                   10942:   </options>
                   10943:   <doc>[channel/]&lt;package&gt; ...
                   10944: Uninstalls one or more PEAR packages.  More than one package may be
                   10945: specified at once.  Prefix with channel name to uninstall from a
                   10946: channel not in your default channel ({config default_channel})
                   10947: </doc>
                   10948:  </uninstall>
                   10949:  <bundle>
                   10950:   <summary>Unpacks a Pecl Package</summary>
                   10951:   <function>doBundle</function>
                   10952:   <shortcut>bun</shortcut>
                   10953:   <options>
                   10954:    <destination>
                   10955:     <shortopt>d</shortopt>
                   10956:     <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
                   10957:     <arg>DIR</arg>
                   10958:    </destination>
                   10959:    <force>
                   10960:     <shortopt>f</shortopt>
                   10961:     <doc>Force the unpacking even if there were errors in the package</doc>
                   10962:    </force>
                   10963:   </options>
                   10964:   <doc>&lt;package&gt;
                   10965: Unpacks a Pecl Package into the selected location. It will download the
                   10966: package if needed.
                   10967: </doc>
                   10968:  </bundle>
                   10969:  <run-scripts>
                   10970:   <summary>Run Post-Install Scripts bundled with a package</summary>
                   10971:   <function>doRunScripts</function>
                   10972:   <shortcut>rs</shortcut>
                   10973:   <options />
                   10974:   <doc>&lt;package&gt;
                   10975: Run post-installation scripts in package &lt;package&gt;, if any exist.
                   10976: </doc>
                   10977:  </run-scripts>
                   10978: </commands>PEAR-1.9.4/PEAR/Command/Install.php0000644000076500000240000014323611605156760015473 0ustar  helgistaff<?php
                   10979: /**
                   10980:  * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
                   10981:  *
                   10982:  * PHP versions 4 and 5
                   10983:  *
                   10984:  * @category   pear
                   10985:  * @package    PEAR
                   10986:  * @author     Stig Bakken <ssb@php.net>
                   10987:  * @author     Greg Beaver <cellog@php.net>
                   10988:  * @copyright  1997-2009 The Authors
                   10989:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10990:  * @version    CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
                   10991:  * @link       http://pear.php.net/package/PEAR
                   10992:  * @since      File available since Release 0.1
                   10993:  */
                   10994: 
                   10995: /**
                   10996:  * base class
                   10997:  */
                   10998: require_once 'PEAR/Command/Common.php';
                   10999: 
                   11000: /**
                   11001:  * PEAR commands for installation or deinstallation/upgrading of
                   11002:  * packages.
                   11003:  *
                   11004:  * @category   pear
                   11005:  * @package    PEAR
                   11006:  * @author     Stig Bakken <ssb@php.net>
                   11007:  * @author     Greg Beaver <cellog@php.net>
                   11008:  * @copyright  1997-2009 The Authors
                   11009:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   11010:  * @version    Release: 1.9.4
                   11011:  * @link       http://pear.php.net/package/PEAR
                   11012:  * @since      Class available since Release 0.1
                   11013:  */
                   11014: class PEAR_Command_Install extends PEAR_Command_Common
                   11015: {
                   11016:     // {{{ properties
                   11017: 
                   11018:     var $commands = array(
                   11019:         'install' => array(
                   11020:             'summary' => 'Install Package',
                   11021:             'function' => 'doInstall',
                   11022:             'shortcut' => 'i',
                   11023:             'options' => array(
                   11024:                 'force' => array(
                   11025:                     'shortopt' => 'f',
                   11026:                     'doc' => 'will overwrite newer installed packages',
                   11027:                     ),
                   11028:                 'loose' => array(
                   11029:                     'shortopt' => 'l',
                   11030:                     'doc' => 'do not check for recommended dependency version',
                   11031:                     ),
                   11032:                 'nodeps' => array(
                   11033:                     'shortopt' => 'n',
                   11034:                     'doc' => 'ignore dependencies, install anyway',
                   11035:                     ),
                   11036:                 'register-only' => array(
                   11037:                     'shortopt' => 'r',
                   11038:                     'doc' => 'do not install files, only register the package as installed',
                   11039:                     ),
                   11040:                 'soft' => array(
                   11041:                     'shortopt' => 's',
                   11042:                     'doc' => 'soft install, fail silently, or upgrade if already installed',
                   11043:                     ),
                   11044:                 'nobuild' => array(
                   11045:                     'shortopt' => 'B',
                   11046:                     'doc' => 'don\'t build C extensions',
                   11047:                     ),
                   11048:                 'nocompress' => array(
                   11049:                     'shortopt' => 'Z',
                   11050:                     'doc' => 'request uncompressed files when downloading',
                   11051:                     ),
                   11052:                 'installroot' => array(
                   11053:                     'shortopt' => 'R',
                   11054:                     'arg' => 'DIR',
                   11055:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   11056:                     ),
                   11057:                 'packagingroot' => array(
                   11058:                     'shortopt' => 'P',
                   11059:                     'arg' => 'DIR',
                   11060:                     'doc' => 'root directory used when packaging files, like RPM packaging',
                   11061:                     ),
                   11062:                 'ignore-errors' => array(
                   11063:                     'doc' => 'force install even if there were errors',
                   11064:                     ),
                   11065:                 'alldeps' => array(
                   11066:                     'shortopt' => 'a',
                   11067:                     'doc' => 'install all required and optional dependencies',
                   11068:                     ),
                   11069:                 'onlyreqdeps' => array(
                   11070:                     'shortopt' => 'o',
                   11071:                     'doc' => 'install all required dependencies',
                   11072:                     ),
                   11073:                 'offline' => array(
                   11074:                     'shortopt' => 'O',
                   11075:                     'doc' => 'do not attempt to download any urls or contact channels',
                   11076:                     ),
                   11077:                 'pretend' => array(
                   11078:                     'shortopt' => 'p',
                   11079:                     'doc' => 'Only list the packages that would be downloaded',
                   11080:                     ),
                   11081:                 ),
                   11082:             'doc' => '[channel/]<package> ...
                   11083: Installs one or more PEAR packages.  You can specify a package to
                   11084: install in four ways:
                   11085: 
                   11086: "Package-1.0.tgz" : installs from a local file
                   11087: 
                   11088: "http://example.com/Package-1.0.tgz" : installs from
                   11089: anywhere on the net.
                   11090: 
                   11091: "package.xml" : installs the package described in
                   11092: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   11093: another package manager such as RPM.
                   11094: 
                   11095: "Package[-version/state][.tar]" : queries your default channel\'s server
                   11096: ({config master_server}) and downloads the newest package with
                   11097: the preferred quality/state ({config preferred_state}).
                   11098: 
                   11099: To retrieve Package version 1.1, use "Package-1.1," to retrieve
                   11100: Package state beta, use "Package-beta."  To retrieve an uncompressed
                   11101: file, append .tar (make sure there is no file by the same name first)
                   11102: 
                   11103: To download a package from another channel, prefix with the channel name like
                   11104: "channel/Package"
                   11105: 
                   11106: More than one package may be specified at once.  It is ok to mix these
                   11107: four ways of specifying packages.
                   11108: '),
                   11109:         'upgrade' => array(
                   11110:             'summary' => 'Upgrade Package',
                   11111:             'function' => 'doInstall',
                   11112:             'shortcut' => 'up',
                   11113:             'options' => array(
                   11114:                 'channel' => array(
                   11115:                     'shortopt' => 'c',
                   11116:                     'doc' => 'upgrade packages from a specific channel',
                   11117:                     'arg' => 'CHAN',
                   11118:                     ),
                   11119:                 'force' => array(
                   11120:                     'shortopt' => 'f',
                   11121:                     'doc' => 'overwrite newer installed packages',
                   11122:                     ),
                   11123:                 'loose' => array(
                   11124:                     'shortopt' => 'l',
                   11125:                     'doc' => 'do not check for recommended dependency version',
                   11126:                     ),
                   11127:                 'nodeps' => array(
                   11128:                     'shortopt' => 'n',
                   11129:                     'doc' => 'ignore dependencies, upgrade anyway',
                   11130:                     ),
                   11131:                 'register-only' => array(
                   11132:                     'shortopt' => 'r',
                   11133:                     'doc' => 'do not install files, only register the package as upgraded',
                   11134:                     ),
                   11135:                 'nobuild' => array(
                   11136:                     'shortopt' => 'B',
                   11137:                     'doc' => 'don\'t build C extensions',
                   11138:                     ),
                   11139:                 'nocompress' => array(
                   11140:                     'shortopt' => 'Z',
                   11141:                     'doc' => 'request uncompressed files when downloading',
                   11142:                     ),
                   11143:                 'installroot' => array(
                   11144:                     'shortopt' => 'R',
                   11145:                     'arg' => 'DIR',
                   11146:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   11147:                     ),
                   11148:                 'ignore-errors' => array(
                   11149:                     'doc' => 'force install even if there were errors',
                   11150:                     ),
                   11151:                 'alldeps' => array(
                   11152:                     'shortopt' => 'a',
                   11153:                     'doc' => 'install all required and optional dependencies',
                   11154:                     ),
                   11155:                 'onlyreqdeps' => array(
                   11156:                     'shortopt' => 'o',
                   11157:                     'doc' => 'install all required dependencies',
                   11158:                     ),
                   11159:                 'offline' => array(
                   11160:                     'shortopt' => 'O',
                   11161:                     'doc' => 'do not attempt to download any urls or contact channels',
                   11162:                     ),
                   11163:                 'pretend' => array(
                   11164:                     'shortopt' => 'p',
                   11165:                     'doc' => 'Only list the packages that would be downloaded',
                   11166:                     ),
                   11167:                 ),
                   11168:             'doc' => '<package> ...
                   11169: Upgrades one or more PEAR packages.  See documentation for the
                   11170: "install" command for ways to specify a package.
                   11171: 
                   11172: When upgrading, your package will be updated if the provided new
                   11173: package has a higher version number (use the -f option if you need to
                   11174: upgrade anyway).
                   11175: 
                   11176: More than one package may be specified at once.
                   11177: '),
                   11178:         'upgrade-all' => array(
                   11179:             'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
                   11180:             'function' => 'doUpgradeAll',
                   11181:             'shortcut' => 'ua',
                   11182:             'options' => array(
                   11183:                 'channel' => array(
                   11184:                     'shortopt' => 'c',
                   11185:                     'doc' => 'upgrade packages from a specific channel',
                   11186:                     'arg' => 'CHAN',
                   11187:                     ),
                   11188:                 'nodeps' => array(
                   11189:                     'shortopt' => 'n',
                   11190:                     'doc' => 'ignore dependencies, upgrade anyway',
                   11191:                     ),
                   11192:                 'register-only' => array(
                   11193:                     'shortopt' => 'r',
                   11194:                     'doc' => 'do not install files, only register the package as upgraded',
                   11195:                     ),
                   11196:                 'nobuild' => array(
                   11197:                     'shortopt' => 'B',
                   11198:                     'doc' => 'don\'t build C extensions',
                   11199:                     ),
                   11200:                 'nocompress' => array(
                   11201:                     'shortopt' => 'Z',
                   11202:                     'doc' => 'request uncompressed files when downloading',
                   11203:                     ),
                   11204:                 'installroot' => array(
                   11205:                     'shortopt' => 'R',
                   11206:                     'arg' => 'DIR',
                   11207:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   11208:                     ),
                   11209:                 'ignore-errors' => array(
                   11210:                     'doc' => 'force install even if there were errors',
                   11211:                     ),
                   11212:                 'loose' => array(
                   11213:                     'doc' => 'do not check for recommended dependency version',
                   11214:                     ),
                   11215:                 ),
                   11216:             'doc' => '
                   11217: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   11218: 
                   11219: Upgrades all packages that have a newer release available.  Upgrades are
                   11220: done only if there is a release available of the state specified in
                   11221: "preferred_state" (currently {config preferred_state}), or a state considered
                   11222: more stable.
                   11223: '),
                   11224:         'uninstall' => array(
                   11225:             'summary' => 'Un-install Package',
                   11226:             'function' => 'doUninstall',
                   11227:             'shortcut' => 'un',
                   11228:             'options' => array(
                   11229:                 'nodeps' => array(
                   11230:                     'shortopt' => 'n',
                   11231:                     'doc' => 'ignore dependencies, uninstall anyway',
                   11232:                     ),
                   11233:                 'register-only' => array(
                   11234:                     'shortopt' => 'r',
                   11235:                     'doc' => 'do not remove files, only register the packages as not installed',
                   11236:                     ),
                   11237:                 'installroot' => array(
                   11238:                     'shortopt' => 'R',
                   11239:                     'arg' => 'DIR',
                   11240:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   11241:                     ),
                   11242:                 'ignore-errors' => array(
                   11243:                     'doc' => 'force install even if there were errors',
                   11244:                     ),
                   11245:                 'offline' => array(
                   11246:                     'shortopt' => 'O',
                   11247:                     'doc' => 'do not attempt to uninstall remotely',
                   11248:                     ),
                   11249:                 ),
                   11250:             'doc' => '[channel/]<package> ...
                   11251: Uninstalls one or more PEAR packages.  More than one package may be
                   11252: specified at once.  Prefix with channel name to uninstall from a
                   11253: channel not in your default channel ({config default_channel})
                   11254: '),
                   11255:         'bundle' => array(
                   11256:             'summary' => 'Unpacks a Pecl Package',
                   11257:             'function' => 'doBundle',
                   11258:             'shortcut' => 'bun',
                   11259:             'options' => array(
                   11260:                 'destination' => array(
                   11261:                    'shortopt' => 'd',
                   11262:                     'arg' => 'DIR',
                   11263:                     'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
                   11264:                     ),
                   11265:                 'force' => array(
                   11266:                     'shortopt' => 'f',
                   11267:                     'doc' => 'Force the unpacking even if there were errors in the package',
                   11268:                 ),
                   11269:             ),
                   11270:             'doc' => '<package>
                   11271: Unpacks a Pecl Package into the selected location. It will download the
                   11272: package if needed.
                   11273: '),
                   11274:         'run-scripts' => array(
                   11275:             'summary' => 'Run Post-Install Scripts bundled with a package',
                   11276:             'function' => 'doRunScripts',
                   11277:             'shortcut' => 'rs',
                   11278:             'options' => array(
                   11279:             ),
                   11280:             'doc' => '<package>
                   11281: Run post-installation scripts in package <package>, if any exist.
                   11282: '),
                   11283:     );
                   11284: 
                   11285:     // }}}
                   11286:     // {{{ constructor
                   11287: 
                   11288:     /**
                   11289:      * PEAR_Command_Install constructor.
                   11290:      *
                   11291:      * @access public
                   11292:      */
                   11293:     function PEAR_Command_Install(&$ui, &$config)
                   11294:     {
                   11295:         parent::PEAR_Command_Common($ui, $config);
                   11296:     }
                   11297: 
                   11298:     // }}}
                   11299: 
                   11300:     /**
                   11301:      * For unit testing purposes
                   11302:      */
                   11303:     function &getDownloader(&$ui, $options, &$config)
                   11304:     {
                   11305:         if (!class_exists('PEAR_Downloader')) {
                   11306:             require_once 'PEAR/Downloader.php';
                   11307:         }
                   11308:         $a = &new PEAR_Downloader($ui, $options, $config);
                   11309:         return $a;
                   11310:     }
                   11311: 
                   11312:     /**
                   11313:      * For unit testing purposes
                   11314:      */
                   11315:     function &getInstaller(&$ui)
                   11316:     {
                   11317:         if (!class_exists('PEAR_Installer')) {
                   11318:             require_once 'PEAR/Installer.php';
                   11319:         }
                   11320:         $a = &new PEAR_Installer($ui);
                   11321:         return $a;
                   11322:     }
                   11323: 
                   11324:     function enableExtension($binaries, $type)
                   11325:     {
                   11326:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   11327:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   11328:         }
                   11329:         $ini = $this->_parseIni($phpini);
                   11330:         if (PEAR::isError($ini)) {
                   11331:             return $ini;
                   11332:         }
                   11333:         $line = 0;
                   11334:         if ($type == 'extsrc' || $type == 'extbin') {
                   11335:             $search = 'extensions';
                   11336:             $enable = 'extension';
                   11337:         } else {
                   11338:             $search = 'zend_extensions';
                   11339:             ob_start();
                   11340:             phpinfo(INFO_GENERAL);
                   11341:             $info = ob_get_contents();
                   11342:             ob_end_clean();
                   11343:             $debug = function_exists('leak') ? '_debug' : '';
                   11344:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11345:             $enable = 'zend_extension' . $debug . $ts;
                   11346:         }
                   11347:         foreach ($ini[$search] as $line => $extension) {
                   11348:             if (in_array($extension, $binaries, true) || in_array(
                   11349:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   11350:                 // already enabled - assume if one is, all are
                   11351:                 return true;
                   11352:             }
                   11353:         }
                   11354:         if ($line) {
                   11355:             $newini = array_slice($ini['all'], 0, $line);
                   11356:         } else {
                   11357:             $newini = array();
                   11358:         }
                   11359:         foreach ($binaries as $binary) {
                   11360:             if ($ini['extension_dir']) {
                   11361:                 $binary = basename($binary);
                   11362:             }
                   11363:             $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
                   11364:         }
                   11365:         $newini = array_merge($newini, array_slice($ini['all'], $line));
                   11366:         $fp = @fopen($phpini, 'wb');
                   11367:         if (!$fp) {
                   11368:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   11369:         }
                   11370:         foreach ($newini as $line) {
                   11371:             fwrite($fp, $line);
                   11372:         }
                   11373:         fclose($fp);
                   11374:         return true;
                   11375:     }
                   11376: 
                   11377:     function disableExtension($binaries, $type)
                   11378:     {
                   11379:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   11380:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   11381:         }
                   11382:         $ini = $this->_parseIni($phpini);
                   11383:         if (PEAR::isError($ini)) {
                   11384:             return $ini;
                   11385:         }
                   11386:         $line = 0;
                   11387:         if ($type == 'extsrc' || $type == 'extbin') {
                   11388:             $search = 'extensions';
                   11389:             $enable = 'extension';
                   11390:         } else {
                   11391:             $search = 'zend_extensions';
                   11392:             ob_start();
                   11393:             phpinfo(INFO_GENERAL);
                   11394:             $info = ob_get_contents();
                   11395:             ob_end_clean();
                   11396:             $debug = function_exists('leak') ? '_debug' : '';
                   11397:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11398:             $enable = 'zend_extension' . $debug . $ts;
                   11399:         }
                   11400:         $found = false;
                   11401:         foreach ($ini[$search] as $line => $extension) {
                   11402:             if (in_array($extension, $binaries, true) || in_array(
                   11403:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   11404:                 $found = true;
                   11405:                 break;
                   11406:             }
                   11407:         }
                   11408:         if (!$found) {
                   11409:             // not enabled
                   11410:             return true;
                   11411:         }
                   11412:         $fp = @fopen($phpini, 'wb');
                   11413:         if (!$fp) {
                   11414:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   11415:         }
                   11416:         if ($line) {
                   11417:             $newini = array_slice($ini['all'], 0, $line);
                   11418:             // delete the enable line
                   11419:             $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
                   11420:         } else {
                   11421:             $newini = array_slice($ini['all'], 1);
                   11422:         }
                   11423:         foreach ($newini as $line) {
                   11424:             fwrite($fp, $line);
                   11425:         }
                   11426:         fclose($fp);
                   11427:         return true;
                   11428:     }
                   11429: 
                   11430:     function _parseIni($filename)
                   11431:     {
                   11432:         if (!file_exists($filename)) {
                   11433:             return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
                   11434:         }
                   11435: 
                   11436:         if (filesize($filename) > 300000) {
                   11437:             return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
                   11438:         }
                   11439: 
                   11440:         ob_start();
                   11441:         phpinfo(INFO_GENERAL);
                   11442:         $info = ob_get_contents();
                   11443:         ob_end_clean();
                   11444:         $debug = function_exists('leak') ? '_debug' : '';
                   11445:         $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11446:         $zend_extension_line = 'zend_extension' . $debug . $ts;
                   11447:         $all = @file($filename);
                   11448:         if (!$all) {
                   11449:             return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
                   11450:         }
                   11451:         $zend_extensions = $extensions = array();
                   11452:         // assume this is right, but pull from the php.ini if it is found
                   11453:         $extension_dir = ini_get('extension_dir');
                   11454:         foreach ($all as $linenum => $line) {
                   11455:             $line = trim($line);
                   11456:             if (!$line) {
                   11457:                 continue;
                   11458:             }
                   11459:             if ($line[0] == ';') {
                   11460:                 continue;
                   11461:             }
                   11462:             if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
                   11463:                 $line = trim(substr($line, 13));
                   11464:                 if ($line[0] == '=') {
                   11465:                     $x = trim(substr($line, 1));
                   11466:                     $x = explode(';', $x);
                   11467:                     $extension_dir = str_replace('"', '', array_shift($x));
                   11468:                     continue;
                   11469:                 }
                   11470:             }
                   11471:             if (strtolower(substr($line, 0, 9)) == 'extension') {
                   11472:                 $line = trim(substr($line, 9));
                   11473:                 if ($line[0] == '=') {
                   11474:                     $x = trim(substr($line, 1));
                   11475:                     $x = explode(';', $x);
                   11476:                     $extensions[$linenum] = str_replace('"', '', array_shift($x));
                   11477:                     continue;
                   11478:                 }
                   11479:             }
                   11480:             if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
                   11481:                   $zend_extension_line) {
                   11482:                 $line = trim(substr($line, strlen($zend_extension_line)));
                   11483:                 if ($line[0] == '=') {
                   11484:                     $x = trim(substr($line, 1));
                   11485:                     $x = explode(';', $x);
                   11486:                     $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
                   11487:                     continue;
                   11488:                 }
                   11489:             }
                   11490:         }
                   11491:         return array(
                   11492:             'extensions' => $extensions,
                   11493:             'zend_extensions' => $zend_extensions,
                   11494:             'extension_dir' => $extension_dir,
                   11495:             'all' => $all,
                   11496:         );
                   11497:     }
                   11498: 
                   11499:     // {{{ doInstall()
                   11500: 
                   11501:     function doInstall($command, $options, $params)
                   11502:     {
                   11503:         if (!class_exists('PEAR_PackageFile')) {
                   11504:             require_once 'PEAR/PackageFile.php';
                   11505:         }
                   11506: 
                   11507:         if (isset($options['installroot']) && isset($options['packagingroot'])) {
                   11508:             return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
                   11509:         }
                   11510: 
                   11511:         $reg = &$this->config->getRegistry();
                   11512:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   11513:         if (!$reg->channelExists($channel)) {
                   11514:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   11515:         }
                   11516: 
                   11517:         if (empty($this->installer)) {
                   11518:             $this->installer = &$this->getInstaller($this->ui);
                   11519:         }
                   11520: 
                   11521:         if ($command == 'upgrade' || $command == 'upgrade-all') {
                   11522:             // If people run the upgrade command but pass nothing, emulate a upgrade-all
                   11523:             if ($command == 'upgrade' && empty($params)) {
                   11524:                 return $this->doUpgradeAll($command, $options, $params);
                   11525:             }
                   11526:             $options['upgrade'] = true;
                   11527:         } else {
                   11528:             $packages = $params;
                   11529:         }
                   11530: 
                   11531:         $instreg = &$reg; // instreg used to check if package is installed
                   11532:         if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
                   11533:             $packrootphp_dir = $this->installer->_prependPath(
                   11534:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   11535:                 $options['packagingroot']);
                   11536:             $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
                   11537: 
                   11538:             if ($this->config->get('verbose') > 2) {
                   11539:                 $this->ui->outputData('using package root: ' . $options['packagingroot']);
                   11540:             }
                   11541:         }
                   11542: 
                   11543:         $abstractpackages = $otherpackages = array();
                   11544:         // parse params
                   11545:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11546: 
                   11547:         foreach ($params as $param) {
                   11548:             if (strpos($param, 'http://') === 0) {
                   11549:                 $otherpackages[] = $param;
                   11550:                 continue;
                   11551:             }
                   11552: 
                   11553:             if (strpos($param, 'channel://') === false && @file_exists($param)) {
                   11554:                 if (isset($options['force'])) {
                   11555:                     $otherpackages[] = $param;
                   11556:                     continue;
                   11557:                 }
                   11558: 
                   11559:                 $pkg = new PEAR_PackageFile($this->config);
                   11560:                 $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
                   11561:                 if (PEAR::isError($pf)) {
                   11562:                     $otherpackages[] = $param;
                   11563:                     continue;
                   11564:                 }
                   11565: 
                   11566:                 $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
                   11567:                 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
                   11568:                 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
                   11569:                 if ($exists && $version_compare) {
                   11570:                     if ($this->config->get('verbose')) {
                   11571:                         $this->ui->outputData('Ignoring installed package ' .
                   11572:                             $reg->parsedPackageNameToString(
                   11573:                             array('package' => $pf->getPackage(),
                   11574:                                   'channel' => $pf->getChannel()), true));
                   11575:                     }
                   11576:                     continue;
                   11577:                 }
                   11578:                 $otherpackages[] = $param;
                   11579:                 continue;
                   11580:             }
                   11581: 
                   11582:             $e = $reg->parsePackageName($param, $channel);
                   11583:             if (PEAR::isError($e)) {
                   11584:                 $otherpackages[] = $param;
                   11585:             } else {
                   11586:                 $abstractpackages[] = $e;
                   11587:             }
                   11588:         }
                   11589:         PEAR::staticPopErrorHandling();
                   11590: 
                   11591:         // if there are any local package .tgz or remote static url, we can't
                   11592:         // filter.  The filter only works for abstract packages
                   11593:         if (count($abstractpackages) && !isset($options['force'])) {
                   11594:             // when not being forced, only do necessary upgrades/installs
                   11595:             if (isset($options['upgrade'])) {
                   11596:                 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
                   11597:             } else {
                   11598:                 $count = count($abstractpackages);
                   11599:                 foreach ($abstractpackages as $i => $package) {
                   11600:                     if (isset($package['group'])) {
                   11601:                         // do not filter out install groups
                   11602:                         continue;
                   11603:                     }
                   11604: 
                   11605:                     if ($instreg->packageExists($package['package'], $package['channel'])) {
                   11606:                         if ($count > 1) {
                   11607:                             if ($this->config->get('verbose')) {
                   11608:                                 $this->ui->outputData('Ignoring installed package ' .
                   11609:                                     $reg->parsedPackageNameToString($package, true));
                   11610:                             }
                   11611:                             unset($abstractpackages[$i]);
                   11612:                         } elseif ($count === 1) {
                   11613:                             // Lets try to upgrade it since it's already installed
                   11614:                             $options['upgrade'] = true;
                   11615:                         }
                   11616:                     }
                   11617:                 }
                   11618:             }
                   11619:             $abstractpackages =
                   11620:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   11621:         } elseif (count($abstractpackages)) {
                   11622:             $abstractpackages =
                   11623:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   11624:         }
                   11625: 
                   11626:         $packages = array_merge($abstractpackages, $otherpackages);
                   11627:         if (!count($packages)) {
                   11628:             $c = '';
                   11629:             if (isset($options['channel'])){
                   11630:                 $c .= ' in channel "' . $options['channel'] . '"';
                   11631:             }
                   11632:             $this->ui->outputData('Nothing to ' . $command . $c);
                   11633:             return true;
                   11634:         }
                   11635: 
                   11636:         $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
                   11637:         $errors = $downloaded = $binaries = array();
                   11638:         $downloaded = &$this->downloader->download($packages);
                   11639:         if (PEAR::isError($downloaded)) {
                   11640:             return $this->raiseError($downloaded);
                   11641:         }
                   11642: 
                   11643:         $errors = $this->downloader->getErrorMsgs();
                   11644:         if (count($errors)) {
                   11645:             $err = array();
                   11646:             $err['data'] = array();
                   11647:             foreach ($errors as $error) {
                   11648:                 if ($error !== null) {
                   11649:                     $err['data'][] = array($error);
                   11650:                 }
                   11651:             }
                   11652: 
                   11653:             if (!empty($err['data'])) {
                   11654:                 $err['headline'] = 'Install Errors';
                   11655:                 $this->ui->outputData($err);
                   11656:             }
                   11657: 
                   11658:             if (!count($downloaded)) {
                   11659:                 return $this->raiseError("$command failed");
                   11660:             }
                   11661:         }
                   11662: 
                   11663:         $data = array(
                   11664:             'headline' => 'Packages that would be Installed'
                   11665:         );
                   11666: 
                   11667:         if (isset($options['pretend'])) {
                   11668:             foreach ($downloaded as $package) {
                   11669:                 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
                   11670:             }
                   11671:             $this->ui->outputData($data, 'pretend');
                   11672:             return true;
                   11673:         }
                   11674: 
                   11675:         $this->installer->setOptions($options);
                   11676:         $this->installer->sortPackagesForInstall($downloaded);
                   11677:         if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
                   11678:             $this->raiseError($err->getMessage());
                   11679:             return true;
                   11680:         }
                   11681: 
                   11682:         $binaries = $extrainfo = array();
                   11683:         foreach ($downloaded as $param) {
                   11684:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11685:             $info = $this->installer->install($param, $options);
                   11686:             PEAR::staticPopErrorHandling();
                   11687:             if (PEAR::isError($info)) {
                   11688:                 $oldinfo = $info;
                   11689:                 $pkg = &$param->getPackageFile();
                   11690:                 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
                   11691:                     if (!($info = $pkg->installBinary($this->installer))) {
                   11692:                         $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
                   11693:                         continue;
                   11694:                     }
                   11695: 
                   11696:                     // we just installed a different package than requested,
                   11697:                     // let's change the param and info so that the rest of this works
                   11698:                     $param = $info[0];
                   11699:                     $info  = $info[1];
                   11700:                 }
                   11701:             }
                   11702: 
                   11703:             if (!is_array($info)) {
                   11704:                 return $this->raiseError("$command failed");
                   11705:             }
                   11706: 
                   11707:             if ($param->getPackageType() == 'extsrc' ||
                   11708:                   $param->getPackageType() == 'extbin' ||
                   11709:                   $param->getPackageType() == 'zendextsrc' ||
                   11710:                   $param->getPackageType() == 'zendextbin'
                   11711:             ) {
                   11712:                 $pkg = &$param->getPackageFile();
                   11713:                 if ($instbin = $pkg->getInstalledBinary()) {
                   11714:                     $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
                   11715:                 } else {
                   11716:                     $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
                   11717:                 }
                   11718: 
                   11719:                 foreach ($instpkg->getFilelist() as $name => $atts) {
                   11720:                     $pinfo = pathinfo($atts['installed_as']);
                   11721:                     if (!isset($pinfo['extension']) ||
                   11722:                           in_array($pinfo['extension'], array('c', 'h'))
                   11723:                     ) {
                   11724:                         continue; // make sure we don't match php_blah.h
                   11725:                     }
                   11726: 
                   11727:                     if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   11728:                           $pinfo['extension'] == 'dll') ||
                   11729:                           // most unices
                   11730:                           $pinfo['extension'] == 'so' ||
                   11731:                           // hp-ux
                   11732:                           $pinfo['extension'] == 'sl') {
                   11733:                         $binaries[] = array($atts['installed_as'], $pinfo);
                   11734:                         break;
                   11735:                     }
                   11736:                 }
                   11737: 
                   11738:                 if (count($binaries)) {
                   11739:                     foreach ($binaries as $pinfo) {
                   11740:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11741:                         $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
                   11742:                         PEAR::staticPopErrorHandling();
                   11743:                         if (PEAR::isError($ret)) {
                   11744:                             $extrainfo[] = $ret->getMessage();
                   11745:                             if ($param->getPackageType() == 'extsrc' ||
                   11746:                                   $param->getPackageType() == 'extbin') {
                   11747:                                 $exttype = 'extension';
                   11748:                             } else {
                   11749:                                 ob_start();
                   11750:                                 phpinfo(INFO_GENERAL);
                   11751:                                 $info = ob_get_contents();
                   11752:                                 ob_end_clean();
                   11753:                                 $debug = function_exists('leak') ? '_debug' : '';
                   11754:                                 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11755:                                 $exttype = 'zend_extension' . $debug . $ts;
                   11756:                             }
                   11757:                             $extrainfo[] = 'You should add "' . $exttype . '=' .
                   11758:                                 $pinfo[1]['basename'] . '" to php.ini';
                   11759:                         } else {
                   11760:                             $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
                   11761:                                 ' enabled in php.ini';
                   11762:                         }
                   11763:                     }
                   11764:                 }
                   11765:             }
                   11766: 
                   11767:             if ($this->config->get('verbose') > 0) {
                   11768:                 $chan = $param->getChannel();
                   11769:                 $label = $reg->parsedPackageNameToString(
                   11770:                     array(
                   11771:                         'channel' => $chan,
                   11772:                         'package' => $param->getPackage(),
                   11773:                         'version' => $param->getVersion(),
                   11774:                     ));
                   11775:                 $out = array('data' => "$command ok: $label");
                   11776:                 if (isset($info['release_warnings'])) {
                   11777:                     $out['release_warnings'] = $info['release_warnings'];
                   11778:                 }
                   11779:                 $this->ui->outputData($out, $command);
                   11780: 
                   11781:                 if (!isset($options['register-only']) && !isset($options['offline'])) {
                   11782:                     if ($this->config->isDefinedLayer('ftp')) {
                   11783:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11784:                         $info = $this->installer->ftpInstall($param);
                   11785:                         PEAR::staticPopErrorHandling();
                   11786:                         if (PEAR::isError($info)) {
                   11787:                             $this->ui->outputData($info->getMessage());
                   11788:                             $this->ui->outputData("remote install failed: $label");
                   11789:                         } else {
                   11790:                             $this->ui->outputData("remote install ok: $label");
                   11791:                         }
                   11792:                     }
                   11793:                 }
                   11794:             }
                   11795: 
                   11796:             $deps = $param->getDeps();
                   11797:             if ($deps) {
                   11798:                 if (isset($deps['group'])) {
                   11799:                     $groups = $deps['group'];
                   11800:                     if (!isset($groups[0])) {
                   11801:                         $groups = array($groups);
                   11802:                     }
                   11803: 
                   11804:                     foreach ($groups as $group) {
                   11805:                         if ($group['attribs']['name'] == 'default') {
                   11806:                             // default group is always installed, unless the user
                   11807:                             // explicitly chooses to install another group
                   11808:                             continue;
                   11809:                         }
                   11810:                         $extrainfo[] = $param->getPackage() . ': Optional feature ' .
                   11811:                             $group['attribs']['name'] . ' available (' .
                   11812:                             $group['attribs']['hint'] . ')';
                   11813:                     }
                   11814: 
                   11815:                     $extrainfo[] = $param->getPackage() .
                   11816:                         ': To install optional features use "pear install ' .
                   11817:                         $reg->parsedPackageNameToString(
                   11818:                             array('package' => $param->getPackage(),
                   11819:                                   'channel' => $param->getChannel()), true) .
                   11820:                               '#featurename"';
                   11821:                 }
                   11822:             }
                   11823: 
                   11824:             $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
                   11825:             // $pkg may be NULL if install is a 'fake' install via --packagingroot
                   11826:             if (is_object($pkg)) {
                   11827:                 $pkg->setConfig($this->config);
                   11828:                 if ($list = $pkg->listPostinstallScripts()) {
                   11829:                     $pn = $reg->parsedPackageNameToString(array('channel' =>
                   11830:                        $param->getChannel(), 'package' => $param->getPackage()), true);
                   11831:                     $extrainfo[] = $pn . ' has post-install scripts:';
                   11832:                     foreach ($list as $file) {
                   11833:                         $extrainfo[] = $file;
                   11834:                     }
                   11835:                     $extrainfo[] = $param->getPackage() .
                   11836:                         ': Use "pear run-scripts ' . $pn . '" to finish setup.';
                   11837:                     $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
                   11838:                 }
                   11839:             }
                   11840:         }
                   11841: 
                   11842:         if (count($extrainfo)) {
                   11843:             foreach ($extrainfo as $info) {
                   11844:                 $this->ui->outputData($info);
                   11845:             }
                   11846:         }
                   11847: 
                   11848:         return true;
                   11849:     }
                   11850: 
                   11851:     // }}}
                   11852:     // {{{ doUpgradeAll()
                   11853: 
                   11854:     function doUpgradeAll($command, $options, $params)
                   11855:     {
                   11856:         $reg = &$this->config->getRegistry();
                   11857:         $upgrade = array();
                   11858: 
                   11859:         if (isset($options['channel'])) {
                   11860:             $channels = array($options['channel']);
                   11861:         } else {
                   11862:             $channels = $reg->listChannels();
                   11863:         }
                   11864: 
                   11865:         foreach ($channels as $channel) {
                   11866:             if ($channel == '__uri') {
                   11867:                 continue;
                   11868:             }
                   11869: 
                   11870:             // parse name with channel
                   11871:             foreach ($reg->listPackages($channel) as $name) {
                   11872:                 $upgrade[] = $reg->parsedPackageNameToString(array(
                   11873:                         'channel' => $channel,
                   11874:                         'package' => $name
                   11875:                     ));
                   11876:             }
                   11877:         }
                   11878: 
                   11879:         $err = $this->doInstall($command, $options, $upgrade);
                   11880:         if (PEAR::isError($err)) {
                   11881:             $this->ui->outputData($err->getMessage(), $command);
                   11882:         }
                   11883:    }
                   11884: 
                   11885:     // }}}
                   11886:     // {{{ doUninstall()
                   11887: 
                   11888:     function doUninstall($command, $options, $params)
                   11889:     {
                   11890:         if (count($params) < 1) {
                   11891:             return $this->raiseError("Please supply the package(s) you want to uninstall");
                   11892:         }
                   11893: 
                   11894:         if (empty($this->installer)) {
                   11895:             $this->installer = &$this->getInstaller($this->ui);
                   11896:         }
                   11897: 
                   11898:         if (isset($options['remoteconfig'])) {
                   11899:             $e = $this->config->readFTPConfigFile($options['remoteconfig']);
                   11900:             if (!PEAR::isError($e)) {
                   11901:                 $this->installer->setConfig($this->config);
                   11902:             }
                   11903:         }
                   11904: 
                   11905:         $reg = &$this->config->getRegistry();
                   11906:         $newparams = array();
                   11907:         $binaries = array();
                   11908:         $badparams = array();
                   11909:         foreach ($params as $pkg) {
                   11910:             $channel = $this->config->get('default_channel');
                   11911:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11912:             $parsed = $reg->parsePackageName($pkg, $channel);
                   11913:             PEAR::staticPopErrorHandling();
                   11914:             if (!$parsed || PEAR::isError($parsed)) {
                   11915:                 $badparams[] = $pkg;
                   11916:                 continue;
                   11917:             }
                   11918:             $package = $parsed['package'];
                   11919:             $channel = $parsed['channel'];
                   11920:             $info = &$reg->getPackage($package, $channel);
                   11921:             if ($info === null &&
                   11922:                  ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
                   11923:                 // make sure this isn't a package that has flipped from pear to pecl but
                   11924:                 // used a package.xml 1.0
                   11925:                 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
                   11926:                 $info = &$reg->getPackage($package, $testc);
                   11927:                 if ($info !== null) {
                   11928:                     $channel = $testc;
                   11929:                 }
                   11930:             }
                   11931:             if ($info === null) {
                   11932:                 $badparams[] = $pkg;
                   11933:             } else {
                   11934:                 $newparams[] = &$info;
                   11935:                 // check for binary packages (this is an alias for those packages if so)
                   11936:                 if ($installedbinary = $info->getInstalledBinary()) {
                   11937:                     $this->ui->log('adding binary package ' .
                   11938:                         $reg->parsedPackageNameToString(array('channel' => $channel,
                   11939:                             'package' => $installedbinary), true));
                   11940:                     $newparams[] = &$reg->getPackage($installedbinary, $channel);
                   11941:                 }
                   11942:                 // add the contents of a dependency group to the list of installed packages
                   11943:                 if (isset($parsed['group'])) {
                   11944:                     $group = $info->getDependencyGroup($parsed['group']);
                   11945:                     if ($group) {
                   11946:                         $installed = $reg->getInstalledGroup($group);
                   11947:                         if ($installed) {
                   11948:                             foreach ($installed as $i => $p) {
                   11949:                                 $newparams[] = &$installed[$i];
                   11950:                             }
                   11951:                         }
                   11952:                     }
                   11953:                 }
                   11954:             }
                   11955:         }
                   11956:         $err = $this->installer->sortPackagesForUninstall($newparams);
                   11957:         if (PEAR::isError($err)) {
                   11958:             $this->ui->outputData($err->getMessage(), $command);
                   11959:             return true;
                   11960:         }
                   11961:         $params = $newparams;
                   11962:         // twist this to use it to check on whether dependent packages are also being uninstalled
                   11963:         // for circular dependencies like subpackages
                   11964:         $this->installer->setUninstallPackages($newparams);
                   11965:         $params = array_merge($params, $badparams);
                   11966:         $binaries = array();
                   11967:         foreach ($params as $pkg) {
                   11968:             $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   11969:             if ($err = $this->installer->uninstall($pkg, $options)) {
                   11970:                 $this->installer->popErrorHandling();
                   11971:                 if (PEAR::isError($err)) {
                   11972:                     $this->ui->outputData($err->getMessage(), $command);
                   11973:                     continue;
                   11974:                 }
                   11975:                 if ($pkg->getPackageType() == 'extsrc' ||
                   11976:                       $pkg->getPackageType() == 'extbin' ||
                   11977:                       $pkg->getPackageType() == 'zendextsrc' ||
                   11978:                       $pkg->getPackageType() == 'zendextbin') {
                   11979:                     if ($instbin = $pkg->getInstalledBinary()) {
                   11980:                         continue; // this will be uninstalled later
                   11981:                     }
                   11982: 
                   11983:                     foreach ($pkg->getFilelist() as $name => $atts) {
                   11984:                         $pinfo = pathinfo($atts['installed_as']);
                   11985:                         if (!isset($pinfo['extension']) ||
                   11986:                               in_array($pinfo['extension'], array('c', 'h'))) {
                   11987:                             continue; // make sure we don't match php_blah.h
                   11988:                         }
                   11989:                         if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   11990:                               $pinfo['extension'] == 'dll') ||
                   11991:                               // most unices
                   11992:                               $pinfo['extension'] == 'so' ||
                   11993:                               // hp-ux
                   11994:                               $pinfo['extension'] == 'sl') {
                   11995:                             $binaries[] = array($atts['installed_as'], $pinfo);
                   11996:                             break;
                   11997:                         }
                   11998:                     }
                   11999:                     if (count($binaries)) {
                   12000:                         foreach ($binaries as $pinfo) {
                   12001:                             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12002:                             $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
                   12003:                             PEAR::staticPopErrorHandling();
                   12004:                             if (PEAR::isError($ret)) {
                   12005:                                 $extrainfo[] = $ret->getMessage();
                   12006:                                 if ($pkg->getPackageType() == 'extsrc' ||
                   12007:                                       $pkg->getPackageType() == 'extbin') {
                   12008:                                     $exttype = 'extension';
                   12009:                                 } else {
                   12010:                                     ob_start();
                   12011:                                     phpinfo(INFO_GENERAL);
                   12012:                                     $info = ob_get_contents();
                   12013:                                     ob_end_clean();
                   12014:                                     $debug = function_exists('leak') ? '_debug' : '';
                   12015:                                     $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   12016:                                     $exttype = 'zend_extension' . $debug . $ts;
                   12017:                                 }
                   12018:                                 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
                   12019:                                     $pinfo[1]['basename'] . '" from php.ini', $command);
                   12020:                             } else {
                   12021:                                 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
                   12022:                                     ' disabled in php.ini', $command);
                   12023:                             }
                   12024:                         }
                   12025:                     }
                   12026:                 }
                   12027:                 $savepkg = $pkg;
                   12028:                 if ($this->config->get('verbose') > 0) {
                   12029:                     if (is_object($pkg)) {
                   12030:                         $pkg = $reg->parsedPackageNameToString($pkg);
                   12031:                     }
                   12032:                     $this->ui->outputData("uninstall ok: $pkg", $command);
                   12033:                 }
                   12034:                 if (!isset($options['offline']) && is_object($savepkg) &&
                   12035:                       defined('PEAR_REMOTEINSTALL_OK')) {
                   12036:                     if ($this->config->isDefinedLayer('ftp')) {
                   12037:                         $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   12038:                         $info = $this->installer->ftpUninstall($savepkg);
                   12039:                         $this->installer->popErrorHandling();
                   12040:                         if (PEAR::isError($info)) {
                   12041:                             $this->ui->outputData($info->getMessage());
                   12042:                             $this->ui->outputData("remote uninstall failed: $pkg");
                   12043:                         } else {
                   12044:                             $this->ui->outputData("remote uninstall ok: $pkg");
                   12045:                         }
                   12046:                     }
                   12047:                 }
                   12048:             } else {
                   12049:                 $this->installer->popErrorHandling();
                   12050:                 if (!is_object($pkg)) {
                   12051:                     return $this->raiseError("uninstall failed: $pkg");
                   12052:                 }
                   12053:                 $pkg = $reg->parsedPackageNameToString($pkg);
                   12054:             }
                   12055:         }
                   12056: 
                   12057:         return true;
                   12058:     }
                   12059: 
                   12060:     // }}}
                   12061: 
                   12062: 
                   12063:     // }}}
                   12064:     // {{{ doBundle()
                   12065:     /*
                   12066:     (cox) It just downloads and untars the package, does not do
                   12067:             any check that the PEAR_Installer::_installFile() does.
                   12068:     */
                   12069: 
                   12070:     function doBundle($command, $options, $params)
                   12071:     {
                   12072:         $opts = array(
                   12073:             'force'        => true,
                   12074:             'nodeps'       => true,
                   12075:             'soft'         => true,
                   12076:             'downloadonly' => true
                   12077:         );
                   12078:         $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
                   12079:         $reg = &$this->config->getRegistry();
                   12080:         if (count($params) < 1) {
                   12081:             return $this->raiseError("Please supply the package you want to bundle");
                   12082:         }
                   12083: 
                   12084:         if (isset($options['destination'])) {
                   12085:             if (!is_dir($options['destination'])) {
                   12086:                 System::mkdir('-p ' . $options['destination']);
                   12087:             }
                   12088:             $dest = realpath($options['destination']);
                   12089:         } else {
                   12090:             $pwd  = getcwd();
                   12091:             $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
                   12092:             $dest = is_dir($dir) ? $dir : $pwd;
                   12093:         }
                   12094:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12095:         $err = $downloader->setDownloadDir($dest);
                   12096:         PEAR::staticPopErrorHandling();
                   12097:         if (PEAR::isError($err)) {
                   12098:             return PEAR::raiseError('download directory "' . $dest .
                   12099:                 '" is not writeable.');
                   12100:         }
                   12101:         $result = &$downloader->download(array($params[0]));
                   12102:         if (PEAR::isError($result)) {
                   12103:             return $result;
                   12104:         }
                   12105:         if (!isset($result[0])) {
                   12106:             return $this->raiseError('unable to unpack ' . $params[0]);
                   12107:         }
                   12108:         $pkgfile = &$result[0]->getPackageFile();
                   12109:         $pkgname = $pkgfile->getName();
                   12110:         $pkgversion = $pkgfile->getVersion();
                   12111: 
                   12112:         // Unpacking -------------------------------------------------
                   12113:         $dest .= DIRECTORY_SEPARATOR . $pkgname;
                   12114:         $orig = $pkgname . '-' . $pkgversion;
                   12115: 
                   12116:         $tar = &new Archive_Tar($pkgfile->getArchiveFile());
                   12117:         if (!$tar->extractModify($dest, $orig)) {
                   12118:             return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
                   12119:         }
                   12120:         $this->ui->outputData("Package ready at '$dest'");
                   12121:     // }}}
                   12122:     }
                   12123: 
                   12124:     // }}}
                   12125: 
                   12126:     function doRunScripts($command, $options, $params)
                   12127:     {
                   12128:         if (!isset($params[0])) {
                   12129:             return $this->raiseError('run-scripts expects 1 parameter: a package name');
                   12130:         }
                   12131: 
                   12132:         $reg = &$this->config->getRegistry();
                   12133:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12134:         $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   12135:         PEAR::staticPopErrorHandling();
                   12136:         if (PEAR::isError($parsed)) {
                   12137:             return $this->raiseError($parsed);
                   12138:         }
                   12139: 
                   12140:         $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
                   12141:         if (!is_object($package)) {
                   12142:             return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
                   12143:         }
                   12144: 
                   12145:         $package->setConfig($this->config);
                   12146:         $package->runPostinstallScripts();
                   12147:         $this->ui->outputData('Install scripts complete', $command);
                   12148:         return true;
                   12149:     }
                   12150: 
                   12151:     /**
                   12152:      * Given a list of packages, filter out those ones that are already up to date
                   12153:      *
                   12154:      * @param $packages: packages, in parsed array format !
                   12155:      * @return list of packages that can be upgraded
                   12156:      */
                   12157:     function _filterUptodatePackages($packages, $command)
                   12158:     {
                   12159:         $reg = &$this->config->getRegistry();
                   12160:         $latestReleases = array();
                   12161: 
                   12162:         $ret = array();
                   12163:         foreach ($packages as $package) {
                   12164:             if (isset($package['group'])) {
                   12165:                 $ret[] = $package;
                   12166:                 continue;
                   12167:             }
                   12168: 
                   12169:             $channel = $package['channel'];
                   12170:             $name    = $package['package'];
                   12171:             if (!$reg->packageExists($name, $channel)) {
                   12172:                 $ret[] = $package;
                   12173:                 continue;
                   12174:             }
                   12175: 
                   12176:             if (!isset($latestReleases[$channel])) {
                   12177:                 // fill in cache for this channel
                   12178:                 $chan = &$reg->getChannel($channel);
                   12179:                 if (PEAR::isError($chan)) {
                   12180:                     return $this->raiseError($chan);
                   12181:                 }
                   12182: 
                   12183:                 $base2 = false;
                   12184:                 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
                   12185:                 if ($chan->supportsREST($preferred_mirror) &&
                   12186:                     (
                   12187:                        //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                   12188:                        ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   12189:                     )
                   12190:                 ) {
                   12191:                     $dorest = true;
                   12192:                 }
                   12193: 
                   12194:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12195:                 if (!isset($package['state'])) {
                   12196:                     $state = $this->config->get('preferred_state', null, $channel);
                   12197:                 } else {
                   12198:                     $state = $package['state'];
                   12199:                 }
                   12200: 
                   12201:                 if ($dorest) {
                   12202:                     if ($base2) {
                   12203:                         $rest = &$this->config->getREST('1.4', array());
                   12204:                         $base = $base2;
                   12205:                     } else {
                   12206:                         $rest = &$this->config->getREST('1.0', array());
                   12207:                     }
                   12208: 
                   12209:                     $installed = array_flip($reg->listPackages($channel));
                   12210:                     $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
                   12211:                 }
                   12212: 
                   12213:                 PEAR::staticPopErrorHandling();
                   12214:                 if (PEAR::isError($latest)) {
                   12215:                     $this->ui->outputData('Error getting channel info from ' . $channel .
                   12216:                         ': ' . $latest->getMessage());
                   12217:                     continue;
                   12218:                 }
                   12219: 
                   12220:                 $latestReleases[$channel] = array_change_key_case($latest);
                   12221:             }
                   12222: 
                   12223:             // check package for latest release
                   12224:             $name_lower = strtolower($name);
                   12225:             if (isset($latestReleases[$channel][$name_lower])) {
                   12226:                 // if not set, up to date
                   12227:                 $inst_version    = $reg->packageInfo($name, 'version', $channel);
                   12228:                 $channel_version = $latestReleases[$channel][$name_lower]['version'];
                   12229:                 if (version_compare($channel_version, $inst_version, 'le')) {
                   12230:                     // installed version is up-to-date
                   12231:                     continue;
                   12232:                 }
                   12233: 
                   12234:                 // maintain BC
                   12235:                 if ($command == 'upgrade-all') {
                   12236:                     $this->ui->outputData(array('data' => 'Will upgrade ' .
                   12237:                         $reg->parsedPackageNameToString($package)), $command);
                   12238:                 }
                   12239:                 $ret[] = $package;
                   12240:             }
                   12241:         }
                   12242: 
                   12243:         return $ret;
                   12244:     }
                   12245: }PEAR-1.9.4/PEAR/Command/Mirror.xml0000644000076500000240000000115111605156760015335 0ustar  helgistaff<commands version="1.0">
                   12246:  <download-all>
                   12247:   <summary>Downloads each available package from the default channel</summary>
                   12248:   <function>doDownloadAll</function>
                   12249:   <shortcut>da</shortcut>
                   12250:   <options>
                   12251:    <channel>
                   12252:     <shortopt>c</shortopt>
                   12253:     <doc>specify a channel other than the default channel</doc>
                   12254:     <arg>CHAN</arg>
                   12255:    </channel>
                   12256:   </options>
                   12257:   <doc>
                   12258: Requests a list of available packages from the default channel ({config default_channel})
                   12259: and downloads them to current working directory.  Note: only
                   12260: packages within preferred_state ({config preferred_state}) will be downloaded</doc>
                   12261:  </download-all>
                   12262: </commands>PEAR-1.9.4/PEAR/Command/Mirror.php0000644000076500000240000001076211605156760015334 0ustar  helgistaff<?php
                   12263: /**
                   12264:  * PEAR_Command_Mirror (download-all command)
                   12265:  *
                   12266:  * PHP versions 4 and 5
                   12267:  *
                   12268:  * @category   pear
                   12269:  * @package    PEAR
                   12270:  * @author     Alexander Merz <alexmerz@php.net>
                   12271:  * @copyright  1997-2009 The Authors
                   12272:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12273:  * @version    CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
                   12274:  * @link       http://pear.php.net/package/PEAR
                   12275:  * @since      File available since Release 1.2.0
                   12276:  */
                   12277: 
                   12278: /**
                   12279:  * base class
                   12280:  */
                   12281: require_once 'PEAR/Command/Common.php';
                   12282: 
                   12283: /**
                   12284:  * PEAR commands for providing file mirrors
                   12285:  *
                   12286:  * @category   pear
                   12287:  * @package    PEAR
                   12288:  * @author     Alexander Merz <alexmerz@php.net>
                   12289:  * @copyright  1997-2009 The Authors
                   12290:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12291:  * @version    Release: 1.9.4
                   12292:  * @link       http://pear.php.net/package/PEAR
                   12293:  * @since      Class available since Release 1.2.0
                   12294:  */
                   12295: class PEAR_Command_Mirror extends PEAR_Command_Common
                   12296: {
                   12297:     var $commands = array(
                   12298:         'download-all' => array(
                   12299:             'summary' => 'Downloads each available package from the default channel',
                   12300:             'function' => 'doDownloadAll',
                   12301:             'shortcut' => 'da',
                   12302:             'options' => array(
                   12303:                 'channel' =>
                   12304:                     array(
                   12305:                     'shortopt' => 'c',
                   12306:                     'doc' => 'specify a channel other than the default channel',
                   12307:                     'arg' => 'CHAN',
                   12308:                     ),
                   12309:                 ),
                   12310:             'doc' => '
                   12311: Requests a list of available packages from the default channel ({config default_channel})
                   12312: and downloads them to current working directory.  Note: only
                   12313: packages within preferred_state ({config preferred_state}) will be downloaded'
                   12314:             ),
                   12315:         );
                   12316: 
                   12317:     /**
                   12318:      * PEAR_Command_Mirror constructor.
                   12319:      *
                   12320:      * @access public
                   12321:      * @param object PEAR_Frontend a reference to an frontend
                   12322:      * @param object PEAR_Config a reference to the configuration data
                   12323:      */
                   12324:     function PEAR_Command_Mirror(&$ui, &$config)
                   12325:     {
                   12326:         parent::PEAR_Command_Common($ui, $config);
                   12327:     }
                   12328: 
                   12329:     /**
                   12330:      * For unit-testing
                   12331:      */
                   12332:     function &factory($a)
                   12333:     {
                   12334:         $a = &PEAR_Command::factory($a, $this->config);
                   12335:         return $a;
                   12336:     }
                   12337: 
                   12338:     /**
                   12339:     * retrieves a list of avaible Packages from master server
                   12340:     * and downloads them
                   12341:     *
                   12342:     * @access public
                   12343:     * @param string $command the command
                   12344:     * @param array $options the command options before the command
                   12345:     * @param array $params the stuff after the command name
                   12346:     * @return bool true if succesful
                   12347:     * @throw PEAR_Error
                   12348:     */
                   12349:     function doDownloadAll($command, $options, $params)
                   12350:     {
                   12351:         $savechannel = $this->config->get('default_channel');
                   12352:         $reg = &$this->config->getRegistry();
                   12353:         $channel = isset($options['channel']) ? $options['channel'] :
                   12354:             $this->config->get('default_channel');
                   12355:         if (!$reg->channelExists($channel)) {
                   12356:             $this->config->set('default_channel', $savechannel);
                   12357:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   12358:         }
                   12359:         $this->config->set('default_channel', $channel);
                   12360: 
                   12361:         $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
                   12362:         $chan = $reg->getChannel($channel);
                   12363:         if (PEAR::isError($chan)) {
                   12364:             return $this->raiseError($chan);
                   12365:         }
                   12366: 
                   12367:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   12368:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   12369:             $rest = &$this->config->getREST('1.0', array());
                   12370:             $remoteInfo = array_flip($rest->listPackages($base, $channel));
                   12371:         }
                   12372: 
                   12373:         if (PEAR::isError($remoteInfo)) {
                   12374:             return $remoteInfo;
                   12375:         }
                   12376: 
                   12377:         $cmd = &$this->factory("download");
                   12378:         if (PEAR::isError($cmd)) {
                   12379:             return $cmd;
                   12380:         }
                   12381: 
                   12382:         $this->ui->outputData('Using Preferred State of ' .
                   12383:             $this->config->get('preferred_state'));
                   12384:         $this->ui->outputData('Gathering release information, please wait...');
                   12385: 
                   12386:         /**
                   12387:          * Error handling not necessary, because already done by
                   12388:          * the download command
                   12389:          */
                   12390:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12391:         $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
                   12392:         PEAR::staticPopErrorHandling();
                   12393:         $this->config->set('default_channel', $savechannel);
                   12394:         if (PEAR::isError($err)) {
                   12395:             $this->ui->outputData($err->getMessage());
                   12396:         }
                   12397: 
                   12398:         return true;
                   12399:     }
                   12400: }PEAR-1.9.4/PEAR/Command/Package.xml0000644000076500000240000001606611605156760015431 0ustar  helgistaff<commands version="1.0">
                   12401:  <package>
                   12402:   <summary>Build Package</summary>
                   12403:   <function>doPackage</function>
                   12404:   <shortcut>p</shortcut>
                   12405:   <options>
                   12406:    <nocompress>
                   12407:     <shortopt>Z</shortopt>
                   12408:     <doc>Do not gzip the package file</doc>
                   12409:    </nocompress>
                   12410:    <showname>
                   12411:     <shortopt>n</shortopt>
                   12412:     <doc>Print the name of the packaged file.</doc>
                   12413:    </showname>
                   12414:   </options>
                   12415:   <doc>[descfile] [descfile2]
                   12416: Creates a PEAR package from its description file (usually called
                   12417: package.xml).  If a second packagefile is passed in, then
                   12418: the packager will check to make sure that one is a package.xml
                   12419: version 1.0, and the other is a package.xml version 2.0.  The
                   12420: package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
                   12421: and the other as &quot;package2.xml&quot; in the archive&quot;
                   12422: </doc>
                   12423:  </package>
                   12424:  <package-validate>
                   12425:   <summary>Validate Package Consistency</summary>
                   12426:   <function>doPackageValidate</function>
                   12427:   <shortcut>pv</shortcut>
                   12428:   <options />
                   12429:   <doc>
                   12430: </doc>
                   12431:  </package-validate>
                   12432:  <cvsdiff>
                   12433:   <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
                   12434:   <function>doCvsDiff</function>
                   12435:   <shortcut>cd</shortcut>
                   12436:   <options>
                   12437:    <quiet>
                   12438:     <shortopt>q</shortopt>
                   12439:     <doc>Be quiet</doc>
                   12440:    </quiet>
                   12441:    <reallyquiet>
                   12442:     <shortopt>Q</shortopt>
                   12443:     <doc>Be really quiet</doc>
                   12444:    </reallyquiet>
                   12445:    <date>
                   12446:     <shortopt>D</shortopt>
                   12447:     <doc>Diff against revision of DATE</doc>
                   12448:     <arg>DATE</arg>
                   12449:    </date>
                   12450:    <release>
                   12451:     <shortopt>R</shortopt>
                   12452:     <doc>Diff against tag for package release REL</doc>
                   12453:     <arg>REL</arg>
                   12454:    </release>
                   12455:    <revision>
                   12456:     <shortopt>r</shortopt>
                   12457:     <doc>Diff against revision REV</doc>
                   12458:     <arg>REV</arg>
                   12459:    </revision>
                   12460:    <context>
                   12461:     <shortopt>c</shortopt>
                   12462:     <doc>Generate context diff</doc>
                   12463:    </context>
                   12464:    <unified>
                   12465:     <shortopt>u</shortopt>
                   12466:     <doc>Generate unified diff</doc>
                   12467:    </unified>
                   12468:    <ignore-case>
                   12469:     <shortopt>i</shortopt>
                   12470:     <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
                   12471:    </ignore-case>
                   12472:    <ignore-whitespace>
                   12473:     <shortopt>b</shortopt>
                   12474:     <doc>Ignore changes in amount of white space</doc>
                   12475:    </ignore-whitespace>
                   12476:    <ignore-blank-lines>
                   12477:     <shortopt>B</shortopt>
                   12478:     <doc>Ignore changes that insert or delete blank lines</doc>
                   12479:    </ignore-blank-lines>
                   12480:    <brief>
                   12481:     <shortopt></shortopt>
                   12482:     <doc>Report only whether the files differ, no details</doc>
                   12483:    </brief>
                   12484:    <dry-run>
                   12485:     <shortopt>n</shortopt>
                   12486:     <doc>Don&#039;t do anything, just pretend</doc>
                   12487:    </dry-run>
                   12488:   </options>
                   12489:   <doc>&lt;package.xml&gt;
                   12490: Compares all the files in a package.  Without any options, this
                   12491: command will compare the current code with the last checked-in code.
                   12492: Using the -r or -R option you may compare the current code with that
                   12493: of a specific release.
                   12494: </doc>
                   12495:  </cvsdiff>
                   12496:  <svntag>
                   12497:   <summary>Set SVN Release Tag</summary>
                   12498:   <function>doSvnTag</function>
                   12499:   <shortcut>sv</shortcut>
                   12500:   <options>
                   12501:    <quiet>
                   12502:     <shortopt>q</shortopt>
                   12503:     <doc>Be quiet</doc>
                   12504:    </quiet>
                   12505:    <slide>
                   12506:     <shortopt>F</shortopt>
                   12507:     <doc>Move (slide) tag if it exists</doc>
                   12508:    </slide>
                   12509:    <delete>
                   12510:     <shortopt>d</shortopt>
                   12511:     <doc>Remove tag</doc>
                   12512:    </delete>
                   12513:    <dry-run>
                   12514:     <shortopt>n</shortopt>
                   12515:     <doc>Don&#039;t do anything, just pretend</doc>
                   12516:    </dry-run>
                   12517:   </options>
                   12518:   <doc>&lt;package.xml&gt; [files...]
                   12519:  Sets a SVN tag on all files in a package.  Use this command after you have
                   12520:  packaged a distribution tarball with the &quot;package&quot; command to tag what
                   12521:  revisions of what files were in that release.  If need to fix something
                   12522:  after running svntag once, but before the tarball is released to the public,
                   12523:  use the &quot;slide&quot; option to move the release tag.
                   12524: 
                   12525:  to include files (such as a second package.xml, or tests not included in the
                   12526:  release), pass them as additional parameters.
                   12527:  </doc>
                   12528:  </svntag>
                   12529:  <cvstag>
                   12530:   <summary>Set CVS Release Tag</summary>
                   12531:   <function>doCvsTag</function>
                   12532:   <shortcut>ct</shortcut>
                   12533:   <options>
                   12534:    <quiet>
                   12535:     <shortopt>q</shortopt>
                   12536:     <doc>Be quiet</doc>
                   12537:    </quiet>
                   12538:    <reallyquiet>
                   12539:     <shortopt>Q</shortopt>
                   12540:     <doc>Be really quiet</doc>
                   12541:    </reallyquiet>
                   12542:    <slide>
                   12543:     <shortopt>F</shortopt>
                   12544:     <doc>Move (slide) tag if it exists</doc>
                   12545:    </slide>
                   12546:    <delete>
                   12547:     <shortopt>d</shortopt>
                   12548:     <doc>Remove tag</doc>
                   12549:    </delete>
                   12550:    <dry-run>
                   12551:     <shortopt>n</shortopt>
                   12552:     <doc>Don&#039;t do anything, just pretend</doc>
                   12553:    </dry-run>
                   12554:   </options>
                   12555:   <doc>&lt;package.xml&gt; [files...]
                   12556: Sets a CVS tag on all files in a package.  Use this command after you have
                   12557: packaged a distribution tarball with the &quot;package&quot; command to tag what
                   12558: revisions of what files were in that release.  If need to fix something
                   12559: after running cvstag once, but before the tarball is released to the public,
                   12560: use the &quot;slide&quot; option to move the release tag.
                   12561: 
                   12562: to include files (such as a second package.xml, or tests not included in the
                   12563: release), pass them as additional parameters.
                   12564: </doc>
                   12565:  </cvstag>
                   12566:  <package-dependencies>
                   12567:   <summary>Show package dependencies</summary>
                   12568:   <function>doPackageDependencies</function>
                   12569:   <shortcut>pd</shortcut>
                   12570:   <options />
                   12571:   <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
                   12572: List all dependencies the package has.
                   12573: Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
                   12574:  </package-dependencies>
                   12575:  <sign>
                   12576:   <summary>Sign a package distribution file</summary>
                   12577:   <function>doSign</function>
                   12578:   <shortcut>si</shortcut>
                   12579:   <options>
                   12580:    <verbose>
                   12581:     <shortopt>v</shortopt>
                   12582:     <doc>Display GnuPG output</doc>
                   12583:    </verbose>
                   12584:   </options>
                   12585:   <doc>&lt;package-file&gt;
                   12586: Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
                   12587:  </sign>
                   12588:  <makerpm>
                   12589:   <summary>Builds an RPM spec file from a PEAR package</summary>
                   12590:   <function>doMakeRPM</function>
                   12591:   <shortcut>rpm</shortcut>
                   12592:   <options>
                   12593:    <spec-template>
                   12594:     <shortopt>t</shortopt>
                   12595:     <doc>Use FILE as RPM spec file template</doc>
                   12596:     <arg>FILE</arg>
                   12597:    </spec-template>
                   12598:    <rpm-pkgname>
                   12599:     <shortopt>p</shortopt>
                   12600:     <doc>Use FORMAT as format string for RPM package name, %s is replaced
                   12601: by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
                   12602:     <arg>FORMAT</arg>
                   12603:    </rpm-pkgname>
                   12604:   </options>
                   12605:   <doc>&lt;package-file&gt;
                   12606: 
                   12607: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
                   12608: package.  Intended to be used from the SPECS directory, with the PEAR
                   12609: package tarball in the SOURCES directory:
                   12610: 
                   12611: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
                   12612: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
                   12613: $ rpm -bb PEAR::Net_Socket-1.0.spec
                   12614: ...
                   12615: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
                   12616: </doc>
                   12617:  </makerpm>
                   12618:  <convert>
                   12619:   <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
                   12620:   <function>doConvert</function>
                   12621:   <shortcut>c2</shortcut>
                   12622:   <options>
                   12623:    <flat>
                   12624:     <shortopt>f</shortopt>
                   12625:     <doc>do not beautify the filelist.</doc>
                   12626:    </flat>
                   12627:   </options>
                   12628:   <doc>[descfile] [descfile2]
                   12629: Converts a package.xml in 1.0 format into a package.xml
                   12630: in 2.0 format.  The new file will be named package2.xml by default,
                   12631: and package.xml will be used as the old file by default.
                   12632: This is not the most intelligent conversion, and should only be
                   12633: used for automated conversion or learning the format.
                   12634: </doc>
                   12635:  </convert>
                   12636: </commands>PEAR-1.9.4/PEAR/Command/Package.php0000644000076500000240000011652311605156760015417 0ustar  helgistaff<?php
                   12637: /**
                   12638:  * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
                   12639:  * sign, makerpm, convert commands)
                   12640:  *
                   12641:  * PHP versions 4 and 5
                   12642:  *
                   12643:  * @category   pear
                   12644:  * @package    PEAR
                   12645:  * @author     Stig Bakken <ssb@php.net>
                   12646:  * @author     Martin Jansen <mj@php.net>
                   12647:  * @author     Greg Beaver <cellog@php.net>
                   12648:  * @copyright  1997-2009 The Authors
                   12649:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12650:  * @version    CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
                   12651:  * @link       http://pear.php.net/package/PEAR
                   12652:  * @since      File available since Release 0.1
                   12653:  */
                   12654: 
                   12655: /**
                   12656:  * base class
                   12657:  */
                   12658: require_once 'PEAR/Command/Common.php';
                   12659: 
                   12660: /**
                   12661:  * PEAR commands for login/logout
                   12662:  *
                   12663:  * @category   pear
                   12664:  * @package    PEAR
                   12665:  * @author     Stig Bakken <ssb@php.net>
                   12666:  * @author     Martin Jansen <mj@php.net>
                   12667:  * @author     Greg Beaver <cellog@php.net>
                   12668:  * @copyright  1997-2009 The Authors
                   12669:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12670:  * @version    Release: @package_version@
                   12671:  * @link       http://pear.php.net/package/PEAR
                   12672:  * @since      Class available since Release 0.1
                   12673:  */
                   12674: 
                   12675: class PEAR_Command_Package extends PEAR_Command_Common
                   12676: {
                   12677:     var $commands = array(
                   12678:         'package' => array(
                   12679:             'summary' => 'Build Package',
                   12680:             'function' => 'doPackage',
                   12681:             'shortcut' => 'p',
                   12682:             'options' => array(
                   12683:                 'nocompress' => array(
                   12684:                     'shortopt' => 'Z',
                   12685:                     'doc' => 'Do not gzip the package file'
                   12686:                     ),
                   12687:                 'showname' => array(
                   12688:                     'shortopt' => 'n',
                   12689:                     'doc' => 'Print the name of the packaged file.',
                   12690:                     ),
                   12691:                 ),
                   12692:             'doc' => '[descfile] [descfile2]
                   12693: Creates a PEAR package from its description file (usually called
                   12694: package.xml).  If a second packagefile is passed in, then
                   12695: the packager will check to make sure that one is a package.xml
                   12696: version 1.0, and the other is a package.xml version 2.0.  The
                   12697: package.xml version 1.0 will be saved as "package.xml" in the archive,
                   12698: and the other as "package2.xml" in the archive"
                   12699: '
                   12700:             ),
                   12701:         'package-validate' => array(
                   12702:             'summary' => 'Validate Package Consistency',
                   12703:             'function' => 'doPackageValidate',
                   12704:             'shortcut' => 'pv',
                   12705:             'options' => array(),
                   12706:             'doc' => '
                   12707: ',
                   12708:             ),
                   12709:         'cvsdiff' => array(
                   12710:             'summary' => 'Run a "cvs diff" for all files in a package',
                   12711:             'function' => 'doCvsDiff',
                   12712:             'shortcut' => 'cd',
                   12713:             'options' => array(
                   12714:                 'quiet' => array(
                   12715:                     'shortopt' => 'q',
                   12716:                     'doc' => 'Be quiet',
                   12717:                     ),
                   12718:                 'reallyquiet' => array(
                   12719:                     'shortopt' => 'Q',
                   12720:                     'doc' => 'Be really quiet',
                   12721:                     ),
                   12722:                 'date' => array(
                   12723:                     'shortopt' => 'D',
                   12724:                     'doc' => 'Diff against revision of DATE',
                   12725:                     'arg' => 'DATE',
                   12726:                     ),
                   12727:                 'release' => array(
                   12728:                     'shortopt' => 'R',
                   12729:                     'doc' => 'Diff against tag for package release REL',
                   12730:                     'arg' => 'REL',
                   12731:                     ),
                   12732:                 'revision' => array(
                   12733:                     'shortopt' => 'r',
                   12734:                     'doc' => 'Diff against revision REV',
                   12735:                     'arg' => 'REV',
                   12736:                     ),
                   12737:                 'context' => array(
                   12738:                     'shortopt' => 'c',
                   12739:                     'doc' => 'Generate context diff',
                   12740:                     ),
                   12741:                 'unified' => array(
                   12742:                     'shortopt' => 'u',
                   12743:                     'doc' => 'Generate unified diff',
                   12744:                     ),
                   12745:                 'ignore-case' => array(
                   12746:                     'shortopt' => 'i',
                   12747:                     'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
                   12748:                     ),
                   12749:                 'ignore-whitespace' => array(
                   12750:                     'shortopt' => 'b',
                   12751:                     'doc' => 'Ignore changes in amount of white space',
                   12752:                     ),
                   12753:                 'ignore-blank-lines' => array(
                   12754:                     'shortopt' => 'B',
                   12755:                     'doc' => 'Ignore changes that insert or delete blank lines',
                   12756:                     ),
                   12757:                 'brief' => array(
                   12758:                     'doc' => 'Report only whether the files differ, no details',
                   12759:                     ),
                   12760:                 'dry-run' => array(
                   12761:                     'shortopt' => 'n',
                   12762:                     'doc' => 'Don\'t do anything, just pretend',
                   12763:                     ),
                   12764:                 ),
                   12765:             'doc' => '<package.xml>
                   12766: Compares all the files in a package.  Without any options, this
                   12767: command will compare the current code with the last checked-in code.
                   12768: Using the -r or -R option you may compare the current code with that
                   12769: of a specific release.
                   12770: ',
                   12771:             ),
                   12772:          'svntag' => array(
                   12773:              'summary' => 'Set SVN Release Tag',
                   12774:              'function' => 'doSvnTag',
                   12775:              'shortcut' => 'sv',
                   12776:              'options' => array(
                   12777:                  'quiet' => array(
                   12778:                      'shortopt' => 'q',
                   12779:                      'doc' => 'Be quiet',
                   12780:                      ),
                   12781:                  'slide' => array(
                   12782:                      'shortopt' => 'F',
                   12783:                      'doc' => 'Move (slide) tag if it exists',
                   12784:                      ),
                   12785:                  'delete' => array(
                   12786:                      'shortopt' => 'd',
                   12787:                      'doc' => 'Remove tag',
                   12788:                      ),
                   12789:                  'dry-run' => array(
                   12790:                      'shortopt' => 'n',
                   12791:                      'doc' => 'Don\'t do anything, just pretend',
                   12792:                      ),
                   12793:                  ),
                   12794:              'doc' => '<package.xml> [files...]
                   12795:  Sets a SVN tag on all files in a package.  Use this command after you have
                   12796:  packaged a distribution tarball with the "package" command to tag what
                   12797:  revisions of what files were in that release.  If need to fix something
                   12798:  after running svntag once, but before the tarball is released to the public,
                   12799:  use the "slide" option to move the release tag.
                   12800: 
                   12801:  to include files (such as a second package.xml, or tests not included in the
                   12802:  release), pass them as additional parameters.
                   12803:  ',
                   12804:              ),
                   12805:         'cvstag' => array(
                   12806:             'summary' => 'Set CVS Release Tag',
                   12807:             'function' => 'doCvsTag',
                   12808:             'shortcut' => 'ct',
                   12809:             'options' => array(
                   12810:                 'quiet' => array(
                   12811:                     'shortopt' => 'q',
                   12812:                     'doc' => 'Be quiet',
                   12813:                     ),
                   12814:                 'reallyquiet' => array(
                   12815:                     'shortopt' => 'Q',
                   12816:                     'doc' => 'Be really quiet',
                   12817:                     ),
                   12818:                 'slide' => array(
                   12819:                     'shortopt' => 'F',
                   12820:                     'doc' => 'Move (slide) tag if it exists',
                   12821:                     ),
                   12822:                 'delete' => array(
                   12823:                     'shortopt' => 'd',
                   12824:                     'doc' => 'Remove tag',
                   12825:                     ),
                   12826:                 'dry-run' => array(
                   12827:                     'shortopt' => 'n',
                   12828:                     'doc' => 'Don\'t do anything, just pretend',
                   12829:                     ),
                   12830:                 ),
                   12831:             'doc' => '<package.xml> [files...]
                   12832: Sets a CVS tag on all files in a package.  Use this command after you have
                   12833: packaged a distribution tarball with the "package" command to tag what
                   12834: revisions of what files were in that release.  If need to fix something
                   12835: after running cvstag once, but before the tarball is released to the public,
                   12836: use the "slide" option to move the release tag.
                   12837: 
                   12838: to include files (such as a second package.xml, or tests not included in the
                   12839: release), pass them as additional parameters.
                   12840: ',
                   12841:             ),
                   12842:         'package-dependencies' => array(
                   12843:             'summary' => 'Show package dependencies',
                   12844:             'function' => 'doPackageDependencies',
                   12845:             'shortcut' => 'pd',
                   12846:             'options' => array(),
                   12847:             'doc' => '<package-file> or <package.xml> or <install-package-name>
                   12848: List all dependencies the package has.
                   12849: Can take a tgz / tar file, package.xml or a package name of an installed package.'
                   12850:             ),
                   12851:         'sign' => array(
                   12852:             'summary' => 'Sign a package distribution file',
                   12853:             'function' => 'doSign',
                   12854:             'shortcut' => 'si',
                   12855:             'options' => array(
                   12856:                 'verbose' => array(
                   12857:                     'shortopt' => 'v',
                   12858:                     'doc' => 'Display GnuPG output',
                   12859:                     ),
                   12860:             ),
                   12861:             'doc' => '<package-file>
                   12862: Signs a package distribution (.tar or .tgz) file with GnuPG.',
                   12863:             ),
                   12864:         'makerpm' => array(
                   12865:             'summary' => 'Builds an RPM spec file from a PEAR package',
                   12866:             'function' => 'doMakeRPM',
                   12867:             'shortcut' => 'rpm',
                   12868:             'options' => array(
                   12869:                 'spec-template' => array(
                   12870:                     'shortopt' => 't',
                   12871:                     'arg' => 'FILE',
                   12872:                     'doc' => 'Use FILE as RPM spec file template'
                   12873:                     ),
                   12874:                 'rpm-pkgname' => array(
                   12875:                     'shortopt' => 'p',
                   12876:                     'arg' => 'FORMAT',
                   12877:                     'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
                   12878: by the PEAR package name, defaults to "PEAR::%s".',
                   12879:                     ),
                   12880:                 ),
                   12881:             'doc' => '<package-file>
                   12882: 
                   12883: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
                   12884: package.  Intended to be used from the SPECS directory, with the PEAR
                   12885: package tarball in the SOURCES directory:
                   12886: 
                   12887: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
                   12888: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
                   12889: $ rpm -bb PEAR::Net_Socket-1.0.spec
                   12890: ...
                   12891: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
                   12892: ',
                   12893:             ),
                   12894:         'convert' => array(
                   12895:             'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
                   12896:             'function' => 'doConvert',
                   12897:             'shortcut' => 'c2',
                   12898:             'options' => array(
                   12899:                 'flat' => array(
                   12900:                     'shortopt' => 'f',
                   12901:                     'doc' => 'do not beautify the filelist.',
                   12902:                     ),
                   12903:                 ),
                   12904:             'doc' => '[descfile] [descfile2]
                   12905: Converts a package.xml in 1.0 format into a package.xml
                   12906: in 2.0 format.  The new file will be named package2.xml by default,
                   12907: and package.xml will be used as the old file by default.
                   12908: This is not the most intelligent conversion, and should only be
                   12909: used for automated conversion or learning the format.
                   12910: '
                   12911:             ),
                   12912:         );
                   12913: 
                   12914:     var $output;
                   12915: 
                   12916:     /**
                   12917:      * PEAR_Command_Package constructor.
                   12918:      *
                   12919:      * @access public
                   12920:      */
                   12921:     function PEAR_Command_Package(&$ui, &$config)
                   12922:     {
                   12923:         parent::PEAR_Command_Common($ui, $config);
                   12924:     }
                   12925: 
                   12926:     function _displayValidationResults($err, $warn, $strict = false)
                   12927:     {
                   12928:         foreach ($err as $e) {
                   12929:             $this->output .= "Error: $e\n";
                   12930:         }
                   12931:         foreach ($warn as $w) {
                   12932:             $this->output .= "Warning: $w\n";
                   12933:         }
                   12934:         $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
                   12935:                                        sizeof($err), sizeof($warn));
                   12936:         if ($strict && count($err) > 0) {
                   12937:             $this->output .= "Fix these errors and try again.";
                   12938:             return false;
                   12939:         }
                   12940:         return true;
                   12941:     }
                   12942: 
                   12943:     function &getPackager()
                   12944:     {
                   12945:         if (!class_exists('PEAR_Packager')) {
                   12946:             require_once 'PEAR/Packager.php';
                   12947:         }
                   12948:         $a = &new PEAR_Packager;
                   12949:         return $a;
                   12950:     }
                   12951: 
                   12952:     function &getPackageFile($config, $debug = false)
                   12953:     {
                   12954:         if (!class_exists('PEAR_Common')) {
                   12955:             require_once 'PEAR/Common.php';
                   12956:         }
                   12957:         if (!class_exists('PEAR_PackageFile')) {
                   12958:             require_once 'PEAR/PackageFile.php';
                   12959:         }
                   12960:         $a = &new PEAR_PackageFile($config, $debug);
                   12961:         $common = new PEAR_Common;
                   12962:         $common->ui = $this->ui;
                   12963:         $a->setLogger($common);
                   12964:         return $a;
                   12965:     }
                   12966: 
                   12967:     function doPackage($command, $options, $params)
                   12968:     {
                   12969:         $this->output = '';
                   12970:         $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
                   12971:         $pkg2 = isset($params[1]) ? $params[1] : null;
                   12972:         if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
                   12973:             $pkg2 = 'package2.xml';
                   12974:         }
                   12975: 
                   12976:         $packager = &$this->getPackager();
                   12977:         $compress = empty($options['nocompress']) ? true : false;
                   12978:         $result   = $packager->package($pkginfofile, $compress, $pkg2);
                   12979:         if (PEAR::isError($result)) {
                   12980:             return $this->raiseError($result);
                   12981:         }
                   12982: 
                   12983:         // Don't want output, only the package file name just created
                   12984:         if (isset($options['showname'])) {
                   12985:             $this->output = $result;
                   12986:         }
                   12987: 
                   12988:         if ($this->output) {
                   12989:             $this->ui->outputData($this->output, $command);
                   12990:         }
                   12991: 
                   12992:         return true;
                   12993:     }
                   12994: 
                   12995:     function doPackageValidate($command, $options, $params)
                   12996:     {
                   12997:         $this->output = '';
                   12998:         if (count($params) < 1) {
                   12999:             $params[0] = 'package.xml';
                   13000:         }
                   13001: 
                   13002:         $obj = &$this->getPackageFile($this->config, $this->_debug);
                   13003:         $obj->rawReturn();
                   13004:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   13005:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
                   13006:         if (PEAR::isError($info)) {
                   13007:             $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
                   13008:         } else {
                   13009:             $archive = $info->getArchiveFile();
                   13010:             $tar = &new Archive_Tar($archive);
                   13011:             $tar->extract(dirname($info->getPackageFile()));
                   13012:             $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
                   13013:                 $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
                   13014:                 basename($info->getPackageFile()));
                   13015:         }
                   13016: 
                   13017:         PEAR::staticPopErrorHandling();
                   13018:         if (PEAR::isError($info)) {
                   13019:             return $this->raiseError($info);
                   13020:         }
                   13021: 
                   13022:         $valid = false;
                   13023:         if ($info->getPackagexmlVersion() == '2.0') {
                   13024:             if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
                   13025:                 $info->flattenFileList();
                   13026:                 $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
                   13027:             }
                   13028:         } else {
                   13029:             $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
                   13030:         }
                   13031: 
                   13032:         $err = $warn = array();
                   13033:         if ($errors = $info->getValidationWarnings()) {
                   13034:             foreach ($errors as $error) {
                   13035:                 if ($error['level'] == 'warning') {
                   13036:                     $warn[] = $error['message'];
                   13037:                 } else {
                   13038:                     $err[] = $error['message'];
                   13039:                 }
                   13040:             }
                   13041:         }
                   13042: 
                   13043:         $this->_displayValidationResults($err, $warn);
                   13044:         $this->ui->outputData($this->output, $command);
                   13045:         return true;
                   13046:     }
                   13047: 
                   13048:     function doSvnTag($command, $options, $params)
                   13049:     {
                   13050:         $this->output = '';
                   13051:         $_cmd = $command;
                   13052:         if (count($params) < 1) {
                   13053:             $help = $this->getHelp($command);
                   13054:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13055:         }
                   13056: 
                   13057:         $packageFile = realpath($params[0]);
                   13058:         $dir = dirname($packageFile);
                   13059:         $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
                   13060:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13061:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
                   13062:         if (PEAR::isError($info)) {
                   13063:             return $this->raiseError($info);
                   13064:         }
                   13065: 
                   13066:         $err = $warn = array();
                   13067:         if (!$info->validate()) {
                   13068:             foreach ($info->getValidationWarnings() as $error) {
                   13069:                 if ($error['level'] == 'warning') {
                   13070:                     $warn[] = $error['message'];
                   13071:                 } else {
                   13072:                     $err[] = $error['message'];
                   13073:                 }
                   13074:             }
                   13075:         }
                   13076: 
                   13077:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13078:             $this->ui->outputData($this->output, $command);
                   13079:             return $this->raiseError('SVN tag failed');
                   13080:         }
                   13081: 
                   13082:         $version    = $info->getVersion();
                   13083:         $package    = $info->getName();
                   13084:         $svntag     = "$package-$version";
                   13085: 
                   13086:         if (isset($options['delete'])) {
                   13087:             return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
                   13088:         }
                   13089: 
                   13090:         $path = $this->_svnFindPath($packageFile);
                   13091: 
                   13092:         // Check if there are any modified files
                   13093:         $fp = popen('svn st --xml ' . dirname($packageFile), "r");
                   13094:         $out = '';
                   13095:         while ($line = fgets($fp, 1024)) {
                   13096:             $out .= rtrim($line)."\n";
                   13097:         }
                   13098:         pclose($fp);
                   13099: 
                   13100:         if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
                   13101:             $params = array(array(
                   13102:                 'name' => 'modified',
                   13103:                 'type' => 'yesno',
                   13104:                 'default' => 'no',
                   13105:                 'prompt' => 'You have files in your SVN checkout (' . $path['from']  . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
                   13106:             ));
                   13107:             $answers = $this->ui->confirmDialog($params);
                   13108: 
                   13109:             if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
                   13110:                 return true;
                   13111:             }
                   13112:         }
                   13113: 
                   13114:         if (isset($options['slide'])) {
                   13115:             $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
                   13116:         }
                   13117: 
                   13118:         // Check if tag already exists
                   13119:         $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
                   13120:         $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
                   13121: 
                   13122:         $fp = popen($existsCommand, "r");
                   13123:         $out = '';
                   13124:         while ($line = fgets($fp, 1024)) {
                   13125:             $out .= rtrim($line)."\n";
                   13126:         }
                   13127:         pclose($fp);
                   13128: 
                   13129:         if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
                   13130:             $this->ui->outputData($this->output, $command);
                   13131:             return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
                   13132:         } elseif (file_exists($path['local']['base'] . 'tags') === false) {
                   13133:             return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
                   13134:         } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
                   13135:             return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
                   13136:         } else {
                   13137:             $makeCommand = 'svn mkdir ' . $releaseTag;
                   13138:             $this->output .= "+ $makeCommand\n";
                   13139:             if (empty($options['dry-run'])) {
                   13140:                 // We need to create the tag dir.
                   13141:                 $fp = popen($makeCommand, "r");
                   13142:                 $out = '';
                   13143:                 while ($line = fgets($fp, 1024)) {
                   13144:                     $out .= rtrim($line)."\n";
                   13145:                 }
                   13146:                 pclose($fp);
                   13147:                 $this->output .= "$out\n";
                   13148:             }
                   13149:         }
                   13150: 
                   13151:         $command = 'svn';
                   13152:         if (isset($options['quiet'])) {
                   13153:             $command .= ' -q';
                   13154:         }
                   13155: 
                   13156:         $command .= ' copy --parents ';
                   13157: 
                   13158:         $dir   = dirname($packageFile);
                   13159:         $dir   = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
                   13160:         $files = array_keys($info->getFilelist());
                   13161:         if (!in_array(basename($packageFile), $files)) {
                   13162:             $files[] = basename($packageFile);
                   13163:         }
                   13164: 
                   13165:         array_shift($params);
                   13166:         if (count($params)) {
                   13167:             // add in additional files to be tagged (package files and such)
                   13168:             $files = array_merge($files, $params);
                   13169:         }
                   13170: 
                   13171:         $commands = array();
                   13172:         foreach ($files as $file) {
                   13173:             if (!file_exists($file)) {
                   13174:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
                   13175:             }
                   13176:             $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
                   13177:                           escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
                   13178:         }
                   13179: 
                   13180:         $this->output .= implode("\n", $commands) . "\n";
                   13181:         if (empty($options['dry-run'])) {
                   13182:             foreach ($commands as $command) {
                   13183:                 $fp = popen($command, "r");
                   13184:                 while ($line = fgets($fp, 1024)) {
                   13185:                     $this->output .= rtrim($line)."\n";
                   13186:                 }
                   13187:                 pclose($fp);
                   13188:             }
                   13189:         }
                   13190: 
                   13191:         $command = 'svn ci -m "Tagging the ' . $version  . ' release" ' . $releaseTag . "\n";
                   13192:         $this->output .= "+ $command\n";
                   13193:         if (empty($options['dry-run'])) {
                   13194:             $fp = popen($command, "r");
                   13195:             while ($line = fgets($fp, 1024)) {
                   13196:                 $this->output .= rtrim($line)."\n";
                   13197:             }
                   13198:             pclose($fp);
                   13199:         }
                   13200: 
                   13201:         $this->ui->outputData($this->output, $_cmd);
                   13202:         return true;
                   13203:     }
                   13204: 
                   13205:     function _svnFindPath($file)
                   13206:     {
                   13207:         $xml = '';
                   13208:         $command = "svn info --xml $file";
                   13209:         $fp = popen($command, "r");
                   13210:         while ($line = fgets($fp, 1024)) {
                   13211:             $xml .= rtrim($line)."\n";
                   13212:         }
                   13213:         pclose($fp);
                   13214:         $url_tag = strpos($xml, '<url>');
                   13215:         $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
                   13216: 
                   13217:         $path = array();
                   13218:         $path['from'] = substr($url, 0, strrpos($url, '/'));
                   13219:         $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
                   13220: 
                   13221:         // Figure out the local paths - see http://pear.php.net/bugs/17463
                   13222:         $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
                   13223:         if ($pos === false) {
                   13224:             $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
                   13225:         }
                   13226:         $path['local']['base'] = substr($file, 0, $pos + 1);
                   13227: 
                   13228:         return $path;
                   13229:     }
                   13230: 
                   13231:     function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
                   13232:     {
                   13233:         $command = 'svn';
                   13234: 
                   13235:         if (isset($options['quiet'])) {
                   13236:             $command .= ' -q';
                   13237:         }
                   13238: 
                   13239:         $command .= ' remove';
                   13240:         $command .= ' -m "Removing tag for the ' . $version  . ' release."';
                   13241: 
                   13242:         $path = $this->_svnFindPath($packageFile);
                   13243:         $command .= ' ' . $path['base'] . 'tags/' . $tag;
                   13244: 
                   13245: 
                   13246:         if ($this->config->get('verbose') > 1) {
                   13247:             $this->output .= "+ $command\n";
                   13248:         }
                   13249: 
                   13250:         $this->output .= "+ $command\n";
                   13251:         if (empty($options['dry-run'])) {
                   13252:             $fp = popen($command, "r");
                   13253:             while ($line = fgets($fp, 1024)) {
                   13254:                 $this->output .= rtrim($line)."\n";
                   13255:             }
                   13256:             pclose($fp);
                   13257:         }
                   13258: 
                   13259:         $this->ui->outputData($this->output, $command);
                   13260:         return true;
                   13261:     }
                   13262: 
                   13263:     function doCvsTag($command, $options, $params)
                   13264:     {
                   13265:         $this->output = '';
                   13266:         $_cmd = $command;
                   13267:         if (count($params) < 1) {
                   13268:             $help = $this->getHelp($command);
                   13269:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13270:         }
                   13271: 
                   13272:         $packageFile = realpath($params[0]);
                   13273:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13274:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
                   13275:         if (PEAR::isError($info)) {
                   13276:             return $this->raiseError($info);
                   13277:         }
                   13278: 
                   13279:         $err = $warn = array();
                   13280:         if (!$info->validate()) {
                   13281:             foreach ($info->getValidationWarnings() as $error) {
                   13282:                 if ($error['level'] == 'warning') {
                   13283:                     $warn[] = $error['message'];
                   13284:                 } else {
                   13285:                     $err[] = $error['message'];
                   13286:                 }
                   13287:             }
                   13288:         }
                   13289: 
                   13290:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13291:             $this->ui->outputData($this->output, $command);
                   13292:             return $this->raiseError('CVS tag failed');
                   13293:         }
                   13294: 
                   13295:         $version    = $info->getVersion();
                   13296:         $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
                   13297:         $cvstag     = "RELEASE_$cvsversion";
                   13298:         $files      = array_keys($info->getFilelist());
                   13299:         $command = 'cvs';
                   13300:         if (isset($options['quiet'])) {
                   13301:             $command .= ' -q';
                   13302:         }
                   13303: 
                   13304:         if (isset($options['reallyquiet'])) {
                   13305:             $command .= ' -Q';
                   13306:         }
                   13307: 
                   13308:         $command .= ' tag';
                   13309:         if (isset($options['slide'])) {
                   13310:             $command .= ' -F';
                   13311:         }
                   13312: 
                   13313:         if (isset($options['delete'])) {
                   13314:             $command .= ' -d';
                   13315:         }
                   13316: 
                   13317:         $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
                   13318:         array_shift($params);
                   13319:         if (count($params)) {
                   13320:             // add in additional files to be tagged
                   13321:             $files = array_merge($files, $params);
                   13322:         }
                   13323: 
                   13324:         $dir = dirname($packageFile);
                   13325:         $dir = substr($dir, strrpos($dir, '/') + 1);
                   13326:         foreach ($files as $file) {
                   13327:             if (!file_exists($file)) {
                   13328:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
                   13329:             }
                   13330:             $command .= ' ' . escapeshellarg($file);
                   13331:         }
                   13332: 
                   13333:         if ($this->config->get('verbose') > 1) {
                   13334:             $this->output .= "+ $command\n";
                   13335:         }
                   13336: 
                   13337:         $this->output .= "+ $command\n";
                   13338:         if (empty($options['dry-run'])) {
                   13339:             $fp = popen($command, "r");
                   13340:             while ($line = fgets($fp, 1024)) {
                   13341:                 $this->output .= rtrim($line)."\n";
                   13342:             }
                   13343:             pclose($fp);
                   13344:         }
                   13345: 
                   13346:         $this->ui->outputData($this->output, $_cmd);
                   13347:         return true;
                   13348:     }
                   13349: 
                   13350:     function doCvsDiff($command, $options, $params)
                   13351:     {
                   13352:         $this->output = '';
                   13353:         if (sizeof($params) < 1) {
                   13354:             $help = $this->getHelp($command);
                   13355:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13356:         }
                   13357: 
                   13358:         $file = realpath($params[0]);
                   13359:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13360:         $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
                   13361:         if (PEAR::isError($info)) {
                   13362:             return $this->raiseError($info);
                   13363:         }
                   13364: 
                   13365:         $err = $warn = array();
                   13366:         if (!$info->validate()) {
                   13367:             foreach ($info->getValidationWarnings() as $error) {
                   13368:                 if ($error['level'] == 'warning') {
                   13369:                     $warn[] = $error['message'];
                   13370:                 } else {
                   13371:                     $err[] = $error['message'];
                   13372:                 }
                   13373:             }
                   13374:         }
                   13375: 
                   13376:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13377:             $this->ui->outputData($this->output, $command);
                   13378:             return $this->raiseError('CVS diff failed');
                   13379:         }
                   13380: 
                   13381:         $info1 = $info->getFilelist();
                   13382:         $files = $info1;
                   13383:         $cmd = "cvs";
                   13384:         if (isset($options['quiet'])) {
                   13385:             $cmd .= ' -q';
                   13386:             unset($options['quiet']);
                   13387:         }
                   13388: 
                   13389:         if (isset($options['reallyquiet'])) {
                   13390:             $cmd .= ' -Q';
                   13391:             unset($options['reallyquiet']);
                   13392:         }
                   13393: 
                   13394:         if (isset($options['release'])) {
                   13395:             $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
                   13396:             $cvstag = "RELEASE_$cvsversion";
                   13397:             $options['revision'] = $cvstag;
                   13398:             unset($options['release']);
                   13399:         }
                   13400: 
                   13401:         $execute = true;
                   13402:         if (isset($options['dry-run'])) {
                   13403:             $execute = false;
                   13404:             unset($options['dry-run']);
                   13405:         }
                   13406: 
                   13407:         $cmd .= ' diff';
                   13408:         // the rest of the options are passed right on to "cvs diff"
                   13409:         foreach ($options as $option => $optarg) {
                   13410:             $arg = $short = false;
                   13411:             if (isset($this->commands[$command]['options'][$option])) {
                   13412:                 $arg = $this->commands[$command]['options'][$option]['arg'];
                   13413:                 $short = $this->commands[$command]['options'][$option]['shortopt'];
                   13414:             }
                   13415:             $cmd .= $short ? " -$short" : " --$option";
                   13416:             if ($arg && $optarg) {
                   13417:                 $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
                   13418:             }
                   13419:         }
                   13420: 
                   13421:         foreach ($files as $file) {
                   13422:             $cmd .= ' ' . escapeshellarg($file['name']);
                   13423:         }
                   13424: 
                   13425:         if ($this->config->get('verbose') > 1) {
                   13426:             $this->output .= "+ $cmd\n";
                   13427:         }
                   13428: 
                   13429:         if ($execute) {
                   13430:             $fp = popen($cmd, "r");
                   13431:             while ($line = fgets($fp, 1024)) {
                   13432:                 $this->output .= rtrim($line)."\n";
                   13433:             }
                   13434:             pclose($fp);
                   13435:         }
                   13436: 
                   13437:         $this->ui->outputData($this->output, $command);
                   13438:         return true;
                   13439:     }
                   13440: 
                   13441:     function doPackageDependencies($command, $options, $params)
                   13442:     {
                   13443:         // $params[0] -> the PEAR package to list its information
                   13444:         if (count($params) !== 1) {
                   13445:             return $this->raiseError("bad parameter(s), try \"help $command\"");
                   13446:         }
                   13447: 
                   13448:         $obj = &$this->getPackageFile($this->config, $this->_debug);
                   13449:         if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
                   13450:            $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   13451:         } else {
                   13452:             $reg  = $this->config->getRegistry();
                   13453:             $info = $obj->fromArray($reg->packageInfo($params[0]));
                   13454:         }
                   13455: 
                   13456:         if (PEAR::isError($info)) {
                   13457:             return $this->raiseError($info);
                   13458:         }
                   13459: 
                   13460:         $deps = $info->getDeps();
                   13461:         if (is_array($deps)) {
                   13462:             if ($info->getPackagexmlVersion() == '1.0') {
                   13463:                 $data = array(
                   13464:                     'caption' => 'Dependencies for pear/' . $info->getPackage(),
                   13465:                     'border' => true,
                   13466:                     'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
                   13467:                     );
                   13468: 
                   13469:                 foreach ($deps as $d) {
                   13470:                     if (isset($d['optional'])) {
                   13471:                         if ($d['optional'] == 'yes') {
                   13472:                             $req = 'No';
                   13473:                         } else {
                   13474:                             $req = 'Yes';
                   13475:                         }
                   13476:                     } else {
                   13477:                         $req = 'Yes';
                   13478:                     }
                   13479: 
                   13480:                     if (isset($this->_deps_rel_trans[$d['rel']])) {
                   13481:                         $rel = $this->_deps_rel_trans[$d['rel']];
                   13482:                     } else {
                   13483:                         $rel = $d['rel'];
                   13484:                     }
                   13485: 
                   13486:                     if (isset($this->_deps_type_trans[$d['type']])) {
                   13487:                         $type = ucfirst($this->_deps_type_trans[$d['type']]);
                   13488:                     } else {
                   13489:                         $type = $d['type'];
                   13490:                     }
                   13491: 
                   13492:                     if (isset($d['name'])) {
                   13493:                         $name = $d['name'];
                   13494:                     } else {
                   13495:                         $name = '';
                   13496:                     }
                   13497: 
                   13498:                     if (isset($d['version'])) {
                   13499:                         $version = $d['version'];
                   13500:                     } else {
                   13501:                         $version = '';
                   13502:                     }
                   13503: 
                   13504:                     $data['data'][] = array($req, $type, $name, $rel, $version);
                   13505:                 }
                   13506:             } else { // package.xml 2.0 dependencies display
                   13507:                 require_once 'PEAR/Dependency2.php';
                   13508:                 $deps = $info->getDependencies();
                   13509:                 $reg = &$this->config->getRegistry();
                   13510:                 if (is_array($deps)) {
                   13511:                     $d = new PEAR_Dependency2($this->config, array(), '');
                   13512:                     $data = array(
                   13513:                         'caption' => 'Dependencies for ' . $info->getPackage(),
                   13514:                         'border' => true,
                   13515:                         'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
                   13516:                         );
                   13517:                     foreach ($deps as $type => $subd) {
                   13518:                         $req = ($type == 'required') ? 'Yes' : 'No';
                   13519:                         if ($type == 'group') {
                   13520:                             $group = $subd['attribs']['name'];
                   13521:                         } else {
                   13522:                             $group = '';
                   13523:                         }
                   13524: 
                   13525:                         if (!isset($subd[0])) {
                   13526:                             $subd = array($subd);
                   13527:                         }
                   13528: 
                   13529:                         foreach ($subd as $groupa) {
                   13530:                             foreach ($groupa as $deptype => $depinfo) {
                   13531:                                 if ($deptype == 'attribs') {
                   13532:                                     continue;
                   13533:                                 }
                   13534: 
                   13535:                                 if ($deptype == 'pearinstaller') {
                   13536:                                     $deptype = 'pear Installer';
                   13537:                                 }
                   13538: 
                   13539:                                 if (!isset($depinfo[0])) {
                   13540:                                     $depinfo = array($depinfo);
                   13541:                                 }
                   13542: 
                   13543:                                 foreach ($depinfo as $inf) {
                   13544:                                     $name = '';
                   13545:                                     if (isset($inf['channel'])) {
                   13546:                                         $alias = $reg->channelAlias($inf['channel']);
                   13547:                                         if (!$alias) {
                   13548:                                             $alias = '(channel?) ' .$inf['channel'];
                   13549:                                         }
                   13550:                                         $name = $alias . '/';
                   13551: 
                   13552:                                     }
                   13553:                                     if (isset($inf['name'])) {
                   13554:                                         $name .= $inf['name'];
                   13555:                                     } elseif (isset($inf['pattern'])) {
                   13556:                                         $name .= $inf['pattern'];
                   13557:                                     } else {
                   13558:                                         $name .= '';
                   13559:                                     }
                   13560: 
                   13561:                                     if (isset($inf['uri'])) {
                   13562:                                         $name .= ' [' . $inf['uri'] .  ']';
                   13563:                                     }
                   13564: 
                   13565:                                     if (isset($inf['conflicts'])) {
                   13566:                                         $ver = 'conflicts';
                   13567:                                     } else {
                   13568:                                         $ver = $d->_getExtraString($inf);
                   13569:                                     }
                   13570: 
                   13571:                                     $data['data'][] = array($req, ucfirst($deptype), $name,
                   13572:                                         $ver, $group);
                   13573:                                 }
                   13574:                             }
                   13575:                         }
                   13576:                     }
                   13577:                 }
                   13578:             }
                   13579: 
                   13580:             $this->ui->outputData($data, $command);
                   13581:             return true;
                   13582:         }
                   13583: 
                   13584:         // Fallback
                   13585:         $this->ui->outputData("This package does not have any dependencies.", $command);
                   13586:     }
                   13587: 
                   13588:     function doSign($command, $options, $params)
                   13589:     {
                   13590:         // should move most of this code into PEAR_Packager
                   13591:         // so it'll be easy to implement "pear package --sign"
                   13592:         if (count($params) !== 1) {
                   13593:             return $this->raiseError("bad parameter(s), try \"help $command\"");
                   13594:         }
                   13595: 
                   13596:         require_once 'System.php';
                   13597:         require_once 'Archive/Tar.php';
                   13598: 
                   13599:         if (!file_exists($params[0])) {
                   13600:             return $this->raiseError("file does not exist: $params[0]");
                   13601:         }
                   13602: 
                   13603:         $obj = $this->getPackageFile($this->config, $this->_debug);
                   13604:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
                   13605:         if (PEAR::isError($info)) {
                   13606:             return $this->raiseError($info);
                   13607:         }
                   13608: 
                   13609:         $tar = new Archive_Tar($params[0]);
                   13610: 
                   13611:         $tmpdir = $this->config->get('temp_dir');
                   13612:         $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
                   13613:         if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
                   13614:             return $this->raiseError("failed to extract tar file");
                   13615:         }
                   13616: 
                   13617:         if (file_exists("$tmpdir/package.sig")) {
                   13618:             return $this->raiseError("package already signed");
                   13619:         }
                   13620: 
                   13621:         $packagexml = 'package.xml';
                   13622:         if (file_exists("$tmpdir/package2.xml")) {
                   13623:             $packagexml = 'package2.xml';
                   13624:         }
                   13625: 
                   13626:         if (file_exists("$tmpdir/package.sig")) {
                   13627:             unlink("$tmpdir/package.sig");
                   13628:         }
                   13629: 
                   13630:         if (!file_exists("$tmpdir/$packagexml")) {
                   13631:             return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
                   13632:         }
                   13633: 
                   13634:         $input = $this->ui->userDialog($command,
                   13635:                                        array('GnuPG Passphrase'),
                   13636:                                        array('password'));
                   13637:         if (!isset($input[0])) {
                   13638:             //use empty passphrase
                   13639:             $input[0] = '';
                   13640:         }
                   13641: 
                   13642:         $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
                   13643:         $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
                   13644:         if (!$gpg) {
                   13645:             return $this->raiseError("gpg command failed");
                   13646:         }
                   13647: 
                   13648:         fwrite($gpg, "$input[0]\n");
                   13649:         if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
                   13650:             return $this->raiseError("gpg sign failed");
                   13651:         }
                   13652: 
                   13653:         if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
                   13654:             return $this->raiseError('failed adding signature to file');
                   13655:         }
                   13656: 
                   13657:         $this->ui->outputData("Package signed.", $command);
                   13658:         return true;
                   13659:     }
                   13660: 
                   13661:     /**
                   13662:      * For unit testing purposes
                   13663:      */
                   13664:     function &getInstaller(&$ui)
                   13665:     {
                   13666:         if (!class_exists('PEAR_Installer')) {
                   13667:             require_once 'PEAR/Installer.php';
                   13668:         }
                   13669:         $a = &new PEAR_Installer($ui);
                   13670:         return $a;
                   13671:     }
                   13672: 
                   13673:     /**
                   13674:      * For unit testing purposes
                   13675:      */
                   13676:     function &getCommandPackaging(&$ui, &$config)
                   13677:     {
                   13678:         if (!class_exists('PEAR_Command_Packaging')) {
                   13679:             if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
                   13680:                 fclose($fp);
                   13681:                 include_once 'PEAR/Command/Packaging.php';
                   13682:             }
                   13683:         }
                   13684: 
                   13685:         if (class_exists('PEAR_Command_Packaging')) {
                   13686:             $a = &new PEAR_Command_Packaging($ui, $config);
                   13687:         } else {
                   13688:             $a = null;
                   13689:         }
                   13690: 
                   13691:         return $a;
                   13692:     }
                   13693: 
                   13694:     function doMakeRPM($command, $options, $params)
                   13695:     {
                   13696: 
                   13697:         // Check to see if PEAR_Command_Packaging is installed, and
                   13698:         // transparently switch to use the "make-rpm-spec" command from it
                   13699:         // instead, if it does. Otherwise, continue to use the old version
                   13700:         // of "makerpm" supplied with this package (PEAR).
                   13701:         $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
                   13702:         if ($packaging_cmd !== null) {
                   13703:             $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
                   13704:                 'newer "make-rpm-spec" command instead');
                   13705:             return $packaging_cmd->run('make-rpm-spec', $options, $params);
                   13706:         }
                   13707: 
                   13708:         $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
                   13709:           'improved version is available via "pear make-rpm-spec", which '.
                   13710:           'is available by installing PEAR_Command_Packaging');
                   13711:         return true;
                   13712:     }
                   13713: 
                   13714:     function doConvert($command, $options, $params)
                   13715:     {
                   13716:         $packagexml    = isset($params[0]) ? $params[0] : 'package.xml';
                   13717:         $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
                   13718:             DIRECTORY_SEPARATOR . 'package2.xml';
                   13719:         $pkg = &$this->getPackageFile($this->config, $this->_debug);
                   13720:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   13721:         $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
                   13722:         PEAR::staticPopErrorHandling();
                   13723:         if (PEAR::isError($pf)) {
                   13724:             if (is_array($pf->getUserInfo())) {
                   13725:                 foreach ($pf->getUserInfo() as $warning) {
                   13726:                     $this->ui->outputData($warning['message']);
                   13727:                 }
                   13728:             }
                   13729:             return $this->raiseError($pf);
                   13730:         }
                   13731: 
                   13732:         if (is_a($pf, 'PEAR_PackageFile_v2')) {
                   13733:             $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
                   13734:             return true;
                   13735:         }
                   13736: 
                   13737:         $gen   = &$pf->getDefaultGenerator();
                   13738:         $newpf = &$gen->toV2();
                   13739:         $newpf->setPackagefile($newpackagexml);
                   13740:         $gen = &$newpf->getDefaultGenerator();
                   13741:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   13742:         $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
                   13743:         $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
                   13744:         PEAR::staticPopErrorHandling();
                   13745:         if (PEAR::isError($saved)) {
                   13746:             if (is_array($saved->getUserInfo())) {
                   13747:                 foreach ($saved->getUserInfo() as $warning) {
                   13748:                     $this->ui->outputData($warning['message']);
                   13749:                 }
                   13750:             }
                   13751: 
                   13752:             $this->ui->outputData($saved->getMessage());
                   13753:             return true;
                   13754:         }
                   13755: 
                   13756:         $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
                   13757:         return true;
                   13758:     }
                   13759: }PEAR-1.9.4/PEAR/Command/Pickle.xml0000644000076500000240000000223311605156760015274 0ustar  helgistaff<commands version="1.0">
                   13760:  <pickle>
                   13761:   <summary>Build PECL Package</summary>
                   13762:   <function>doPackage</function>
                   13763:   <shortcut>pi</shortcut>
                   13764:   <options>
                   13765:    <nocompress>
                   13766:     <shortopt>Z</shortopt>
                   13767:     <doc>Do not gzip the package file</doc>
                   13768:    </nocompress>
                   13769:    <showname>
                   13770:     <shortopt>n</shortopt>
                   13771:     <doc>Print the name of the packaged file.</doc>
                   13772:    </showname>
                   13773:   </options>
                   13774:   <doc>[descfile]
                   13775: Creates a PECL package from its package2.xml file.
                   13776: 
                   13777: An automatic conversion will be made to a package.xml 1.0 and written out to
                   13778: disk in the current directory as &quot;package.xml&quot;.  Note that
                   13779: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
                   13780: 
                   13781:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
                   13782:  - more than one extsrcrelease or zendextsrcrelease
                   13783:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
                   13784:  - dependency groups
                   13785:  - ignore tags in release filelist
                   13786:  - tasks other than replace
                   13787:  - custom roles
                   13788: 
                   13789: will cause pickle to fail, and output an error message.  If your package2.xml
                   13790: uses any of these features, you are best off using PEAR_PackageFileManager to
                   13791: generate both package.xml.
                   13792: </doc>
                   13793:  </pickle>
                   13794: </commands>PEAR-1.9.4/PEAR/Command/Pickle.php0000644000076500000240000003715611605156760015277 0ustar  helgistaff<?php
                   13795: /**
                   13796:  * PEAR_Command_Pickle (pickle command)
                   13797:  *
                   13798:  * PHP versions 4 and 5
                   13799:  *
                   13800:  * @category   pear
                   13801:  * @package    PEAR
                   13802:  * @author     Greg Beaver <cellog@php.net>
                   13803:  * @copyright  2005-2009 The Authors
                   13804:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   13805:  * @version    CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
                   13806:  * @link       http://pear.php.net/package/PEAR
                   13807:  * @since      File available since Release 1.4.1
                   13808:  */
                   13809: 
                   13810: /**
                   13811:  * base class
                   13812:  */
                   13813: require_once 'PEAR/Command/Common.php';
                   13814: 
                   13815: /**
                   13816:  * PEAR commands for login/logout
                   13817:  *
                   13818:  * @category   pear
                   13819:  * @package    PEAR
                   13820:  * @author     Greg Beaver <cellog@php.net>
                   13821:  * @copyright  2005-2009 The Authors
                   13822:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   13823:  * @version    Release: 1.9.4
                   13824:  * @link       http://pear.php.net/package/PEAR
                   13825:  * @since      Class available since Release 1.4.1
                   13826:  */
                   13827: 
                   13828: class PEAR_Command_Pickle extends PEAR_Command_Common
                   13829: {
                   13830:     var $commands = array(
                   13831:         'pickle' => array(
                   13832:             'summary' => 'Build PECL Package',
                   13833:             'function' => 'doPackage',
                   13834:             'shortcut' => 'pi',
                   13835:             'options' => array(
                   13836:                 'nocompress' => array(
                   13837:                     'shortopt' => 'Z',
                   13838:                     'doc' => 'Do not gzip the package file'
                   13839:                     ),
                   13840:                 'showname' => array(
                   13841:                     'shortopt' => 'n',
                   13842:                     'doc' => 'Print the name of the packaged file.',
                   13843:                     ),
                   13844:                 ),
                   13845:             'doc' => '[descfile]
                   13846: Creates a PECL package from its package2.xml file.
                   13847: 
                   13848: An automatic conversion will be made to a package.xml 1.0 and written out to
                   13849: disk in the current directory as "package.xml".  Note that
                   13850: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
                   13851: 
                   13852:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
                   13853:  - more than one extsrcrelease or zendextsrcrelease
                   13854:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
                   13855:  - dependency groups
                   13856:  - ignore tags in release filelist
                   13857:  - tasks other than replace
                   13858:  - custom roles
                   13859: 
                   13860: will cause pickle to fail, and output an error message.  If your package2.xml
                   13861: uses any of these features, you are best off using PEAR_PackageFileManager to
                   13862: generate both package.xml.
                   13863: '
                   13864:             ),
                   13865:         );
                   13866: 
                   13867:     /**
                   13868:      * PEAR_Command_Package constructor.
                   13869:      *
                   13870:      * @access public
                   13871:      */
                   13872:     function PEAR_Command_Pickle(&$ui, &$config)
                   13873:     {
                   13874:         parent::PEAR_Command_Common($ui, $config);
                   13875:     }
                   13876: 
                   13877:     /**
                   13878:      * For unit-testing ease
                   13879:      *
                   13880:      * @return PEAR_Packager
                   13881:      */
                   13882:     function &getPackager()
                   13883:     {
                   13884:         if (!class_exists('PEAR_Packager')) {
                   13885:             require_once 'PEAR/Packager.php';
                   13886:         }
                   13887: 
                   13888:         $a = &new PEAR_Packager;
                   13889:         return $a;
                   13890:     }
                   13891: 
                   13892:     /**
                   13893:      * For unit-testing ease
                   13894:      *
                   13895:      * @param PEAR_Config $config
                   13896:      * @param bool $debug
                   13897:      * @param string|null $tmpdir
                   13898:      * @return PEAR_PackageFile
                   13899:      */
                   13900:     function &getPackageFile($config, $debug = false)
                   13901:     {
                   13902:         if (!class_exists('PEAR_Common')) {
                   13903:             require_once 'PEAR/Common.php';
                   13904:         }
                   13905: 
                   13906:         if (!class_exists('PEAR_PackageFile')) {
                   13907:             require_once 'PEAR/PackageFile.php';
                   13908:         }
                   13909: 
                   13910:         $a = &new PEAR_PackageFile($config, $debug);
                   13911:         $common = new PEAR_Common;
                   13912:         $common->ui = $this->ui;
                   13913:         $a->setLogger($common);
                   13914:         return $a;
                   13915:     }
                   13916: 
                   13917:     function doPackage($command, $options, $params)
                   13918:     {
                   13919:         $this->output = '';
                   13920:         $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
                   13921:         $packager = &$this->getPackager();
                   13922:         if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
                   13923:             return $err;
                   13924:         }
                   13925: 
                   13926:         $compress = empty($options['nocompress']) ? true : false;
                   13927:         $result = $packager->package($pkginfofile, $compress, 'package.xml');
                   13928:         if (PEAR::isError($result)) {
                   13929:             return $this->raiseError($result);
                   13930:         }
                   13931: 
                   13932:         // Don't want output, only the package file name just created
                   13933:         if (isset($options['showname'])) {
                   13934:             $this->ui->outputData($result, $command);
                   13935:         }
                   13936: 
                   13937:         return true;
                   13938:     }
                   13939: 
                   13940:     function _convertPackage($packagexml)
                   13941:     {
                   13942:         $pkg = &$this->getPackageFile($this->config);
                   13943:         $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
                   13944:         if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
                   13945:             return $this->raiseError('Cannot process "' .
                   13946:                 $packagexml . '", is not a package.xml 2.0');
                   13947:         }
                   13948: 
                   13949:         require_once 'PEAR/PackageFile/v1.php';
                   13950:         $pf = new PEAR_PackageFile_v1;
                   13951:         $pf->setConfig($this->config);
                   13952:         if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
                   13953:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13954:             '", is not an extension source package.  Using a PEAR_PackageFileManager-based ' .
                   13955:             'script is an option');
                   13956:         }
                   13957: 
                   13958:         if (is_array($pf2->getUsesRole())) {
                   13959:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13960:             '", contains custom roles.  Using a PEAR_PackageFileManager-based script or ' .
                   13961:             'the convert command is an option');
                   13962:         }
                   13963: 
                   13964:         if (is_array($pf2->getUsesTask())) {
                   13965:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13966:             '", contains custom tasks.  Using a PEAR_PackageFileManager-based script or ' .
                   13967:             'the convert command is an option');
                   13968:         }
                   13969: 
                   13970:         $deps = $pf2->getDependencies();
                   13971:         if (isset($deps['group'])) {
                   13972:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13973:             '", contains dependency groups.  Using a PEAR_PackageFileManager-based script ' .
                   13974:             'or the convert command is an option');
                   13975:         }
                   13976: 
                   13977:         if (isset($deps['required']['subpackage']) ||
                   13978:               isset($deps['optional']['subpackage'])) {
                   13979:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13980:             '", contains subpackage dependencies.  Using a PEAR_PackageFileManager-based  '.
                   13981:             'script is an option');
                   13982:         }
                   13983: 
                   13984:         if (isset($deps['required']['os'])) {
                   13985:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13986:             '", contains os dependencies.  Using a PEAR_PackageFileManager-based  '.
                   13987:             'script is an option');
                   13988:         }
                   13989: 
                   13990:         if (isset($deps['required']['arch'])) {
                   13991:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   13992:             '", contains arch dependencies.  Using a PEAR_PackageFileManager-based  '.
                   13993:             'script is an option');
                   13994:         }
                   13995: 
                   13996:         $pf->setPackage($pf2->getPackage());
                   13997:         $pf->setSummary($pf2->getSummary());
                   13998:         $pf->setDescription($pf2->getDescription());
                   13999:         foreach ($pf2->getMaintainers() as $maintainer) {
                   14000:             $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
                   14001:                 $maintainer['name'], $maintainer['email']);
                   14002:         }
                   14003: 
                   14004:         $pf->setVersion($pf2->getVersion());
                   14005:         $pf->setDate($pf2->getDate());
                   14006:         $pf->setLicense($pf2->getLicense());
                   14007:         $pf->setState($pf2->getState());
                   14008:         $pf->setNotes($pf2->getNotes());
                   14009:         $pf->addPhpDep($deps['required']['php']['min'], 'ge');
                   14010:         if (isset($deps['required']['php']['max'])) {
                   14011:             $pf->addPhpDep($deps['required']['php']['max'], 'le');
                   14012:         }
                   14013: 
                   14014:         if (isset($deps['required']['package'])) {
                   14015:             if (!isset($deps['required']['package'][0])) {
                   14016:                 $deps['required']['package'] = array($deps['required']['package']);
                   14017:             }
                   14018: 
                   14019:             foreach ($deps['required']['package'] as $dep) {
                   14020:                 if (!isset($dep['channel'])) {
                   14021:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14022:                     ' contains uri-based dependency on a package.  Using a ' .
                   14023:                     'PEAR_PackageFileManager-based script is an option');
                   14024:                 }
                   14025: 
                   14026:                 if ($dep['channel'] != 'pear.php.net'
                   14027:                     && $dep['channel'] != 'pecl.php.net'
                   14028:                     && $dep['channel'] != 'doc.php.net') {
                   14029:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14030:                     ' contains dependency on a non-standard channel package.  Using a ' .
                   14031:                     'PEAR_PackageFileManager-based script is an option');
                   14032:                 }
                   14033: 
                   14034:                 if (isset($dep['conflicts'])) {
                   14035:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14036:                     ' contains conflicts dependency.  Using a ' .
                   14037:                     'PEAR_PackageFileManager-based script is an option');
                   14038:                 }
                   14039: 
                   14040:                 if (isset($dep['exclude'])) {
                   14041:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14042:                 }
                   14043: 
                   14044:                 if (isset($dep['min'])) {
                   14045:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
                   14046:                 }
                   14047: 
                   14048:                 if (isset($dep['max'])) {
                   14049:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le');
                   14050:                 }
                   14051:             }
                   14052:         }
                   14053: 
                   14054:         if (isset($deps['required']['extension'])) {
                   14055:             if (!isset($deps['required']['extension'][0])) {
                   14056:                 $deps['required']['extension'] = array($deps['required']['extension']);
                   14057:             }
                   14058: 
                   14059:             foreach ($deps['required']['extension'] as $dep) {
                   14060:                 if (isset($dep['conflicts'])) {
                   14061:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14062:                     ' contains conflicts dependency.  Using a ' .
                   14063:                     'PEAR_PackageFileManager-based script is an option');
                   14064:                 }
                   14065: 
                   14066:                 if (isset($dep['exclude'])) {
                   14067:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14068:                 }
                   14069: 
                   14070:                 if (isset($dep['min'])) {
                   14071:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
                   14072:                 }
                   14073: 
                   14074:                 if (isset($dep['max'])) {
                   14075:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
                   14076:                 }
                   14077:             }
                   14078:         }
                   14079: 
                   14080:         if (isset($deps['optional']['package'])) {
                   14081:             if (!isset($deps['optional']['package'][0])) {
                   14082:                 $deps['optional']['package'] = array($deps['optional']['package']);
                   14083:             }
                   14084: 
                   14085:             foreach ($deps['optional']['package'] as $dep) {
                   14086:                 if (!isset($dep['channel'])) {
                   14087:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14088:                     ' contains uri-based dependency on a package.  Using a ' .
                   14089:                     'PEAR_PackageFileManager-based script is an option');
                   14090:                 }
                   14091: 
                   14092:                 if ($dep['channel'] != 'pear.php.net'
                   14093:                     && $dep['channel'] != 'pecl.php.net'
                   14094:                     && $dep['channel'] != 'doc.php.net') {
                   14095:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14096:                     ' contains dependency on a non-standard channel package.  Using a ' .
                   14097:                     'PEAR_PackageFileManager-based script is an option');
                   14098:                 }
                   14099: 
                   14100:                 if (isset($dep['exclude'])) {
                   14101:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14102:                 }
                   14103: 
                   14104:                 if (isset($dep['min'])) {
                   14105:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
                   14106:                 }
                   14107: 
                   14108:                 if (isset($dep['max'])) {
                   14109:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
                   14110:                 }
                   14111:             }
                   14112:         }
                   14113: 
                   14114:         if (isset($deps['optional']['extension'])) {
                   14115:             if (!isset($deps['optional']['extension'][0])) {
                   14116:                 $deps['optional']['extension'] = array($deps['optional']['extension']);
                   14117:             }
                   14118: 
                   14119:             foreach ($deps['optional']['extension'] as $dep) {
                   14120:                 if (isset($dep['exclude'])) {
                   14121:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14122:                 }
                   14123: 
                   14124:                 if (isset($dep['min'])) {
                   14125:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
                   14126:                 }
                   14127: 
                   14128:                 if (isset($dep['max'])) {
                   14129:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
                   14130:                 }
                   14131:             }
                   14132:         }
                   14133: 
                   14134:         $contents = $pf2->getContents();
                   14135:         $release  = $pf2->getReleases();
                   14136:         if (isset($releases[0])) {
                   14137:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
                   14138:             . 'multiple extsrcrelease/zendextsrcrelease tags.  Using a PEAR_PackageFileManager-based script ' .
                   14139:             'or the convert command is an option');
                   14140:         }
                   14141: 
                   14142:         if ($configoptions = $pf2->getConfigureOptions()) {
                   14143:             foreach ($configoptions as $option) {
                   14144:                 $default = isset($option['default']) ? $option['default'] : false;
                   14145:                 $pf->addConfigureOption($option['name'], $option['prompt'], $default);
                   14146:             }
                   14147:         }
                   14148: 
                   14149:         if (isset($release['filelist']['ignore'])) {
                   14150:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
                   14151:             . 'ignore tags.  Using a PEAR_PackageFileManager-based script or the convert' .
                   14152:             ' command is an option');
                   14153:         }
                   14154: 
                   14155:         if (isset($release['filelist']['install']) &&
                   14156:               !isset($release['filelist']['install'][0])) {
                   14157:             $release['filelist']['install'] = array($release['filelist']['install']);
                   14158:         }
                   14159: 
                   14160:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
                   14161:             $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
                   14162:         } else {
                   14163:             $baseinstalldir = false;
                   14164:         }
                   14165: 
                   14166:         if (!isset($contents['dir']['file'][0])) {
                   14167:             $contents['dir']['file'] = array($contents['dir']['file']);
                   14168:         }
                   14169: 
                   14170:         foreach ($contents['dir']['file'] as $file) {
                   14171:             if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
                   14172:                 $file['attribs']['baseinstalldir'] = $baseinstalldir;
                   14173:             }
                   14174: 
                   14175:             $processFile = $file;
                   14176:             unset($processFile['attribs']);
                   14177:             if (count($processFile)) {
                   14178:                 foreach ($processFile as $name => $task) {
                   14179:                     if ($name != $pf2->getTasksNs() . ':replace') {
                   14180:                         return $this->raiseError('Cannot safely process "' . $packagexml .
                   14181:                         '" contains tasks other than replace.  Using a ' .
                   14182:                         'PEAR_PackageFileManager-based script is an option.');
                   14183:                     }
                   14184:                     $file['attribs']['replace'][] = $task;
                   14185:                 }
                   14186:             }
                   14187: 
                   14188:             if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
                   14189:                 return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14190:                 '", contains custom roles.  Using a PEAR_PackageFileManager-based script ' .
                   14191:                 'or the convert command is an option');
                   14192:             }
                   14193: 
                   14194:             if (isset($release['filelist']['install'])) {
                   14195:                 foreach ($release['filelist']['install'] as $installas) {
                   14196:                     if ($installas['attribs']['name'] == $file['attribs']['name']) {
                   14197:                         $file['attribs']['install-as'] = $installas['attribs']['as'];
                   14198:                     }
                   14199:                 }
                   14200:             }
                   14201: 
                   14202:             $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
                   14203:         }
                   14204: 
                   14205:         if ($pf2->getChangeLog()) {
                   14206:             $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
                   14207:                 '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
                   14208:                 'translation for package.xml 1.0');
                   14209:         }
                   14210: 
                   14211:         $gen = &$pf->getDefaultGenerator();
                   14212:         $gen->toPackageFile('.');
                   14213:     }
                   14214: }PEAR-1.9.4/PEAR/Command/Registry.xml0000644000076500000240000000337611605156760015706 0ustar  helgistaff<commands version="1.0">
                   14215:  <list>
                   14216:   <summary>List Installed Packages In The Default Channel</summary>
                   14217:   <function>doList</function>
                   14218:   <shortcut>l</shortcut>
                   14219:   <options>
                   14220:    <channel>
                   14221:     <shortopt>c</shortopt>
                   14222:     <doc>list installed packages from this channel</doc>
                   14223:     <arg>CHAN</arg>
                   14224:    </channel>
                   14225:    <allchannels>
                   14226:     <shortopt>a</shortopt>
                   14227:     <doc>list installed packages from all channels</doc>
                   14228:    </allchannels>
                   14229:    <channelinfo>
                   14230:     <shortopt>i</shortopt>
                   14231:     <doc>output fully channel-aware data, even on failure</doc>
                   14232:    </channelinfo>
                   14233:   </options>
                   14234:   <doc>&lt;package&gt;
                   14235: If invoked without parameters, this command lists the PEAR packages
                   14236: installed in your php_dir ({config php_dir}).  With a parameter, it
                   14237: lists the files in a package.
                   14238: </doc>
                   14239:  </list>
                   14240:  <list-files>
                   14241:   <summary>List Files In Installed Package</summary>
                   14242:   <function>doFileList</function>
                   14243:   <shortcut>fl</shortcut>
                   14244:   <options />
                   14245:   <doc>&lt;package&gt;
                   14246: List the files in an installed package.
                   14247: </doc>
                   14248:  </list-files>
                   14249:  <shell-test>
                   14250:   <summary>Shell Script Test</summary>
                   14251:   <function>doShellTest</function>
                   14252:   <shortcut>st</shortcut>
                   14253:   <options />
                   14254:   <doc>&lt;package&gt; [[relation] version]
                   14255: Tests if a package is installed in the system. Will exit(1) if it is not.
                   14256:    &lt;relation&gt;   The version comparison operator. One of:
                   14257:                 &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
                   14258:    &lt;version&gt;    The version to compare with
                   14259: </doc>
                   14260:  </shell-test>
                   14261:  <info>
                   14262:   <summary>Display information about a package</summary>
                   14263:   <function>doInfo</function>
                   14264:   <shortcut>in</shortcut>
                   14265:   <options />
                   14266:   <doc>&lt;package&gt;
                   14267: Displays information about a package. The package argument may be a
                   14268: local package file, an URL to a package file, or the name of an
                   14269: installed package.</doc>
                   14270:  </info>
                   14271: </commands>PEAR-1.9.4/PEAR/Command/Registry.php0000644000076500000240000013241611605156760015673 0ustar  helgistaff<?php
                   14272: /**
                   14273:  * PEAR_Command_Registry (list, list-files, shell-test, info commands)
                   14274:  *
                   14275:  * PHP versions 4 and 5
                   14276:  *
                   14277:  * @category   pear
                   14278:  * @package    PEAR
                   14279:  * @author     Stig Bakken <ssb@php.net>
                   14280:  * @author     Greg Beaver <cellog@php.net>
                   14281:  * @copyright  1997-2009 The Authors
                   14282:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14283:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
                   14284:  * @link       http://pear.php.net/package/PEAR
                   14285:  * @since      File available since Release 0.1
                   14286:  */
                   14287: 
                   14288: /**
                   14289:  * base class
                   14290:  */
                   14291: require_once 'PEAR/Command/Common.php';
                   14292: 
                   14293: /**
                   14294:  * PEAR commands for registry manipulation
                   14295:  *
                   14296:  * @category   pear
                   14297:  * @package    PEAR
                   14298:  * @author     Stig Bakken <ssb@php.net>
                   14299:  * @author     Greg Beaver <cellog@php.net>
                   14300:  * @copyright  1997-2009 The Authors
                   14301:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14302:  * @version    Release: 1.9.4
                   14303:  * @link       http://pear.php.net/package/PEAR
                   14304:  * @since      Class available since Release 0.1
                   14305:  */
                   14306: class PEAR_Command_Registry extends PEAR_Command_Common
                   14307: {
                   14308:     var $commands = array(
                   14309:         'list' => array(
                   14310:             'summary' => 'List Installed Packages In The Default Channel',
                   14311:             'function' => 'doList',
                   14312:             'shortcut' => 'l',
                   14313:             'options' => array(
                   14314:                 'channel' => array(
                   14315:                     'shortopt' => 'c',
                   14316:                     'doc' => 'list installed packages from this channel',
                   14317:                     'arg' => 'CHAN',
                   14318:                     ),
                   14319:                 'allchannels' => array(
                   14320:                     'shortopt' => 'a',
                   14321:                     'doc' => 'list installed packages from all channels',
                   14322:                     ),
                   14323:                 'channelinfo' => array(
                   14324:                     'shortopt' => 'i',
                   14325:                     'doc' => 'output fully channel-aware data, even on failure',
                   14326:                     ),
                   14327:                 ),
                   14328:             'doc' => '<package>
                   14329: If invoked without parameters, this command lists the PEAR packages
                   14330: installed in your php_dir ({config php_dir}).  With a parameter, it
                   14331: lists the files in a package.
                   14332: ',
                   14333:             ),
                   14334:         'list-files' => array(
                   14335:             'summary' => 'List Files In Installed Package',
                   14336:             'function' => 'doFileList',
                   14337:             'shortcut' => 'fl',
                   14338:             'options' => array(),
                   14339:             'doc' => '<package>
                   14340: List the files in an installed package.
                   14341: '
                   14342:             ),
                   14343:         'shell-test' => array(
                   14344:             'summary' => 'Shell Script Test',
                   14345:             'function' => 'doShellTest',
                   14346:             'shortcut' => 'st',
                   14347:             'options' => array(),
                   14348:             'doc' => '<package> [[relation] version]
                   14349: Tests if a package is installed in the system. Will exit(1) if it is not.
                   14350:    <relation>   The version comparison operator. One of:
                   14351:                 <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
                   14352:    <version>    The version to compare with
                   14353: '),
                   14354:         'info' => array(
                   14355:             'summary'  => 'Display information about a package',
                   14356:             'function' => 'doInfo',
                   14357:             'shortcut' => 'in',
                   14358:             'options'  => array(),
                   14359:             'doc'      => '<package>
                   14360: Displays information about a package. The package argument may be a
                   14361: local package file, an URL to a package file, or the name of an
                   14362: installed package.'
                   14363:             )
                   14364:         );
                   14365: 
                   14366:     /**
                   14367:      * PEAR_Command_Registry constructor.
                   14368:      *
                   14369:      * @access public
                   14370:      */
                   14371:     function PEAR_Command_Registry(&$ui, &$config)
                   14372:     {
                   14373:         parent::PEAR_Command_Common($ui, $config);
                   14374:     }
                   14375: 
                   14376:     function _sortinfo($a, $b)
                   14377:     {
                   14378:         $apackage = isset($a['package']) ? $a['package'] : $a['name'];
                   14379:         $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
                   14380:         return strcmp($apackage, $bpackage);
                   14381:     }
                   14382: 
                   14383:     function doList($command, $options, $params)
                   14384:     {
                   14385:         $reg = &$this->config->getRegistry();
                   14386:         $channelinfo = isset($options['channelinfo']);
                   14387:         if (isset($options['allchannels']) && !$channelinfo) {
                   14388:             return $this->doListAll($command, array(), $params);
                   14389:         }
                   14390: 
                   14391:         if (isset($options['allchannels']) && $channelinfo) {
                   14392:             // allchannels with $channelinfo
                   14393:             unset($options['allchannels']);
                   14394:             $channels = $reg->getChannels();
                   14395:             $errors = array();
                   14396:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14397:             foreach ($channels as $channel) {
                   14398:                 $options['channel'] = $channel->getName();
                   14399:                 $ret = $this->doList($command, $options, $params);
                   14400: 
                   14401:                 if (PEAR::isError($ret)) {
                   14402:                     $errors[] = $ret;
                   14403:                 }
                   14404:             }
                   14405: 
                   14406:             PEAR::staticPopErrorHandling();
                   14407:             if (count($errors)) {
                   14408:                 // for now, only give first error
                   14409:                 return PEAR::raiseError($errors[0]);
                   14410:             }
                   14411: 
                   14412:             return true;
                   14413:         }
                   14414: 
                   14415:         if (count($params) === 1) {
                   14416:             return $this->doFileList($command, $options, $params);
                   14417:         }
                   14418: 
                   14419:         if (isset($options['channel'])) {
                   14420:             if (!$reg->channelExists($options['channel'])) {
                   14421:                 return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
                   14422:             }
                   14423: 
                   14424:             $channel = $reg->channelName($options['channel']);
                   14425:         } else {
                   14426:             $channel = $this->config->get('default_channel');
                   14427:         }
                   14428: 
                   14429:         $installed = $reg->packageInfo(null, null, $channel);
                   14430:         usort($installed, array(&$this, '_sortinfo'));
                   14431: 
                   14432:         $data = array(
                   14433:             'caption' => 'Installed packages, channel ' .
                   14434:                 $channel . ':',
                   14435:             'border' => true,
                   14436:             'headline' => array('Package', 'Version', 'State'),
                   14437:             'channel' => $channel,
                   14438:             );
                   14439:         if ($channelinfo) {
                   14440:             $data['headline'] = array('Channel', 'Package', 'Version', 'State');
                   14441:         }
                   14442: 
                   14443:         if (count($installed) && !isset($data['data'])) {
                   14444:             $data['data'] = array();
                   14445:         }
                   14446: 
                   14447:         foreach ($installed as $package) {
                   14448:             $pobj = $reg->getPackage(isset($package['package']) ?
                   14449:                                         $package['package'] : $package['name'], $channel);
                   14450:             if ($channelinfo) {
                   14451:                 $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
                   14452:                                     $pobj->getState() ? $pobj->getState() : null);
                   14453:             } else {
                   14454:                 $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
                   14455:                                     $pobj->getState() ? $pobj->getState() : null);
                   14456:             }
                   14457:             $data['data'][] = $packageinfo;
                   14458:         }
                   14459: 
                   14460:         if (count($installed) === 0) {
                   14461:             if (!$channelinfo) {
                   14462:                 $data = '(no packages installed from channel ' . $channel . ')';
                   14463:             } else {
                   14464:                 $data = array(
                   14465:                     'caption' => 'Installed packages, channel ' .
                   14466:                         $channel . ':',
                   14467:                     'border' => true,
                   14468:                     'channel' => $channel,
                   14469:                     'data' => array(array('(no packages installed)')),
                   14470:                 );
                   14471:             }
                   14472:         }
                   14473: 
                   14474:         $this->ui->outputData($data, $command);
                   14475:         return true;
                   14476:     }
                   14477: 
                   14478:     function doListAll($command, $options, $params)
                   14479:     {
                   14480:         // This duplicate code is deprecated over
                   14481:         // list --channelinfo, which gives identical
                   14482:         // output for list and list --allchannels.
                   14483:         $reg = &$this->config->getRegistry();
                   14484:         $installed = $reg->packageInfo(null, null, null);
                   14485:         foreach ($installed as $channel => $packages) {
                   14486:             usort($packages, array($this, '_sortinfo'));
                   14487:             $data = array(
                   14488:                 'caption'  => 'Installed packages, channel ' . $channel . ':',
                   14489:                 'border'   => true,
                   14490:                 'headline' => array('Package', 'Version', 'State'),
                   14491:                 'channel'  => $channel
                   14492:             );
                   14493: 
                   14494:             foreach ($packages as $package) {
                   14495:                 $p = isset($package['package']) ? $package['package'] : $package['name'];
                   14496:                 $pobj = $reg->getPackage($p, $channel);
                   14497:                 $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
                   14498:                                         $pobj->getState() ? $pobj->getState() : null);
                   14499:             }
                   14500: 
                   14501:             // Adds a blank line after each section
                   14502:             $data['data'][] = array();
                   14503: 
                   14504:             if (count($packages) === 0) {
                   14505:                 $data = array(
                   14506:                     'caption' => 'Installed packages, channel ' . $channel . ':',
                   14507:                     'border' => true,
                   14508:                     'data' => array(array('(no packages installed)'), array()),
                   14509:                     'channel' => $channel
                   14510:                     );
                   14511:             }
                   14512:             $this->ui->outputData($data, $command);
                   14513:         }
                   14514:         return true;
                   14515:     }
                   14516: 
                   14517:     function doFileList($command, $options, $params)
                   14518:     {
                   14519:         if (count($params) !== 1) {
                   14520:             return $this->raiseError('list-files expects 1 parameter');
                   14521:         }
                   14522: 
                   14523:         $reg = &$this->config->getRegistry();
                   14524:         $fp = false;
                   14525:         if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
                   14526:             if ($fp) {
                   14527:                 fclose($fp);
                   14528:             }
                   14529: 
                   14530:             if (!class_exists('PEAR_PackageFile')) {
                   14531:                 require_once 'PEAR/PackageFile.php';
                   14532:             }
                   14533: 
                   14534:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
                   14535:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14536:             $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   14537:             PEAR::staticPopErrorHandling();
                   14538:             $headings = array('Package File', 'Install Path');
                   14539:             $installed = false;
                   14540:         } else {
                   14541:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14542:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   14543:             PEAR::staticPopErrorHandling();
                   14544:             if (PEAR::isError($parsed)) {
                   14545:                 return $this->raiseError($parsed);
                   14546:             }
                   14547: 
                   14548:             $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
                   14549:             $headings = array('Type', 'Install Path');
                   14550:             $installed = true;
                   14551:         }
                   14552: 
                   14553:         if (PEAR::isError($info)) {
                   14554:             return $this->raiseError($info);
                   14555:         }
                   14556: 
                   14557:         if ($info === null) {
                   14558:             return $this->raiseError("`$params[0]' not installed");
                   14559:         }
                   14560: 
                   14561:         $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
                   14562:             $info->getFilelist() : $info->getContents();
                   14563:         if ($installed) {
                   14564:             $caption = 'Installed Files For ' . $params[0];
                   14565:         } else {
                   14566:             $caption = 'Contents of ' . basename($params[0]);
                   14567:         }
                   14568: 
                   14569:         $data = array(
                   14570:             'caption' => $caption,
                   14571:             'border' => true,
                   14572:             'headline' => $headings);
                   14573:         if ($info->getPackagexmlVersion() == '1.0' || $installed) {
                   14574:             foreach ($list as $file => $att) {
                   14575:                 if ($installed) {
                   14576:                     if (empty($att['installed_as'])) {
                   14577:                         continue;
                   14578:                     }
                   14579:                     $data['data'][] = array($att['role'], $att['installed_as']);
                   14580:                 } else {
                   14581:                     if (isset($att['baseinstalldir']) && !in_array($att['role'],
                   14582:                           array('test', 'data', 'doc'))) {
                   14583:                         $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
                   14584:                             $file;
                   14585:                     } else {
                   14586:                         $dest = $file;
                   14587:                     }
                   14588:                     switch ($att['role']) {
                   14589:                         case 'test':
                   14590:                         case 'data':
                   14591:                         case 'doc':
                   14592:                             $role = $att['role'];
                   14593:                             if ($role == 'test') {
                   14594:                                 $role .= 's';
                   14595:                             }
                   14596:                             $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
                   14597:                                 $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
                   14598:                             break;
                   14599:                         case 'php':
                   14600:                         default:
                   14601:                             $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
                   14602:                                 $dest;
                   14603:                     }
                   14604:                     $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   14605:                     $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   14606:                                                     array(DIRECTORY_SEPARATOR,
                   14607:                                                           DIRECTORY_SEPARATOR,
                   14608:                                                           DIRECTORY_SEPARATOR),
                   14609:                                                     $dest);
                   14610:                     $file = preg_replace('!/+!', '/', $file);
                   14611:                     $data['data'][] = array($file, $dest);
                   14612:                 }
                   14613:             }
                   14614:         } else { // package.xml 2.0, not installed
                   14615:             if (!isset($list['dir']['file'][0])) {
                   14616:                 $list['dir']['file'] = array($list['dir']['file']);
                   14617:             }
                   14618: 
                   14619:             foreach ($list['dir']['file'] as $att) {
                   14620:                 $att = $att['attribs'];
                   14621:                 $file = $att['name'];
                   14622:                 $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
                   14623:                 $role->setup($this, $info, $att, $file);
                   14624:                 if (!$role->isInstallable()) {
                   14625:                     $dest = '(not installable)';
                   14626:                 } else {
                   14627:                     $dest = $role->processInstallation($info, $att, $file, '');
                   14628:                     if (PEAR::isError($dest)) {
                   14629:                         $dest = '(Unknown role "' . $att['role'] . ')';
                   14630:                     } else {
                   14631:                         list(,, $dest) = $dest;
                   14632:                     }
                   14633:                 }
                   14634:                 $data['data'][] = array($file, $dest);
                   14635:             }
                   14636:         }
                   14637: 
                   14638:         $this->ui->outputData($data, $command);
                   14639:         return true;
                   14640:     }
                   14641: 
                   14642:     function doShellTest($command, $options, $params)
                   14643:     {
                   14644:         if (count($params) < 1) {
                   14645:             return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
                   14646:         }
                   14647: 
                   14648:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14649:         $reg = &$this->config->getRegistry();
                   14650:         $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   14651:         if (PEAR::isError($info)) {
                   14652:             exit(1); // invalid package name
                   14653:         }
                   14654: 
                   14655:         $package = $info['package'];
                   14656:         $channel = $info['channel'];
                   14657:         // "pear shell-test Foo"
                   14658:         if (!$reg->packageExists($package, $channel)) {
                   14659:             if ($channel == 'pecl.php.net') {
                   14660:                 if ($reg->packageExists($package, 'pear.php.net')) {
                   14661:                     $channel = 'pear.php.net'; // magically change channels for extensions
                   14662:                 }
                   14663:             }
                   14664:         }
                   14665: 
                   14666:         if (count($params) === 1) {
                   14667:             if (!$reg->packageExists($package, $channel)) {
                   14668:                 exit(1);
                   14669:             }
                   14670:             // "pear shell-test Foo 1.0"
                   14671:         } elseif (count($params) === 2) {
                   14672:             $v = $reg->packageInfo($package, 'version', $channel);
                   14673:             if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
                   14674:                 exit(1);
                   14675:             }
                   14676:             // "pear shell-test Foo ge 1.0"
                   14677:         } elseif (count($params) === 3) {
                   14678:             $v = $reg->packageInfo($package, 'version', $channel);
                   14679:             if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
                   14680:                 exit(1);
                   14681:             }
                   14682:         } else {
                   14683:             PEAR::staticPopErrorHandling();
                   14684:             $this->raiseError("$command: expects 1 to 3 parameters");
                   14685:             exit(1);
                   14686:         }
                   14687:     }
                   14688: 
                   14689:     function doInfo($command, $options, $params)
                   14690:     {
                   14691:         if (count($params) !== 1) {
                   14692:             return $this->raiseError('pear info expects 1 parameter');
                   14693:         }
                   14694: 
                   14695:         $info = $fp = false;
                   14696:         $reg = &$this->config->getRegistry();
                   14697:         if (is_file($params[0]) && !is_dir($params[0]) &&
                   14698:             (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
                   14699:         ) {
                   14700:             if ($fp) {
                   14701:                 fclose($fp);
                   14702:             }
                   14703: 
                   14704:             if (!class_exists('PEAR_PackageFile')) {
                   14705:                 require_once 'PEAR/PackageFile.php';
                   14706:             }
                   14707: 
                   14708:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
                   14709:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14710:             $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   14711:             PEAR::staticPopErrorHandling();
                   14712:             if (PEAR::isError($obj)) {
                   14713:                 $uinfo = $obj->getUserInfo();
                   14714:                 if (is_array($uinfo)) {
                   14715:                     foreach ($uinfo as $message) {
                   14716:                         if (is_array($message)) {
                   14717:                             $message = $message['message'];
                   14718:                         }
                   14719:                         $this->ui->outputData($message);
                   14720:                     }
                   14721:                 }
                   14722: 
                   14723:                 return $this->raiseError($obj);
                   14724:             }
                   14725: 
                   14726:             if ($obj->getPackagexmlVersion() != '1.0') {
                   14727:                 return $this->_doInfo2($command, $options, $params, $obj, false);
                   14728:             }
                   14729: 
                   14730:             $info = $obj->toArray();
                   14731:         } else {
                   14732:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   14733:             if (PEAR::isError($parsed)) {
                   14734:                 return $this->raiseError($parsed);
                   14735:             }
                   14736: 
                   14737:             $package = $parsed['package'];
                   14738:             $channel = $parsed['channel'];
                   14739:             $info = $reg->packageInfo($package, null, $channel);
                   14740:             if (isset($info['old'])) {
                   14741:                 $obj = $reg->getPackage($package, $channel);
                   14742:                 return $this->_doInfo2($command, $options, $params, $obj, true);
                   14743:             }
                   14744:         }
                   14745: 
                   14746:         if (PEAR::isError($info)) {
                   14747:             return $info;
                   14748:         }
                   14749: 
                   14750:         if (empty($info)) {
                   14751:             $this->raiseError("No information found for `$params[0]'");
                   14752:             return;
                   14753:         }
                   14754: 
                   14755:         unset($info['filelist']);
                   14756:         unset($info['dirtree']);
                   14757:         unset($info['changelog']);
                   14758:         if (isset($info['xsdversion'])) {
                   14759:             $info['package.xml version'] = $info['xsdversion'];
                   14760:             unset($info['xsdversion']);
                   14761:         }
                   14762: 
                   14763:         if (isset($info['packagerversion'])) {
                   14764:             $info['packaged with PEAR version'] = $info['packagerversion'];
                   14765:             unset($info['packagerversion']);
                   14766:         }
                   14767: 
                   14768:         $keys = array_keys($info);
                   14769:         $longtext = array('description', 'summary');
                   14770:         foreach ($keys as $key) {
                   14771:             if (is_array($info[$key])) {
                   14772:                 switch ($key) {
                   14773:                     case 'maintainers': {
                   14774:                         $i = 0;
                   14775:                         $mstr = '';
                   14776:                         foreach ($info[$key] as $m) {
                   14777:                             if ($i++ > 0) {
                   14778:                                 $mstr .= "\n";
                   14779:                             }
                   14780:                             $mstr .= $m['name'] . " <";
                   14781:                             if (isset($m['email'])) {
                   14782:                                 $mstr .= $m['email'];
                   14783:                             } else {
                   14784:                                 $mstr .= $m['handle'] . '@php.net';
                   14785:                             }
                   14786:                             $mstr .= "> ($m[role])";
                   14787:                         }
                   14788:                         $info[$key] = $mstr;
                   14789:                         break;
                   14790:                     }
                   14791:                     case 'release_deps': {
                   14792:                         $i = 0;
                   14793:                         $dstr = '';
                   14794:                         foreach ($info[$key] as $d) {
                   14795:                             if (isset($this->_deps_rel_trans[$d['rel']])) {
                   14796:                                 $rel = $this->_deps_rel_trans[$d['rel']];
                   14797:                             } else {
                   14798:                                 $rel = $d['rel'];
                   14799:                             }
                   14800:                             if (isset($this->_deps_type_trans[$d['type']])) {
                   14801:                                 $type = ucfirst($this->_deps_type_trans[$d['type']]);
                   14802:                             } else {
                   14803:                                 $type = $d['type'];
                   14804:                             }
                   14805:                             if (isset($d['name'])) {
                   14806:                                 $name = $d['name'] . ' ';
                   14807:                             } else {
                   14808:                                 $name = '';
                   14809:                             }
                   14810:                             if (isset($d['version'])) {
                   14811:                                 $version = $d['version'] . ' ';
                   14812:                             } else {
                   14813:                                 $version = '';
                   14814:                             }
                   14815:                             if (isset($d['optional']) && $d['optional'] == 'yes') {
                   14816:                                 $optional = ' (optional)';
                   14817:                             } else {
                   14818:                                 $optional = '';
                   14819:                             }
                   14820:                             $dstr .= "$type $name$rel $version$optional\n";
                   14821:                         }
                   14822:                         $info[$key] = $dstr;
                   14823:                         break;
                   14824:                     }
                   14825:                     case 'provides' : {
                   14826:                         $debug = $this->config->get('verbose');
                   14827:                         if ($debug < 2) {
                   14828:                             $pstr = 'Classes: ';
                   14829:                         } else {
                   14830:                             $pstr = '';
                   14831:                         }
                   14832:                         $i = 0;
                   14833:                         foreach ($info[$key] as $p) {
                   14834:                             if ($debug < 2 && $p['type'] != "class") {
                   14835:                                 continue;
                   14836:                             }
                   14837:                             // Only print classes when verbosity mode is < 2
                   14838:                             if ($debug < 2) {
                   14839:                                 if ($i++ > 0) {
                   14840:                                     $pstr .= ", ";
                   14841:                                 }
                   14842:                                 $pstr .= $p['name'];
                   14843:                             } else {
                   14844:                                 if ($i++ > 0) {
                   14845:                                     $pstr .= "\n";
                   14846:                                 }
                   14847:                                 $pstr .= ucfirst($p['type']) . " " . $p['name'];
                   14848:                                 if (isset($p['explicit']) && $p['explicit'] == 1) {
                   14849:                                     $pstr .= " (explicit)";
                   14850:                                 }
                   14851:                             }
                   14852:                         }
                   14853:                         $info[$key] = $pstr;
                   14854:                         break;
                   14855:                     }
                   14856:                     case 'configure_options' : {
                   14857:                         foreach ($info[$key] as $i => $p) {
                   14858:                             $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
                   14859:                             $info[$key][$i] = array_map(create_function('$a',
                   14860:                                 'return join(" = ",$a);'), $info[$key][$i]);
                   14861:                             $info[$key][$i] = implode(', ', $info[$key][$i]);
                   14862:                         }
                   14863:                         $info[$key] = implode("\n", $info[$key]);
                   14864:                         break;
                   14865:                     }
                   14866:                     default: {
                   14867:                         $info[$key] = implode(", ", $info[$key]);
                   14868:                         break;
                   14869:                     }
                   14870:                 }
                   14871:             }
                   14872: 
                   14873:             if ($key == '_lastmodified') {
                   14874:                 $hdate = date('Y-m-d', $info[$key]);
                   14875:                 unset($info[$key]);
                   14876:                 $info['Last Modified'] = $hdate;
                   14877:             } elseif ($key == '_lastversion') {
                   14878:                 $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
                   14879:                 unset($info[$key]);
                   14880:             } else {
                   14881:                 $info[$key] = trim($info[$key]);
                   14882:                 if (in_array($key, $longtext)) {
                   14883:                     $info[$key] = preg_replace('/  +/', ' ', $info[$key]);
                   14884:                 }
                   14885:             }
                   14886:         }
                   14887: 
                   14888:         $caption = 'About ' . $info['package'] . '-' . $info['version'];
                   14889:         $data = array(
                   14890:             'caption' => $caption,
                   14891:             'border' => true);
                   14892:         foreach ($info as $key => $value) {
                   14893:             $key = ucwords(trim(str_replace('_', ' ', $key)));
                   14894:             $data['data'][] = array($key, $value);
                   14895:         }
                   14896:         $data['raw'] = $info;
                   14897: 
                   14898:         $this->ui->outputData($data, 'package-info');
                   14899:     }
                   14900: 
                   14901:     /**
                   14902:      * @access private
                   14903:      */
                   14904:     function _doInfo2($command, $options, $params, &$obj, $installed)
                   14905:     {
                   14906:         $reg = &$this->config->getRegistry();
                   14907:         $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
                   14908:             $obj->getVersion();
                   14909:         $data = array(
                   14910:             'caption' => $caption,
                   14911:             'border' => true);
                   14912:         switch ($obj->getPackageType()) {
                   14913:             case 'php' :
                   14914:                 $release = 'PEAR-style PHP-based Package';
                   14915:             break;
                   14916:             case 'extsrc' :
                   14917:                 $release = 'PECL-style PHP extension (source code)';
                   14918:             break;
                   14919:             case 'zendextsrc' :
                   14920:                 $release = 'PECL-style Zend extension (source code)';
                   14921:             break;
                   14922:             case 'extbin' :
                   14923:                 $release = 'PECL-style PHP extension (binary)';
                   14924:             break;
                   14925:             case 'zendextbin' :
                   14926:                 $release = 'PECL-style Zend extension (binary)';
                   14927:             break;
                   14928:             case 'bundle' :
                   14929:                 $release = 'Package bundle (collection of packages)';
                   14930:             break;
                   14931:         }
                   14932:         $extends = $obj->getExtends();
                   14933:         $extends = $extends ?
                   14934:             $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
                   14935:         if ($src = $obj->getSourcePackage()) {
                   14936:             $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
                   14937:         }
                   14938: 
                   14939:         $info = array(
                   14940:             'Release Type' => $release,
                   14941:             'Name' => $extends,
                   14942:             'Channel' => $obj->getChannel(),
                   14943:             'Summary' => preg_replace('/  +/', ' ', $obj->getSummary()),
                   14944:             'Description' => preg_replace('/  +/', ' ', $obj->getDescription()),
                   14945:             );
                   14946:         $info['Maintainers'] = '';
                   14947:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   14948:             $leads = $obj->{"get{$role}s"}();
                   14949:             if (!$leads) {
                   14950:                 continue;
                   14951:             }
                   14952: 
                   14953:             if (isset($leads['active'])) {
                   14954:                 $leads = array($leads);
                   14955:             }
                   14956: 
                   14957:             foreach ($leads as $lead) {
                   14958:                 if (!empty($info['Maintainers'])) {
                   14959:                     $info['Maintainers'] .= "\n";
                   14960:                 }
                   14961: 
                   14962:                 $active = $lead['active'] == 'no' ? ', inactive' : '';
                   14963:                 $info['Maintainers'] .= $lead['name'] . ' <';
                   14964:                 $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
                   14965:             }
                   14966:         }
                   14967: 
                   14968:         $info['Release Date'] = $obj->getDate();
                   14969:         if ($time = $obj->getTime()) {
                   14970:             $info['Release Date'] .= ' ' . $time;
                   14971:         }
                   14972: 
                   14973:         $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
                   14974:         $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
                   14975:         $info['License'] = $obj->getLicense();
                   14976:         $uri = $obj->getLicenseLocation();
                   14977:         if ($uri) {
                   14978:             if (isset($uri['uri'])) {
                   14979:                 $info['License'] .= ' (' . $uri['uri'] . ')';
                   14980:             } else {
                   14981:                 $extra = $obj->getInstalledLocation($info['filesource']);
                   14982:                 if ($extra) {
                   14983:                     $info['License'] .= ' (' . $uri['filesource'] . ')';
                   14984:                 }
                   14985:             }
                   14986:         }
                   14987: 
                   14988:         $info['Release Notes'] = $obj->getNotes();
                   14989:         if ($compat = $obj->getCompatible()) {
                   14990:             if (!isset($compat[0])) {
                   14991:                 $compat = array($compat);
                   14992:             }
                   14993: 
                   14994:             $info['Compatible with'] = '';
                   14995:             foreach ($compat as $package) {
                   14996:                 $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
                   14997:                     "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
                   14998:                 if (isset($package['exclude'])) {
                   14999:                     if (is_array($package['exclude'])) {
                   15000:                         $package['exclude'] = implode(', ', $package['exclude']);
                   15001:                     }
                   15002: 
                   15003:                     if (!isset($info['Not Compatible with'])) {
                   15004:                         $info['Not Compatible with'] = '';
                   15005:                     } else {
                   15006:                         $info['Not Compatible with'] .= "\n";
                   15007:                     }
                   15008:                     $info['Not Compatible with'] .= $package['channel'] . '/' .
                   15009:                         $package['name'] . "\nVersions " . $package['exclude'];
                   15010:                 }
                   15011:             }
                   15012:         }
                   15013: 
                   15014:         $usesrole = $obj->getUsesrole();
                   15015:         if ($usesrole) {
                   15016:             if (!isset($usesrole[0])) {
                   15017:                 $usesrole = array($usesrole);
                   15018:             }
                   15019: 
                   15020:             foreach ($usesrole as $roledata) {
                   15021:                 if (isset($info['Uses Custom Roles'])) {
                   15022:                     $info['Uses Custom Roles'] .= "\n";
                   15023:                 } else {
                   15024:                     $info['Uses Custom Roles'] = '';
                   15025:                 }
                   15026: 
                   15027:                 if (isset($roledata['package'])) {
                   15028:                     $rolepackage = $reg->parsedPackageNameToString($roledata, true);
                   15029:                 } else {
                   15030:                     $rolepackage = $roledata['uri'];
                   15031:                 }
                   15032:                 $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
                   15033:             }
                   15034:         }
                   15035: 
                   15036:         $usestask = $obj->getUsestask();
                   15037:         if ($usestask) {
                   15038:             if (!isset($usestask[0])) {
                   15039:                 $usestask = array($usestask);
                   15040:             }
                   15041: 
                   15042:             foreach ($usestask as $taskdata) {
                   15043:                 if (isset($info['Uses Custom Tasks'])) {
                   15044:                     $info['Uses Custom Tasks'] .= "\n";
                   15045:                 } else {
                   15046:                     $info['Uses Custom Tasks'] = '';
                   15047:                 }
                   15048: 
                   15049:                 if (isset($taskdata['package'])) {
                   15050:                     $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
                   15051:                 } else {
                   15052:                     $taskpackage = $taskdata['uri'];
                   15053:                 }
                   15054:                 $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
                   15055:             }
                   15056:         }
                   15057: 
                   15058:         $deps = $obj->getDependencies();
                   15059:         $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
                   15060:         if (isset($deps['required']['php']['max'])) {
                   15061:             $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
                   15062:         } else {
                   15063:             $info['Required Dependencies'] .= "\n";
                   15064:         }
                   15065: 
                   15066:         if (isset($deps['required']['php']['exclude'])) {
                   15067:             if (!isset($info['Not Compatible with'])) {
                   15068:                 $info['Not Compatible with'] = '';
                   15069:             } else {
                   15070:                 $info['Not Compatible with'] .= "\n";
                   15071:             }
                   15072: 
                   15073:             if (is_array($deps['required']['php']['exclude'])) {
                   15074:                 $deps['required']['php']['exclude'] =
                   15075:                     implode(', ', $deps['required']['php']['exclude']);
                   15076:             }
                   15077:             $info['Not Compatible with'] .= "PHP versions\n  " .
                   15078:                 $deps['required']['php']['exclude'];
                   15079:         }
                   15080: 
                   15081:         $info['Required Dependencies'] .= 'PEAR installer version';
                   15082:         if (isset($deps['required']['pearinstaller']['max'])) {
                   15083:             $info['Required Dependencies'] .= 's ' .
                   15084:                 $deps['required']['pearinstaller']['min'] . '-' .
                   15085:                 $deps['required']['pearinstaller']['max'];
                   15086:         } else {
                   15087:             $info['Required Dependencies'] .= ' ' .
                   15088:                 $deps['required']['pearinstaller']['min'] . ' or newer';
                   15089:         }
                   15090: 
                   15091:         if (isset($deps['required']['pearinstaller']['exclude'])) {
                   15092:             if (!isset($info['Not Compatible with'])) {
                   15093:                 $info['Not Compatible with'] = '';
                   15094:             } else {
                   15095:                 $info['Not Compatible with'] .= "\n";
                   15096:             }
                   15097: 
                   15098:             if (is_array($deps['required']['pearinstaller']['exclude'])) {
                   15099:                 $deps['required']['pearinstaller']['exclude'] =
                   15100:                     implode(', ', $deps['required']['pearinstaller']['exclude']);
                   15101:             }
                   15102:             $info['Not Compatible with'] .= "PEAR installer\n  Versions " .
                   15103:                 $deps['required']['pearinstaller']['exclude'];
                   15104:         }
                   15105: 
                   15106:         foreach (array('Package', 'Extension') as $type) {
                   15107:             $index = strtolower($type);
                   15108:             if (isset($deps['required'][$index])) {
                   15109:                 if (isset($deps['required'][$index]['name'])) {
                   15110:                     $deps['required'][$index] = array($deps['required'][$index]);
                   15111:                 }
                   15112: 
                   15113:                 foreach ($deps['required'][$index] as $package) {
                   15114:                     if (isset($package['conflicts'])) {
                   15115:                         $infoindex = 'Not Compatible with';
                   15116:                         if (!isset($info['Not Compatible with'])) {
                   15117:                             $info['Not Compatible with'] = '';
                   15118:                         } else {
                   15119:                             $info['Not Compatible with'] .= "\n";
                   15120:                         }
                   15121:                     } else {
                   15122:                         $infoindex = 'Required Dependencies';
                   15123:                         $info[$infoindex] .= "\n";
                   15124:                     }
                   15125: 
                   15126:                     if ($index == 'extension') {
                   15127:                         $name = $package['name'];
                   15128:                     } else {
                   15129:                         if (isset($package['channel'])) {
                   15130:                             $name = $package['channel'] . '/' . $package['name'];
                   15131:                         } else {
                   15132:                             $name = '__uri/' . $package['name'] . ' (static URI)';
                   15133:                         }
                   15134:                     }
                   15135: 
                   15136:                     $info[$infoindex] .= "$type $name";
                   15137:                     if (isset($package['uri'])) {
                   15138:                         $info[$infoindex] .= "\n  Download URI: $package[uri]";
                   15139:                         continue;
                   15140:                     }
                   15141: 
                   15142:                     if (isset($package['max']) && isset($package['min'])) {
                   15143:                         $info[$infoindex] .= " \n  Versions " .
                   15144:                             $package['min'] . '-' . $package['max'];
                   15145:                     } elseif (isset($package['min'])) {
                   15146:                         $info[$infoindex] .= " \n  Version " .
                   15147:                             $package['min'] . ' or newer';
                   15148:                     } elseif (isset($package['max'])) {
                   15149:                         $info[$infoindex] .= " \n  Version " .
                   15150:                             $package['max'] . ' or older';
                   15151:                     }
                   15152: 
                   15153:                     if (isset($package['recommended'])) {
                   15154:                         $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                   15155:                     }
                   15156: 
                   15157:                     if (isset($package['exclude'])) {
                   15158:                         if (!isset($info['Not Compatible with'])) {
                   15159:                             $info['Not Compatible with'] = '';
                   15160:                         } else {
                   15161:                             $info['Not Compatible with'] .= "\n";
                   15162:                         }
                   15163: 
                   15164:                         if (is_array($package['exclude'])) {
                   15165:                             $package['exclude'] = implode(', ', $package['exclude']);
                   15166:                         }
                   15167: 
                   15168:                         $package['package'] = $package['name']; // for parsedPackageNameToString
                   15169:                          if (isset($package['conflicts'])) {
                   15170:                             $info['Not Compatible with'] .= '=> except ';
                   15171:                         }
                   15172:                        $info['Not Compatible with'] .= 'Package ' .
                   15173:                             $reg->parsedPackageNameToString($package, true);
                   15174:                         $info['Not Compatible with'] .= "\n  Versions " . $package['exclude'];
                   15175:                     }
                   15176:                 }
                   15177:             }
                   15178:         }
                   15179: 
                   15180:         if (isset($deps['required']['os'])) {
                   15181:             if (isset($deps['required']['os']['name'])) {
                   15182:                 $dep['required']['os']['name'] = array($dep['required']['os']['name']);
                   15183:             }
                   15184: 
                   15185:             foreach ($dep['required']['os'] as $os) {
                   15186:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                   15187:                     if (!isset($info['Not Compatible with'])) {
                   15188:                         $info['Not Compatible with'] = '';
                   15189:                     } else {
                   15190:                         $info['Not Compatible with'] .= "\n";
                   15191:                     }
                   15192:                     $info['Not Compatible with'] .= "$os[name] Operating System";
                   15193:                 } else {
                   15194:                     $info['Required Dependencies'] .= "\n";
                   15195:                     $info['Required Dependencies'] .= "$os[name] Operating System";
                   15196:                 }
                   15197:             }
                   15198:         }
                   15199: 
                   15200:         if (isset($deps['required']['arch'])) {
                   15201:             if (isset($deps['required']['arch']['pattern'])) {
                   15202:                 $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
                   15203:             }
                   15204: 
                   15205:             foreach ($dep['required']['arch'] as $os) {
                   15206:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                   15207:                     if (!isset($info['Not Compatible with'])) {
                   15208:                         $info['Not Compatible with'] = '';
                   15209:                     } else {
                   15210:                         $info['Not Compatible with'] .= "\n";
                   15211:                     }
                   15212:                     $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                   15213:                 } else {
                   15214:                     $info['Required Dependencies'] .= "\n";
                   15215:                     $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                   15216:                 }
                   15217:             }
                   15218:         }
                   15219: 
                   15220:         if (isset($deps['optional'])) {
                   15221:             foreach (array('Package', 'Extension') as $type) {
                   15222:                 $index = strtolower($type);
                   15223:                 if (isset($deps['optional'][$index])) {
                   15224:                     if (isset($deps['optional'][$index]['name'])) {
                   15225:                         $deps['optional'][$index] = array($deps['optional'][$index]);
                   15226:                     }
                   15227: 
                   15228:                     foreach ($deps['optional'][$index] as $package) {
                   15229:                         if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15230:                             $infoindex = 'Not Compatible with';
                   15231:                             if (!isset($info['Not Compatible with'])) {
                   15232:                                 $info['Not Compatible with'] = '';
                   15233:                             } else {
                   15234:                                 $info['Not Compatible with'] .= "\n";
                   15235:                             }
                   15236:                         } else {
                   15237:                             $infoindex = 'Optional Dependencies';
                   15238:                             if (!isset($info['Optional Dependencies'])) {
                   15239:                                 $info['Optional Dependencies'] = '';
                   15240:                             } else {
                   15241:                                 $info['Optional Dependencies'] .= "\n";
                   15242:                             }
                   15243:                         }
                   15244: 
                   15245:                         if ($index == 'extension') {
                   15246:                             $name = $package['name'];
                   15247:                         } else {
                   15248:                             if (isset($package['channel'])) {
                   15249:                                 $name = $package['channel'] . '/' . $package['name'];
                   15250:                             } else {
                   15251:                                 $name = '__uri/' . $package['name'] . ' (static URI)';
                   15252:                             }
                   15253:                         }
                   15254: 
                   15255:                         $info[$infoindex] .= "$type $name";
                   15256:                         if (isset($package['uri'])) {
                   15257:                             $info[$infoindex] .= "\n  Download URI: $package[uri]";
                   15258:                             continue;
                   15259:                         }
                   15260: 
                   15261:                         if ($infoindex == 'Not Compatible with') {
                   15262:                             // conflicts is only used to say that all versions conflict
                   15263:                             continue;
                   15264:                         }
                   15265: 
                   15266:                         if (isset($package['max']) && isset($package['min'])) {
                   15267:                             $info[$infoindex] .= " \n  Versions " .
                   15268:                                 $package['min'] . '-' . $package['max'];
                   15269:                         } elseif (isset($package['min'])) {
                   15270:                             $info[$infoindex] .= " \n  Version " .
                   15271:                                 $package['min'] . ' or newer';
                   15272:                         } elseif (isset($package['max'])) {
                   15273:                             $info[$infoindex] .= " \n  Version " .
                   15274:                                 $package['min'] . ' or older';
                   15275:                         }
                   15276: 
                   15277:                         if (isset($package['recommended'])) {
                   15278:                             $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                   15279:                         }
                   15280: 
                   15281:                         if (isset($package['exclude'])) {
                   15282:                             if (!isset($info['Not Compatible with'])) {
                   15283:                                 $info['Not Compatible with'] = '';
                   15284:                             } else {
                   15285:                                 $info['Not Compatible with'] .= "\n";
                   15286:                             }
                   15287: 
                   15288:                             if (is_array($package['exclude'])) {
                   15289:                                 $package['exclude'] = implode(', ', $package['exclude']);
                   15290:                             }
                   15291: 
                   15292:                             $info['Not Compatible with'] .= "Package $package\n  Versions " .
                   15293:                                 $package['exclude'];
                   15294:                         }
                   15295:                     }
                   15296:                 }
                   15297:             }
                   15298:         }
                   15299: 
                   15300:         if (isset($deps['group'])) {
                   15301:             if (!isset($deps['group'][0])) {
                   15302:                 $deps['group'] = array($deps['group']);
                   15303:             }
                   15304: 
                   15305:             foreach ($deps['group'] as $group) {
                   15306:                 $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
                   15307:                 $groupindex = $group['attribs']['name'] . ' Contents';
                   15308:                 $info[$groupindex] = '';
                   15309:                 foreach (array('Package', 'Extension') as $type) {
                   15310:                     $index = strtolower($type);
                   15311:                     if (isset($group[$index])) {
                   15312:                         if (isset($group[$index]['name'])) {
                   15313:                             $group[$index] = array($group[$index]);
                   15314:                         }
                   15315: 
                   15316:                         foreach ($group[$index] as $package) {
                   15317:                             if (!empty($info[$groupindex])) {
                   15318:                                 $info[$groupindex] .= "\n";
                   15319:                             }
                   15320: 
                   15321:                             if ($index == 'extension') {
                   15322:                                 $name = $package['name'];
                   15323:                             } else {
                   15324:                                 if (isset($package['channel'])) {
                   15325:                                     $name = $package['channel'] . '/' . $package['name'];
                   15326:                                 } else {
                   15327:                                     $name = '__uri/' . $package['name'] . ' (static URI)';
                   15328:                                 }
                   15329:                             }
                   15330: 
                   15331:                             if (isset($package['uri'])) {
                   15332:                                 if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15333:                                     $info[$groupindex] .= "Not Compatible with $type $name";
                   15334:                                 } else {
                   15335:                                     $info[$groupindex] .= "$type $name";
                   15336:                                 }
                   15337: 
                   15338:                                 $info[$groupindex] .= "\n  Download URI: $package[uri]";
                   15339:                                 continue;
                   15340:                             }
                   15341: 
                   15342:                             if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15343:                                 $info[$groupindex] .= "Not Compatible with $type $name";
                   15344:                                 continue;
                   15345:                             }
                   15346: 
                   15347:                             $info[$groupindex] .= "$type $name";
                   15348:                             if (isset($package['max']) && isset($package['min'])) {
                   15349:                                 $info[$groupindex] .= " \n  Versions " .
                   15350:                                     $package['min'] . '-' . $package['max'];
                   15351:                             } elseif (isset($package['min'])) {
                   15352:                                 $info[$groupindex] .= " \n  Version " .
                   15353:                                     $package['min'] . ' or newer';
                   15354:                             } elseif (isset($package['max'])) {
                   15355:                                 $info[$groupindex] .= " \n  Version " .
                   15356:                                     $package['min'] . ' or older';
                   15357:                             }
                   15358: 
                   15359:                             if (isset($package['recommended'])) {
                   15360:                                 $info[$groupindex] .= "\n  Recommended version: $package[recommended]";
                   15361:                             }
                   15362: 
                   15363:                             if (isset($package['exclude'])) {
                   15364:                                 if (!isset($info['Not Compatible with'])) {
                   15365:                                     $info['Not Compatible with'] = '';
                   15366:                                 } else {
                   15367:                                     $info[$groupindex] .= "Not Compatible with\n";
                   15368:                                 }
                   15369: 
                   15370:                                 if (is_array($package['exclude'])) {
                   15371:                                     $package['exclude'] = implode(', ', $package['exclude']);
                   15372:                                 }
                   15373:                                 $info[$groupindex] .= "  Package $package\n  Versions " .
                   15374:                                     $package['exclude'];
                   15375:                             }
                   15376:                         }
                   15377:                     }
                   15378:                 }
                   15379:             }
                   15380:         }
                   15381: 
                   15382:         if ($obj->getPackageType() == 'bundle') {
                   15383:             $info['Bundled Packages'] = '';
                   15384:             foreach ($obj->getBundledPackages() as $package) {
                   15385:                 if (!empty($info['Bundled Packages'])) {
                   15386:                     $info['Bundled Packages'] .= "\n";
                   15387:                 }
                   15388: 
                   15389:                 if (isset($package['uri'])) {
                   15390:                     $info['Bundled Packages'] .= '__uri/' . $package['name'];
                   15391:                     $info['Bundled Packages'] .= "\n  (URI: $package[uri]";
                   15392:                 } else {
                   15393:                     $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
                   15394:                 }
                   15395:             }
                   15396:         }
                   15397: 
                   15398:         $info['package.xml version'] = '2.0';
                   15399:         if ($installed) {
                   15400:             if ($obj->getLastModified()) {
                   15401:                 $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
                   15402:             }
                   15403: 
                   15404:             $v = $obj->getLastInstalledVersion();
                   15405:             $info['Previous Installed Version'] = $v ? $v : '- None -';
                   15406:         }
                   15407: 
                   15408:         foreach ($info as $key => $value) {
                   15409:             $data['data'][] = array($key, $value);
                   15410:         }
                   15411: 
                   15412:         $data['raw'] = $obj->getArray(); // no validation needed
                   15413:         $this->ui->outputData($data, 'package-info');
                   15414:     }
                   15415: }PEAR-1.9.4/PEAR/Command/Remote.xml0000644000076500000240000000635711605156760015333 0ustar  helgistaff<commands version="1.0">
                   15416:  <remote-info>
                   15417:   <summary>Information About Remote Packages</summary>
                   15418:   <function>doRemoteInfo</function>
                   15419:   <shortcut>ri</shortcut>
                   15420:   <options />
                   15421:   <doc>&lt;package&gt;
                   15422: Get details on a package from the server.</doc>
                   15423:  </remote-info>
                   15424:  <list-upgrades>
                   15425:   <summary>List Available Upgrades</summary>
                   15426:   <function>doListUpgrades</function>
                   15427:   <shortcut>lu</shortcut>
                   15428:   <options>
                   15429:    <channelinfo>
                   15430:     <shortopt>i</shortopt>
                   15431:     <doc>output fully channel-aware data, even on failure</doc>
                   15432:    </channelinfo>
                   15433:   </options>
                   15434:   <doc>[preferred_state]
                   15435: List releases on the server of packages you have installed where
                   15436: a newer version is available with the same release state (stable etc.)
                   15437: or the state passed as the second parameter.</doc>
                   15438:  </list-upgrades>
                   15439:  <remote-list>
                   15440:   <summary>List Remote Packages</summary>
                   15441:   <function>doRemoteList</function>
                   15442:   <shortcut>rl</shortcut>
                   15443:   <options>
                   15444:    <channel>
                   15445:     <shortopt>c</shortopt>
                   15446:     <doc>specify a channel other than the default channel</doc>
                   15447:     <arg>CHAN</arg>
                   15448:    </channel>
                   15449:   </options>
                   15450:   <doc>
                   15451: Lists the packages available on the configured server along with the
                   15452: latest stable release of each package.</doc>
                   15453:  </remote-list>
                   15454:  <search>
                   15455:   <summary>Search remote package database</summary>
                   15456:   <function>doSearch</function>
                   15457:   <shortcut>sp</shortcut>
                   15458:   <options>
                   15459:    <channel>
                   15460:     <shortopt>c</shortopt>
                   15461:     <doc>specify a channel other than the default channel</doc>
                   15462:     <arg>CHAN</arg>
                   15463:    </channel>
                   15464:    <allchannels>
                   15465:     <shortopt>a</shortopt>
                   15466:     <doc>search packages from all known channels</doc>
                   15467:    </allchannels>
                   15468:    <channelinfo>
                   15469:     <shortopt>i</shortopt>
                   15470:     <doc>output fully channel-aware data, even on failure</doc>
                   15471:    </channelinfo>
                   15472:   </options>
                   15473:   <doc>[packagename] [packageinfo]
                   15474: Lists all packages which match the search parameters.  The first
                   15475: parameter is a fragment of a packagename.  The default channel
                   15476: will be used unless explicitly overridden.  The second parameter
                   15477: will be used to match any portion of the summary/description</doc>
                   15478:  </search>
                   15479:  <list-all>
                   15480:   <summary>List All Packages</summary>
                   15481:   <function>doListAll</function>
                   15482:   <shortcut>la</shortcut>
                   15483:   <options>
                   15484:    <channel>
                   15485:     <shortopt>c</shortopt>
                   15486:     <doc>specify a channel other than the default channel</doc>
                   15487:     <arg>CHAN</arg>
                   15488:    </channel>
                   15489:    <channelinfo>
                   15490:     <shortopt>i</shortopt>
                   15491:     <doc>output fully channel-aware data, even on failure</doc>
                   15492:    </channelinfo>
                   15493:   </options>
                   15494:   <doc>
                   15495: Lists the packages available on the configured server along with the
                   15496: latest stable release of each package.</doc>
                   15497:  </list-all>
                   15498:  <download>
                   15499:   <summary>Download Package</summary>
                   15500:   <function>doDownload</function>
                   15501:   <shortcut>d</shortcut>
                   15502:   <options>
                   15503:    <nocompress>
                   15504:     <shortopt>Z</shortopt>
                   15505:     <doc>download an uncompressed (.tar) file</doc>
                   15506:    </nocompress>
                   15507:   </options>
                   15508:   <doc>&lt;package&gt;...
                   15509: Download package tarballs.  The files will be named as suggested by the
                   15510: server, for example if you download the DB package and the latest stable
                   15511: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
                   15512:  </download>
                   15513:  <clear-cache>
                   15514:   <summary>Clear Web Services Cache</summary>
                   15515:   <function>doClearCache</function>
                   15516:   <shortcut>cc</shortcut>
                   15517:   <options />
                   15518:   <doc>
                   15519: Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
                   15520: parameter.
                   15521: </doc>
                   15522:  </clear-cache>
                   15523: </commands>PEAR-1.9.4/PEAR/Command/Remote.php0000644000076500000240000007256611605156760015327 0ustar  helgistaff<?php
                   15524: /**
                   15525:  * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
                   15526:  * clear-cache commands)
                   15527:  *
                   15528:  * PHP versions 4 and 5
                   15529:  *
                   15530:  * @category   pear
                   15531:  * @package    PEAR
                   15532:  * @author     Stig Bakken <ssb@php.net>
                   15533:  * @author     Greg Beaver <cellog@php.net>
                   15534:  * @copyright  1997-2009 The Authors
                   15535:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   15536:  * @version    CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
                   15537:  * @link       http://pear.php.net/package/PEAR
                   15538:  * @since      File available since Release 0.1
                   15539:  */
                   15540: 
                   15541: /**
                   15542:  * base class
                   15543:  */
                   15544: require_once 'PEAR/Command/Common.php';
                   15545: require_once 'PEAR/REST.php';
                   15546: 
                   15547: /**
                   15548:  * PEAR commands for remote server querying
                   15549:  *
                   15550:  * @category   pear
                   15551:  * @package    PEAR
                   15552:  * @author     Stig Bakken <ssb@php.net>
                   15553:  * @author     Greg Beaver <cellog@php.net>
                   15554:  * @copyright  1997-2009 The Authors
                   15555:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   15556:  * @version    Release: 1.9.4
                   15557:  * @link       http://pear.php.net/package/PEAR
                   15558:  * @since      Class available since Release 0.1
                   15559:  */
                   15560: class PEAR_Command_Remote extends PEAR_Command_Common
                   15561: {
                   15562:     var $commands = array(
                   15563:         'remote-info' => array(
                   15564:             'summary' => 'Information About Remote Packages',
                   15565:             'function' => 'doRemoteInfo',
                   15566:             'shortcut' => 'ri',
                   15567:             'options' => array(),
                   15568:             'doc' => '<package>
                   15569: Get details on a package from the server.',
                   15570:             ),
                   15571:         'list-upgrades' => array(
                   15572:             'summary' => 'List Available Upgrades',
                   15573:             'function' => 'doListUpgrades',
                   15574:             'shortcut' => 'lu',
                   15575:             'options' => array(
                   15576:                 'channelinfo' => array(
                   15577:                     'shortopt' => 'i',
                   15578:                     'doc' => 'output fully channel-aware data, even on failure',
                   15579:                     ),
                   15580:             ),
                   15581:             'doc' => '[preferred_state]
                   15582: List releases on the server of packages you have installed where
                   15583: a newer version is available with the same release state (stable etc.)
                   15584: or the state passed as the second parameter.'
                   15585:             ),
                   15586:         'remote-list' => array(
                   15587:             'summary' => 'List Remote Packages',
                   15588:             'function' => 'doRemoteList',
                   15589:             'shortcut' => 'rl',
                   15590:             'options' => array(
                   15591:                 'channel' =>
                   15592:                     array(
                   15593:                     'shortopt' => 'c',
                   15594:                     'doc' => 'specify a channel other than the default channel',
                   15595:                     'arg' => 'CHAN',
                   15596:                     )
                   15597:                 ),
                   15598:             'doc' => '
                   15599: Lists the packages available on the configured server along with the
                   15600: latest stable release of each package.',
                   15601:             ),
                   15602:         'search' => array(
                   15603:             'summary' => 'Search remote package database',
                   15604:             'function' => 'doSearch',
                   15605:             'shortcut' => 'sp',
                   15606:             'options' => array(
                   15607:                 'channel' =>
                   15608:                     array(
                   15609:                     'shortopt' => 'c',
                   15610:                     'doc' => 'specify a channel other than the default channel',
                   15611:                     'arg' => 'CHAN',
                   15612:                     ),
                   15613:                 'allchannels' => array(
                   15614:                     'shortopt' => 'a',
                   15615:                     'doc' => 'search packages from all known channels',
                   15616:                     ),
                   15617:                 'channelinfo' => array(
                   15618:                     'shortopt' => 'i',
                   15619:                     'doc' => 'output fully channel-aware data, even on failure',
                   15620:                     ),
                   15621:                 ),
                   15622:             'doc' => '[packagename] [packageinfo]
                   15623: Lists all packages which match the search parameters.  The first
                   15624: parameter is a fragment of a packagename.  The default channel
                   15625: will be used unless explicitly overridden.  The second parameter
                   15626: will be used to match any portion of the summary/description',
                   15627:             ),
                   15628:         'list-all' => array(
                   15629:             'summary' => 'List All Packages',
                   15630:             'function' => 'doListAll',
                   15631:             'shortcut' => 'la',
                   15632:             'options' => array(
                   15633:                 'channel' =>
                   15634:                     array(
                   15635:                     'shortopt' => 'c',
                   15636:                     'doc' => 'specify a channel other than the default channel',
                   15637:                     'arg' => 'CHAN',
                   15638:                     ),
                   15639:                 'channelinfo' => array(
                   15640:                     'shortopt' => 'i',
                   15641:                     'doc' => 'output fully channel-aware data, even on failure',
                   15642:                     ),
                   15643:                 ),
                   15644:             'doc' => '
                   15645: Lists the packages available on the configured server along with the
                   15646: latest stable release of each package.',
                   15647:             ),
                   15648:         'download' => array(
                   15649:             'summary' => 'Download Package',
                   15650:             'function' => 'doDownload',
                   15651:             'shortcut' => 'd',
                   15652:             'options' => array(
                   15653:                 'nocompress' => array(
                   15654:                     'shortopt' => 'Z',
                   15655:                     'doc' => 'download an uncompressed (.tar) file',
                   15656:                     ),
                   15657:                 ),
                   15658:             'doc' => '<package>...
                   15659: Download package tarballs.  The files will be named as suggested by the
                   15660: server, for example if you download the DB package and the latest stable
                   15661: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
                   15662:             ),
                   15663:         'clear-cache' => array(
                   15664:             'summary' => 'Clear Web Services Cache',
                   15665:             'function' => 'doClearCache',
                   15666:             'shortcut' => 'cc',
                   15667:             'options' => array(),
                   15668:             'doc' => '
                   15669: Clear the REST cache. See also the cache_ttl configuration
                   15670: parameter.
                   15671: ',
                   15672:             ),
                   15673:         );
                   15674: 
                   15675:     /**
                   15676:      * PEAR_Command_Remote constructor.
                   15677:      *
                   15678:      * @access public
                   15679:      */
                   15680:     function PEAR_Command_Remote(&$ui, &$config)
                   15681:     {
                   15682:         parent::PEAR_Command_Common($ui, $config);
                   15683:     }
                   15684: 
                   15685:     function _checkChannelForStatus($channel, $chan)
                   15686:     {
                   15687:         if (PEAR::isError($chan)) {
                   15688:             $this->raiseError($chan);
                   15689:         }
                   15690:         if (!is_a($chan, 'PEAR_ChannelFile')) {
                   15691:             return $this->raiseError('Internal corruption error: invalid channel "' .
                   15692:                 $channel . '"');
                   15693:         }
                   15694:         $rest = new PEAR_REST($this->config);
                   15695:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   15696:         $mirror = $this->config->get('preferred_mirror', null,
                   15697:                                      $channel);
                   15698:         $a = $rest->downloadHttp('http://' . $channel .
                   15699:             '/channel.xml', $chan->lastModified());
                   15700:         PEAR::staticPopErrorHandling();
                   15701:         if (!PEAR::isError($a) && $a) {
                   15702:             $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
                   15703:                 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
                   15704:                 '" to update');
                   15705:         }
                   15706:     }
                   15707: 
                   15708:     function doRemoteInfo($command, $options, $params)
                   15709:     {
                   15710:         if (sizeof($params) != 1) {
                   15711:             return $this->raiseError("$command expects one param: the remote package name");
                   15712:         }
                   15713:         $savechannel = $channel = $this->config->get('default_channel');
                   15714:         $reg = &$this->config->getRegistry();
                   15715:         $package = $params[0];
                   15716:         $parsed = $reg->parsePackageName($package, $channel);
                   15717:         if (PEAR::isError($parsed)) {
                   15718:             return $this->raiseError('Invalid package name "' . $package . '"');
                   15719:         }
                   15720: 
                   15721:         $channel = $parsed['channel'];
                   15722:         $this->config->set('default_channel', $channel);
                   15723:         $chan = $reg->getChannel($channel);
                   15724:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   15725:             return $e;
                   15726:         }
                   15727: 
                   15728:         $mirror = $this->config->get('preferred_mirror');
                   15729:         if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
                   15730:             $rest = &$this->config->getREST('1.0', array());
                   15731:             $info = $rest->packageInfo($base, $parsed['package'], $channel);
                   15732:         }
                   15733: 
                   15734:         if (!isset($info)) {
                   15735:             return $this->raiseError('No supported protocol was found');
                   15736:         }
                   15737: 
                   15738:         if (PEAR::isError($info)) {
                   15739:             $this->config->set('default_channel', $savechannel);
                   15740:             return $this->raiseError($info);
                   15741:         }
                   15742: 
                   15743:         if (!isset($info['name'])) {
                   15744:             return $this->raiseError('No remote package "' . $package . '" was found');
                   15745:         }
                   15746: 
                   15747:         $installed = $reg->packageInfo($info['name'], null, $channel);
                   15748:         $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
                   15749:         if (is_array($info['installed'])) {
                   15750:             $info['installed'] = $info['installed']['release'];
                   15751:         }
                   15752: 
                   15753:         $this->ui->outputData($info, $command);
                   15754:         $this->config->set('default_channel', $savechannel);
                   15755: 
                   15756:         return true;
                   15757:     }
                   15758: 
                   15759:     function doRemoteList($command, $options, $params)
                   15760:     {
                   15761:         $savechannel = $channel = $this->config->get('default_channel');
                   15762:         $reg = &$this->config->getRegistry();
                   15763:         if (isset($options['channel'])) {
                   15764:             $channel = $options['channel'];
                   15765:             if (!$reg->channelExists($channel)) {
                   15766:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
                   15767:             }
                   15768: 
                   15769:             $this->config->set('default_channel', $channel);
                   15770:         }
                   15771: 
                   15772:         $chan = $reg->getChannel($channel);
                   15773:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   15774:             return $e;
                   15775:         }
                   15776: 
                   15777:         $list_options = false;
                   15778:         if ($this->config->get('preferred_state') == 'stable') {
                   15779:             $list_options = true;
                   15780:         }
                   15781: 
                   15782:         $available = array();
                   15783:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   15784:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
                   15785:         ) {
                   15786:             // use faster list-all if available
                   15787:             $rest = &$this->config->getREST('1.1', array());
                   15788:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
                   15789:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   15790:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   15791:             $rest = &$this->config->getREST('1.0', array());
                   15792:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
                   15793:         }
                   15794: 
                   15795:         if (PEAR::isError($available)) {
                   15796:             $this->config->set('default_channel', $savechannel);
                   15797:             return $this->raiseError($available);
                   15798:         }
                   15799: 
                   15800:         $i = $j = 0;
                   15801:         $data = array(
                   15802:             'caption' => 'Channel ' . $channel . ' Available packages:',
                   15803:             'border' => true,
                   15804:             'headline' => array('Package', 'Version'),
                   15805:             'channel' => $channel
                   15806:             );
                   15807: 
                   15808:         if (count($available) == 0) {
                   15809:             $data = '(no packages available yet)';
                   15810:         } else {
                   15811:             foreach ($available as $name => $info) {
                   15812:                 $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
                   15813:                 $data['data'][] = array($name, $version);
                   15814:             }
                   15815:         }
                   15816:         $this->ui->outputData($data, $command);
                   15817:         $this->config->set('default_channel', $savechannel);
                   15818:         return true;
                   15819:     }
                   15820: 
                   15821:     function doListAll($command, $options, $params)
                   15822:     {
                   15823:         $savechannel = $channel = $this->config->get('default_channel');
                   15824:         $reg = &$this->config->getRegistry();
                   15825:         if (isset($options['channel'])) {
                   15826:             $channel = $options['channel'];
                   15827:             if (!$reg->channelExists($channel)) {
                   15828:                 return $this->raiseError("Channel \"$channel\" does not exist");
                   15829:             }
                   15830: 
                   15831:             $this->config->set('default_channel', $channel);
                   15832:         }
                   15833: 
                   15834:         $list_options = false;
                   15835:         if ($this->config->get('preferred_state') == 'stable') {
                   15836:             $list_options = true;
                   15837:         }
                   15838: 
                   15839:         $chan = $reg->getChannel($channel);
                   15840:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   15841:             return $e;
                   15842:         }
                   15843: 
                   15844:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   15845:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
                   15846:             // use faster list-all if available
                   15847:             $rest = &$this->config->getREST('1.1', array());
                   15848:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
                   15849:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   15850:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   15851:             $rest = &$this->config->getREST('1.0', array());
                   15852:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
                   15853:         }
                   15854: 
                   15855:         if (PEAR::isError($available)) {
                   15856:             $this->config->set('default_channel', $savechannel);
                   15857:             return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
                   15858:         }
                   15859: 
                   15860:         $data = array(
                   15861:             'caption' => 'All packages [Channel ' . $channel . ']:',
                   15862:             'border' => true,
                   15863:             'headline' => array('Package', 'Latest', 'Local'),
                   15864:             'channel' => $channel,
                   15865:             );
                   15866: 
                   15867:         if (isset($options['channelinfo'])) {
                   15868:             // add full channelinfo
                   15869:             $data['caption'] = 'Channel ' . $channel . ' All packages:';
                   15870:             $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
                   15871:                 'Description', 'Dependencies');
                   15872:         }
                   15873:         $local_pkgs = $reg->listPackages($channel);
                   15874: 
                   15875:         foreach ($available as $name => $info) {
                   15876:             $installed = $reg->packageInfo($name, null, $channel);
                   15877:             if (is_array($installed['version'])) {
                   15878:                 $installed['version'] = $installed['version']['release'];
                   15879:             }
                   15880:             $desc = $info['summary'];
                   15881:             if (isset($params[$name])) {
                   15882:                 $desc .= "\n\n".$info['description'];
                   15883:             }
                   15884:             if (isset($options['mode']))
                   15885:             {
                   15886:                 if ($options['mode'] == 'installed' && !isset($installed['version'])) {
                   15887:                     continue;
                   15888:                 }
                   15889:                 if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
                   15890:                     continue;
                   15891:                 }
                   15892:                 if ($options['mode'] == 'upgrades'
                   15893:                       && (!isset($installed['version']) || version_compare($installed['version'],
                   15894:                       $info['stable'], '>='))) {
                   15895:                     continue;
                   15896:                 }
                   15897:             }
                   15898:             $pos = array_search(strtolower($name), $local_pkgs);
                   15899:             if ($pos !== false) {
                   15900:                 unset($local_pkgs[$pos]);
                   15901:             }
                   15902: 
                   15903:             if (isset($info['stable']) && !$info['stable']) {
                   15904:                 $info['stable'] = null;
                   15905:             }
                   15906: 
                   15907:             if (isset($options['channelinfo'])) {
                   15908:                 // add full channelinfo
                   15909:                 if ($info['stable'] === $info['unstable']) {
                   15910:                     $state = $info['state'];
                   15911:                 } else {
                   15912:                     $state = 'stable';
                   15913:                 }
                   15914:                 $latest = $info['stable'].' ('.$state.')';
                   15915:                 $local = '';
                   15916:                 if (isset($installed['version'])) {
                   15917:                     $inst_state = $reg->packageInfo($name, 'release_state', $channel);
                   15918:                     $local = $installed['version'].' ('.$inst_state.')';
                   15919:                 }
                   15920: 
                   15921:                 $packageinfo = array(
                   15922:                     $channel,
                   15923:                     $name,
                   15924:                     $latest,
                   15925:                     $local,
                   15926:                     isset($desc) ? $desc : null,
                   15927:                     isset($info['deps']) ? $info['deps'] : null,
                   15928:                 );
                   15929:             } else {
                   15930:                 $packageinfo = array(
                   15931:                     $reg->channelAlias($channel) . '/' . $name,
                   15932:                     isset($info['stable']) ? $info['stable'] : null,
                   15933:                     isset($installed['version']) ? $installed['version'] : null,
                   15934:                     isset($desc) ? $desc : null,
                   15935:                     isset($info['deps']) ? $info['deps'] : null,
                   15936:                 );
                   15937:             }
                   15938:             $data['data'][$info['category']][] = $packageinfo;
                   15939:         }
                   15940: 
                   15941:         if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
                   15942:             $this->config->set('default_channel', $savechannel);
                   15943:             $this->ui->outputData($data, $command);
                   15944:             return true;
                   15945:         }
                   15946: 
                   15947:         foreach ($local_pkgs as $name) {
                   15948:             $info = &$reg->getPackage($name, $channel);
                   15949:             $data['data']['Local'][] = array(
                   15950:                 $reg->channelAlias($channel) . '/' . $info->getPackage(),
                   15951:                 '',
                   15952:                 $info->getVersion(),
                   15953:                 $info->getSummary(),
                   15954:                 $info->getDeps()
                   15955:                 );
                   15956:         }
                   15957: 
                   15958:         $this->config->set('default_channel', $savechannel);
                   15959:         $this->ui->outputData($data, $command);
                   15960:         return true;
                   15961:     }
                   15962: 
                   15963:     function doSearch($command, $options, $params)
                   15964:     {
                   15965:         if ((!isset($params[0]) || empty($params[0]))
                   15966:             && (!isset($params[1]) || empty($params[1])))
                   15967:         {
                   15968:             return $this->raiseError('no valid search string supplied');
                   15969:         }
                   15970: 
                   15971:         $channelinfo = isset($options['channelinfo']);
                   15972:         $reg = &$this->config->getRegistry();
                   15973:         if (isset($options['allchannels'])) {
                   15974:             // search all channels
                   15975:             unset($options['allchannels']);
                   15976:             $channels = $reg->getChannels();
                   15977:             $errors = array();
                   15978:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   15979:             foreach ($channels as $channel) {
                   15980:                 if ($channel->getName() != '__uri') {
                   15981:                     $options['channel'] = $channel->getName();
                   15982:                     $ret = $this->doSearch($command, $options, $params);
                   15983:                     if (PEAR::isError($ret)) {
                   15984:                         $errors[] = $ret;
                   15985:                     }
                   15986:                 }
                   15987:             }
                   15988: 
                   15989:             PEAR::staticPopErrorHandling();
                   15990:             if (count($errors) !== 0) {
                   15991:                 // for now, only give first error
                   15992:                 return PEAR::raiseError($errors[0]);
                   15993:             }
                   15994: 
                   15995:             return true;
                   15996:         }
                   15997: 
                   15998:         $savechannel = $channel = $this->config->get('default_channel');
                   15999:         $package = strtolower($params[0]);
                   16000:         $summary = isset($params[1]) ? $params[1] : false;
                   16001:         if (isset($options['channel'])) {
                   16002:             $reg = &$this->config->getRegistry();
                   16003:             $channel = $options['channel'];
                   16004:             if (!$reg->channelExists($channel)) {
                   16005:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
                   16006:             }
                   16007: 
                   16008:             $this->config->set('default_channel', $channel);
                   16009:         }
                   16010: 
                   16011:         $chan = $reg->getChannel($channel);
                   16012:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16013:             return $e;
                   16014:         }
                   16015: 
                   16016:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16017:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   16018:             $rest = &$this->config->getREST('1.0', array());
                   16019:             $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
                   16020:         }
                   16021: 
                   16022:         if (PEAR::isError($available)) {
                   16023:             $this->config->set('default_channel', $savechannel);
                   16024:             return $this->raiseError($available);
                   16025:         }
                   16026: 
                   16027:         if (!$available && !$channelinfo) {
                   16028:             // clean exit when not found, no error !
                   16029:             $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
                   16030:             $this->ui->outputData($data);
                   16031:             $this->config->set('default_channel', $channel);
                   16032:             return true;
                   16033:         }
                   16034: 
                   16035:         if ($channelinfo) {
                   16036:             $data = array(
                   16037:                 'caption' => 'Matched packages, channel ' . $channel . ':',
                   16038:                 'border' => true,
                   16039:                 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
                   16040:                 'channel' => $channel
                   16041:                 );
                   16042:         } else {
                   16043:             $data = array(
                   16044:                 'caption' => 'Matched packages, channel ' . $channel . ':',
                   16045:                 'border' => true,
                   16046:                 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
                   16047:                 'channel' => $channel
                   16048:                 );
                   16049:         }
                   16050: 
                   16051:         if (!$available && $channelinfo) {
                   16052:             unset($data['headline']);
                   16053:             $data['data'] = 'No packages found that match pattern "' . $package . '".';
                   16054:             $available = array();
                   16055:         }
                   16056: 
                   16057:         foreach ($available as $name => $info) {
                   16058:             $installed = $reg->packageInfo($name, null, $channel);
                   16059:             $desc = $info['summary'];
                   16060:             if (isset($params[$name]))
                   16061:                 $desc .= "\n\n".$info['description'];
                   16062: 
                   16063:             if (!isset($info['stable']) || !$info['stable']) {
                   16064:                 $version_remote = 'none';
                   16065:             } else {
                   16066:                 if ($info['unstable']) {
                   16067:                     $version_remote = $info['unstable'];
                   16068:                 } else {
                   16069:                     $version_remote = $info['stable'];
                   16070:                 }
                   16071:                 $version_remote .= ' ('.$info['state'].')';
                   16072:             }
                   16073:             $version = is_array($installed['version']) ? $installed['version']['release'] :
                   16074:                 $installed['version'];
                   16075:             if ($channelinfo) {
                   16076:                 $packageinfo = array(
                   16077:                     $channel,
                   16078:                     $name,
                   16079:                     $version_remote,
                   16080:                     $version,
                   16081:                     $desc,
                   16082:                 );
                   16083:             } else {
                   16084:                 $packageinfo = array(
                   16085:                     $name,
                   16086:                     $version_remote,
                   16087:                     $version,
                   16088:                     $desc,
                   16089:                 );
                   16090:             }
                   16091:             $data['data'][$info['category']][] = $packageinfo;
                   16092:         }
                   16093: 
                   16094:         $this->ui->outputData($data, $command);
                   16095:         $this->config->set('default_channel', $channel);
                   16096:         return true;
                   16097:     }
                   16098: 
                   16099:     function &getDownloader($options)
                   16100:     {
                   16101:         if (!class_exists('PEAR_Downloader')) {
                   16102:             require_once 'PEAR/Downloader.php';
                   16103:         }
                   16104:         $a = &new PEAR_Downloader($this->ui, $options, $this->config);
                   16105:         return $a;
                   16106:     }
                   16107: 
                   16108:     function doDownload($command, $options, $params)
                   16109:     {
                   16110:         // make certain that dependencies are ignored
                   16111:         $options['downloadonly'] = 1;
                   16112: 
                   16113:         // eliminate error messages for preferred_state-related errors
                   16114:         /* TODO: Should be an option, but until now download does respect
                   16115:            prefered state */
                   16116:         /* $options['ignorepreferred_state'] = 1; */
                   16117:         // eliminate error messages for preferred_state-related errors
                   16118: 
                   16119:         $downloader = &$this->getDownloader($options);
                   16120:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16121:         $e = $downloader->setDownloadDir(getcwd());
                   16122:         PEAR::staticPopErrorHandling();
                   16123:         if (PEAR::isError($e)) {
                   16124:             return $this->raiseError('Current directory is not writeable, cannot download');
                   16125:         }
                   16126: 
                   16127:         $errors = array();
                   16128:         $downloaded = array();
                   16129:         $err = $downloader->download($params);
                   16130:         if (PEAR::isError($err)) {
                   16131:             return $err;
                   16132:         }
                   16133: 
                   16134:         $errors = $downloader->getErrorMsgs();
                   16135:         if (count($errors)) {
                   16136:             foreach ($errors as $error) {
                   16137:                 if ($error !== null) {
                   16138:                     $this->ui->outputData($error);
                   16139:                 }
                   16140:             }
                   16141: 
                   16142:             return $this->raiseError("$command failed");
                   16143:         }
                   16144: 
                   16145:         $downloaded = $downloader->getDownloadedPackages();
                   16146:         foreach ($downloaded as $pkg) {
                   16147:             $this->ui->outputData("File $pkg[file] downloaded", $command);
                   16148:         }
                   16149: 
                   16150:         return true;
                   16151:     }
                   16152: 
                   16153:     function downloadCallback($msg, $params = null)
                   16154:     {
                   16155:         if ($msg == 'done') {
                   16156:             $this->bytes_downloaded = $params;
                   16157:         }
                   16158:     }
                   16159: 
                   16160:     function doListUpgrades($command, $options, $params)
                   16161:     {
                   16162:         require_once 'PEAR/Common.php';
                   16163:         if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
                   16164:             return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
                   16165:         }
                   16166: 
                   16167:         $savechannel = $channel = $this->config->get('default_channel');
                   16168:         $reg = &$this->config->getRegistry();
                   16169:         foreach ($reg->listChannels() as $channel) {
                   16170:             $inst = array_flip($reg->listPackages($channel));
                   16171:             if (!count($inst)) {
                   16172:                 continue;
                   16173:             }
                   16174: 
                   16175:             if ($channel == '__uri') {
                   16176:                 continue;
                   16177:             }
                   16178: 
                   16179:             $this->config->set('default_channel', $channel);
                   16180:             $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
                   16181: 
                   16182:             $caption = $channel . ' Available Upgrades';
                   16183:             $chan = $reg->getChannel($channel);
                   16184:             if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16185:                 return $e;
                   16186:             }
                   16187: 
                   16188:             $latest = array();
                   16189:             $base2  = false;
                   16190:             $preferred_mirror = $this->config->get('preferred_mirror');
                   16191:             if ($chan->supportsREST($preferred_mirror) &&
                   16192:                 (
                   16193:                    //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                   16194:                    ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   16195:                 )
                   16196: 
                   16197:             ) {
                   16198:                 if ($base2) {
                   16199:                     $rest = &$this->config->getREST('1.4', array());
                   16200:                     $base = $base2;
                   16201:                 } else {
                   16202:                     $rest = &$this->config->getREST('1.0', array());
                   16203:                 }
                   16204: 
                   16205:                 if (empty($state) || $state == 'any') {
                   16206:                     $state = false;
                   16207:                 } else {
                   16208:                     $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
                   16209:                 }
                   16210: 
                   16211:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16212:                 $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
                   16213:                 PEAR::staticPopErrorHandling();
                   16214:             }
                   16215: 
                   16216:             if (PEAR::isError($latest)) {
                   16217:                 $this->ui->outputData($latest->getMessage());
                   16218:                 continue;
                   16219:             }
                   16220: 
                   16221:             $caption .= ':';
                   16222:             if (PEAR::isError($latest)) {
                   16223:                 $this->config->set('default_channel', $savechannel);
                   16224:                 return $latest;
                   16225:             }
                   16226: 
                   16227:             $data = array(
                   16228:                 'caption' => $caption,
                   16229:                 'border' => 1,
                   16230:                 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
                   16231:                 'channel' => $channel
                   16232:                 );
                   16233: 
                   16234:             foreach ((array)$latest as $pkg => $info) {
                   16235:                 $package = strtolower($pkg);
                   16236:                 if (!isset($inst[$package])) {
                   16237:                     // skip packages we don't have installed
                   16238:                     continue;
                   16239:                 }
                   16240: 
                   16241:                 extract($info);
                   16242:                 $inst_version = $reg->packageInfo($package, 'version', $channel);
                   16243:                 $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                   16244:                 if (version_compare("$version", "$inst_version", "le")) {
                   16245:                     // installed version is up-to-date
                   16246:                     continue;
                   16247:                 }
                   16248: 
                   16249:                 if ($filesize >= 20480) {
                   16250:                     $filesize += 1024 - ($filesize % 1024);
                   16251:                     $fs = sprintf("%dkB", $filesize / 1024);
                   16252:                 } elseif ($filesize > 0) {
                   16253:                     $filesize += 103 - ($filesize % 103);
                   16254:                     $fs = sprintf("%.1fkB", $filesize / 1024.0);
                   16255:                 } else {
                   16256:                     $fs = "  -"; // XXX center instead
                   16257:                 }
                   16258: 
                   16259:                 $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
                   16260:             }
                   16261: 
                   16262:             if (isset($options['channelinfo'])) {
                   16263:                 if (empty($data['data'])) {
                   16264:                     unset($data['headline']);
                   16265:                     if (count($inst) == 0) {
                   16266:                         $data['data'] = '(no packages installed)';
                   16267:                     } else {
                   16268:                         $data['data'] = '(no upgrades available)';
                   16269:                     }
                   16270:                 }
                   16271:                 $this->ui->outputData($data, $command);
                   16272:             } else {
                   16273:                 if (empty($data['data'])) {
                   16274:                     $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
                   16275:                 } else {
                   16276:                     $this->ui->outputData($data, $command);
                   16277:                 }
                   16278:             }
                   16279:         }
                   16280: 
                   16281:         $this->config->set('default_channel', $savechannel);
                   16282:         return true;
                   16283:     }
                   16284: 
                   16285:     function doClearCache($command, $options, $params)
                   16286:     {
                   16287:         $cache_dir = $this->config->get('cache_dir');
                   16288:         $verbose   = $this->config->get('verbose');
                   16289:         $output = '';
                   16290:         if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
                   16291:             return $this->raiseError("$cache_dir does not exist or is not a directory");
                   16292:         }
                   16293: 
                   16294:         if (!($dp = @opendir($cache_dir))) {
                   16295:             return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
                   16296:         }
                   16297: 
                   16298:         if ($verbose >= 1) {
                   16299:             $output .= "reading directory $cache_dir\n";
                   16300:         }
                   16301: 
                   16302:         $num = 0;
                   16303:         while ($ent = readdir($dp)) {
                   16304:             if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
                   16305:                 $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
                   16306:                 if (file_exists($path)) {
                   16307:                     $ok = @unlink($path);
                   16308:                 } else {
                   16309:                     $ok = false;
                   16310:                     $php_errormsg = '';
                   16311:                 }
                   16312: 
                   16313:                 if ($ok) {
                   16314:                     if ($verbose >= 2) {
                   16315:                         $output .= "deleted $path\n";
                   16316:                     }
                   16317:                     $num++;
                   16318:                 } elseif ($verbose >= 1) {
                   16319:                     $output .= "failed to delete $path $php_errormsg\n";
                   16320:                 }
                   16321:             }
                   16322:         }
                   16323: 
                   16324:         closedir($dp);
                   16325:         if ($verbose >= 1) {
                   16326:             $output .= "$num cache entries cleared\n";
                   16327:         }
                   16328: 
                   16329:         $this->ui->outputData(rtrim($output), $command);
                   16330:         return $num;
                   16331:     }
                   16332: }PEAR-1.9.4/PEAR/Command/Test.xml0000644000076500000240000000315111605156760015004 0ustar  helgistaff<commands version="1.0">
                   16333:  <run-tests>
                   16334:   <summary>Run Regression Tests</summary>
                   16335:   <function>doRunTests</function>
                   16336:   <shortcut>rt</shortcut>
                   16337:   <options>
                   16338:    <recur>
                   16339:     <shortopt>r</shortopt>
                   16340:     <doc>Run tests in child directories, recursively.  4 dirs deep maximum</doc>
                   16341:    </recur>
                   16342:    <ini>
                   16343:     <shortopt>i</shortopt>
                   16344:     <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
                   16345:     <arg>SETTINGS</arg>
                   16346:    </ini>
                   16347:    <realtimelog>
                   16348:     <shortopt>l</shortopt>
                   16349:     <doc>Log test runs/results as they are run</doc>
                   16350:    </realtimelog>
                   16351:    <quiet>
                   16352:     <shortopt>q</shortopt>
                   16353:     <doc>Only display detail for failed tests</doc>
                   16354:    </quiet>
                   16355:    <simple>
                   16356:     <shortopt>s</shortopt>
                   16357:     <doc>Display simple output for all tests</doc>
                   16358:    </simple>
                   16359:    <package>
                   16360:     <shortopt>p</shortopt>
                   16361:     <doc>Treat parameters as installed packages from which to run tests</doc>
                   16362:    </package>
                   16363:    <phpunit>
                   16364:     <shortopt>u</shortopt>
                   16365:     <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
                   16366: If none is found, all .phpt tests will be tried instead.</doc>
                   16367:    </phpunit>
                   16368:    <tapoutput>
                   16369:     <shortopt>t</shortopt>
                   16370:     <doc>Output run-tests.log in TAP-compliant format</doc>
                   16371:    </tapoutput>
                   16372:    <cgi>
                   16373:     <shortopt>c</shortopt>
                   16374:     <doc>CGI php executable (needed for tests with POST/GET section)</doc>
                   16375:     <arg>PHPCGI</arg>
                   16376:    </cgi>
                   16377:    <coverage>
                   16378:     <shortopt>x</shortopt>
                   16379:     <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
                   16380:    </coverage>
                   16381:   </options>
                   16382:   <doc>[testfile|dir ...]
                   16383: Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
                   16384:  </run-tests>
                   16385: </commands>PEAR-1.9.4/PEAR/Command/Test.php0000644000076500000240000002726611605156760015010 0ustar  helgistaff<?php
                   16386: /**
                   16387:  * PEAR_Command_Test (run-tests)
                   16388:  *
                   16389:  * PHP versions 4 and 5
                   16390:  *
                   16391:  * @category   pear
                   16392:  * @package    PEAR
                   16393:  * @author     Stig Bakken <ssb@php.net>
                   16394:  * @author     Martin Jansen <mj@php.net>
                   16395:  * @author     Greg Beaver <cellog@php.net>
                   16396:  * @copyright  1997-2009 The Authors
                   16397:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16398:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
                   16399:  * @link       http://pear.php.net/package/PEAR
                   16400:  * @since      File available since Release 0.1
                   16401:  */
                   16402: 
                   16403: /**
                   16404:  * base class
                   16405:  */
                   16406: require_once 'PEAR/Command/Common.php';
                   16407: 
                   16408: /**
                   16409:  * PEAR commands for login/logout
                   16410:  *
                   16411:  * @category   pear
                   16412:  * @package    PEAR
                   16413:  * @author     Stig Bakken <ssb@php.net>
                   16414:  * @author     Martin Jansen <mj@php.net>
                   16415:  * @author     Greg Beaver <cellog@php.net>
                   16416:  * @copyright  1997-2009 The Authors
                   16417:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16418:  * @version    Release: 1.9.4
                   16419:  * @link       http://pear.php.net/package/PEAR
                   16420:  * @since      Class available since Release 0.1
                   16421:  */
                   16422: 
                   16423: class PEAR_Command_Test extends PEAR_Command_Common
                   16424: {
                   16425:     var $commands = array(
                   16426:         'run-tests' => array(
                   16427:             'summary' => 'Run Regression Tests',
                   16428:             'function' => 'doRunTests',
                   16429:             'shortcut' => 'rt',
                   16430:             'options' => array(
                   16431:                 'recur' => array(
                   16432:                     'shortopt' => 'r',
                   16433:                     'doc' => 'Run tests in child directories, recursively.  4 dirs deep maximum',
                   16434:                 ),
                   16435:                 'ini' => array(
                   16436:                     'shortopt' => 'i',
                   16437:                     'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
                   16438:                     'arg' => 'SETTINGS'
                   16439:                 ),
                   16440:                 'realtimelog' => array(
                   16441:                     'shortopt' => 'l',
                   16442:                     'doc' => 'Log test runs/results as they are run',
                   16443:                 ),
                   16444:                 'quiet' => array(
                   16445:                     'shortopt' => 'q',
                   16446:                     'doc' => 'Only display detail for failed tests',
                   16447:                 ),
                   16448:                 'simple' => array(
                   16449:                     'shortopt' => 's',
                   16450:                     'doc' => 'Display simple output for all tests',
                   16451:                 ),
                   16452:                 'package' => array(
                   16453:                     'shortopt' => 'p',
                   16454:                     'doc' => 'Treat parameters as installed packages from which to run tests',
                   16455:                 ),
                   16456:                 'phpunit' => array(
                   16457:                     'shortopt' => 'u',
                   16458:                     'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
                   16459: If none is found, all .phpt tests will be tried instead.',
                   16460:                 ),
                   16461:                 'tapoutput' => array(
                   16462:                     'shortopt' => 't',
                   16463:                     'doc' => 'Output run-tests.log in TAP-compliant format',
                   16464:                 ),
                   16465:                 'cgi' => array(
                   16466:                     'shortopt' => 'c',
                   16467:                     'doc' => 'CGI php executable (needed for tests with POST/GET section)',
                   16468:                     'arg' => 'PHPCGI',
                   16469:                 ),
                   16470:                 'coverage' => array(
                   16471:                     'shortopt' => 'x',
                   16472:                     'doc'      => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
                   16473:                 ),
                   16474:             ),
                   16475:             'doc' => '[testfile|dir ...]
                   16476: Run regression tests with PHP\'s regression testing script (run-tests.php).',
                   16477:             ),
                   16478:         );
                   16479: 
                   16480:     var $output;
                   16481: 
                   16482:     /**
                   16483:      * PEAR_Command_Test constructor.
                   16484:      *
                   16485:      * @access public
                   16486:      */
                   16487:     function PEAR_Command_Test(&$ui, &$config)
                   16488:     {
                   16489:         parent::PEAR_Command_Common($ui, $config);
                   16490:     }
                   16491: 
                   16492:     function doRunTests($command, $options, $params)
                   16493:     {
                   16494:         if (isset($options['phpunit']) && isset($options['tapoutput'])) {
                   16495:             return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
                   16496:         }
                   16497: 
                   16498:         require_once 'PEAR/Common.php';
                   16499:         require_once 'System.php';
                   16500:         $log = new PEAR_Common;
                   16501:         $log->ui = &$this->ui; // slightly hacky, but it will work
                   16502:         $tests = array();
                   16503:         $depth = isset($options['recur']) ? 14 : 1;
                   16504: 
                   16505:         if (!count($params)) {
                   16506:             $params[] = '.';
                   16507:         }
                   16508: 
                   16509:         if (isset($options['package'])) {
                   16510:             $oldparams = $params;
                   16511:             $params = array();
                   16512:             $reg = &$this->config->getRegistry();
                   16513:             foreach ($oldparams as $param) {
                   16514:                 $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
                   16515:                 if (PEAR::isError($pname)) {
                   16516:                     return $this->raiseError($pname);
                   16517:                 }
                   16518: 
                   16519:                 $package = &$reg->getPackage($pname['package'], $pname['channel']);
                   16520:                 if (!$package) {
                   16521:                     return PEAR::raiseError('Unknown package "' .
                   16522:                         $reg->parsedPackageNameToString($pname) . '"');
                   16523:                 }
                   16524: 
                   16525:                 $filelist = $package->getFilelist();
                   16526:                 foreach ($filelist as $name => $atts) {
                   16527:                     if (isset($atts['role']) && $atts['role'] != 'test') {
                   16528:                         continue;
                   16529:                     }
                   16530: 
                   16531:                     if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
                   16532:                         $params[] = $atts['installed_as'];
                   16533:                         continue;
                   16534:                     } elseif (!preg_match('/\.phpt\\z/', $name)) {
                   16535:                         continue;
                   16536:                     }
                   16537:                     $params[] = $atts['installed_as'];
                   16538:                 }
                   16539:             }
                   16540:         }
                   16541: 
                   16542:         foreach ($params as $p) {
                   16543:             if (is_dir($p)) {
                   16544:                 if (isset($options['phpunit'])) {
                   16545:                     $dir = System::find(array($p, '-type', 'f',
                   16546:                                                 '-maxdepth', $depth,
                   16547:                                                 '-name', 'AllTests.php'));
                   16548:                     if (count($dir)) {
                   16549:                         foreach ($dir as $p) {
                   16550:                             $p = realpath($p);
                   16551:                             if (!count($tests) ||
                   16552:                                   (count($tests) && strlen($p) < strlen($tests[0]))) {
                   16553:                                 // this is in a higher-level directory, use this one instead.
                   16554:                                 $tests = array($p);
                   16555:                             }
                   16556:                         }
                   16557:                     }
                   16558:                     continue;
                   16559:                 }
                   16560: 
                   16561:                 $args  = array($p, '-type', 'f', '-name', '*.phpt');
                   16562:             } else {
                   16563:                 if (isset($options['phpunit'])) {
                   16564:                     if (preg_match('/AllTests\.php\\z/i', $p)) {
                   16565:                         $p = realpath($p);
                   16566:                         if (!count($tests) ||
                   16567:                               (count($tests) && strlen($p) < strlen($tests[0]))) {
                   16568:                             // this is in a higher-level directory, use this one instead.
                   16569:                             $tests = array($p);
                   16570:                         }
                   16571:                     }
                   16572:                     continue;
                   16573:                 }
                   16574: 
                   16575:                 if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
                   16576:                     $tests[] = $p;
                   16577:                     continue;
                   16578:                 }
                   16579: 
                   16580:                 if (!preg_match('/\.phpt\\z/', $p)) {
                   16581:                     $p .= '.phpt';
                   16582:                 }
                   16583: 
                   16584:                 $args  = array(dirname($p), '-type', 'f', '-name', $p);
                   16585:             }
                   16586: 
                   16587:             if (!isset($options['recur'])) {
                   16588:                 $args[] = '-maxdepth';
                   16589:                 $args[] = 1;
                   16590:             }
                   16591: 
                   16592:             $dir   = System::find($args);
                   16593:             $tests = array_merge($tests, $dir);
                   16594:         }
                   16595: 
                   16596:         $ini_settings = '';
                   16597:         if (isset($options['ini'])) {
                   16598:             $ini_settings .= $options['ini'];
                   16599:         }
                   16600: 
                   16601:         if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
                   16602:             $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
                   16603:         }
                   16604: 
                   16605:         if ($ini_settings) {
                   16606:             $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
                   16607:         }
                   16608: 
                   16609:         $skipped = $passed = $failed = array();
                   16610:         $tests_count = count($tests);
                   16611:         $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
                   16612:         $start = time();
                   16613:         if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
                   16614:             unlink('run-tests.log');
                   16615:         }
                   16616: 
                   16617:         if (isset($options['tapoutput'])) {
                   16618:             $tap = '1..' . $tests_count . "\n";
                   16619:         }
                   16620: 
                   16621:         require_once 'PEAR/RunTest.php';
                   16622:         $run = new PEAR_RunTest($log, $options);
                   16623:         $run->tests_count = $tests_count;
                   16624: 
                   16625:         if (isset($options['coverage']) && extension_loaded('xdebug')){
                   16626:             $run->xdebug_loaded = true;
                   16627:         } else {
                   16628:             $run->xdebug_loaded = false;
                   16629:         }
                   16630: 
                   16631:         $j = $i = 1;
                   16632:         foreach ($tests as $t) {
                   16633:             if (isset($options['realtimelog'])) {
                   16634:                 $fp = @fopen('run-tests.log', 'a');
                   16635:                 if ($fp) {
                   16636:                     fwrite($fp, "Running test [$i / $tests_count] $t...");
                   16637:                     fclose($fp);
                   16638:                 }
                   16639:             }
                   16640:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16641:             if (isset($options['phpunit'])) {
                   16642:                 $result = $run->runPHPUnit($t, $ini_settings);
                   16643:             } else {
                   16644:                 $result = $run->run($t, $ini_settings, $j);
                   16645:             }
                   16646:             PEAR::staticPopErrorHandling();
                   16647:             if (PEAR::isError($result)) {
                   16648:                 $this->ui->log($result->getMessage());
                   16649:                 continue;
                   16650:             }
                   16651: 
                   16652:             if (isset($options['tapoutput'])) {
                   16653:                 $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
                   16654:                 continue;
                   16655:             }
                   16656: 
                   16657:             if (isset($options['realtimelog'])) {
                   16658:                 $fp = @fopen('run-tests.log', 'a');
                   16659:                 if ($fp) {
                   16660:                     fwrite($fp, "$result\n");
                   16661:                     fclose($fp);
                   16662:                 }
                   16663:             }
                   16664: 
                   16665:             if ($result == 'FAILED') {
                   16666:                 $failed[] = $t;
                   16667:             }
                   16668:             if ($result == 'PASSED') {
                   16669:                 $passed[] = $t;
                   16670:             }
                   16671:             if ($result == 'SKIPPED') {
                   16672:                 $skipped[] = $t;
                   16673:             }
                   16674: 
                   16675:             $j++;
                   16676:         }
                   16677: 
                   16678:         $total = date('i:s', time() - $start);
                   16679:         if (isset($options['tapoutput'])) {
                   16680:             $fp = @fopen('run-tests.log', 'w');
                   16681:             if ($fp) {
                   16682:                 fwrite($fp, $tap, strlen($tap));
                   16683:                 fclose($fp);
                   16684:                 $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
                   16685:                     '"', $command);
                   16686:             }
                   16687:         } else {
                   16688:             if (count($failed)) {
                   16689:                 $output = "TOTAL TIME: $total\n";
                   16690:                 $output .= count($passed) . " PASSED TESTS\n";
                   16691:                 $output .= count($skipped) . " SKIPPED TESTS\n";
                   16692:                 $output .= count($failed) . " FAILED TESTS:\n";
                   16693:                 foreach ($failed as $failure) {
                   16694:                     $output .= $failure . "\n";
                   16695:                 }
                   16696: 
                   16697:                 $mode = isset($options['realtimelog']) ? 'a' : 'w';
                   16698:                 $fp   = @fopen('run-tests.log', $mode);
                   16699: 
                   16700:                 if ($fp) {
                   16701:                     fwrite($fp, $output, strlen($output));
                   16702:                     fclose($fp);
                   16703:                     $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
                   16704:                 }
                   16705:             } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
                   16706:                 @unlink('run-tests.log');
                   16707:             }
                   16708:         }
                   16709:         $this->ui->outputData('TOTAL TIME: ' . $total);
                   16710:         $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
                   16711:         $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
                   16712:         if (count($failed)) {
                   16713:             $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
                   16714:             foreach ($failed as $failure) {
                   16715:                 $this->ui->outputData($failure, $command);
                   16716:             }
                   16717:         }
                   16718: 
                   16719:         return true;
                   16720:     }
                   16721: }PEAR-1.9.4/PEAR/Downloader/Package.php0000644000076500000240000022464611605156760016145 0ustar  helgistaff<?php
                   16722: /**
                   16723:  * PEAR_Downloader_Package
                   16724:  *
                   16725:  * PHP versions 4 and 5
                   16726:  *
                   16727:  * @category   pear
                   16728:  * @package    PEAR
                   16729:  * @author     Greg Beaver <cellog@php.net>
                   16730:  * @copyright  1997-2009 The Authors
                   16731:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16732:  * @version    CVS: $Id: Package.php 313023 2011-07-06 19:17:11Z dufuz $
                   16733:  * @link       http://pear.php.net/package/PEAR
                   16734:  * @since      File available since Release 1.4.0a1
                   16735:  */
                   16736: 
                   16737: /**
                   16738:  * Error code when parameter initialization fails because no releases
                   16739:  * exist within preferred_state, but releases do exist
                   16740:  */
                   16741: define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
                   16742: /**
                   16743:  * Error code when parameter initialization fails because no releases
                   16744:  * exist that will work with the existing PHP version
                   16745:  */
                   16746: define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
                   16747: 
                   16748: /**
                   16749:  * Coordinates download parameters and manages their dependencies
                   16750:  * prior to downloading them.
                   16751:  *
                   16752:  * Input can come from three sources:
                   16753:  *
                   16754:  * - local files (archives or package.xml)
                   16755:  * - remote files (downloadable urls)
                   16756:  * - abstract package names
                   16757:  *
                   16758:  * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
                   16759:  * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
                   16760:  * format returned of dependencies is slightly different from that used in package.xml.
                   16761:  *
                   16762:  * This class hides the differences between these elements, and makes automatic
                   16763:  * dependency resolution a piece of cake.  It also manages conflicts when
                   16764:  * two classes depend on incompatible dependencies, or differing versions of the same
                   16765:  * package dependency.  In addition, download will not be attempted if the php version is
                   16766:  * not supported, PEAR installer version is not supported, or non-PECL extensions are not
                   16767:  * installed.
                   16768:  * @category   pear
                   16769:  * @package    PEAR
                   16770:  * @author     Greg Beaver <cellog@php.net>
                   16771:  * @copyright  1997-2009 The Authors
                   16772:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16773:  * @version    Release: 1.9.4
                   16774:  * @link       http://pear.php.net/package/PEAR
                   16775:  * @since      Class available since Release 1.4.0a1
                   16776:  */
                   16777: class PEAR_Downloader_Package
                   16778: {
                   16779:     /**
                   16780:      * @var PEAR_Downloader
                   16781:      */
                   16782:     var $_downloader;
                   16783:     /**
                   16784:      * @var PEAR_Config
                   16785:      */
                   16786:     var $_config;
                   16787:     /**
                   16788:      * @var PEAR_Registry
                   16789:      */
                   16790:     var $_registry;
                   16791:     /**
                   16792:      * Used to implement packagingroot properly
                   16793:      * @var PEAR_Registry
                   16794:      */
                   16795:     var $_installRegistry;
                   16796:     /**
                   16797:      * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
                   16798:      */
                   16799:     var $_packagefile;
                   16800:     /**
                   16801:      * @var array
                   16802:      */
                   16803:     var $_parsedname;
                   16804:     /**
                   16805:      * @var array
                   16806:      */
                   16807:     var $_downloadURL;
                   16808:     /**
                   16809:      * @var array
                   16810:      */
                   16811:     var $_downloadDeps = array();
                   16812:     /**
                   16813:      * @var boolean
                   16814:      */
                   16815:     var $_valid = false;
                   16816:     /**
                   16817:      * @var boolean
                   16818:      */
                   16819:     var $_analyzed = false;
                   16820:     /**
                   16821:      * if this or a parent package was invoked with Package-state, this is set to the
                   16822:      * state variable.
                   16823:      *
                   16824:      * This allows temporary reassignment of preferred_state for a parent package and all of
                   16825:      * its dependencies.
                   16826:      * @var string|false
                   16827:      */
                   16828:     var $_explicitState = false;
                   16829:     /**
                   16830:      * If this package is invoked with Package#group, this variable will be true
                   16831:      */
                   16832:     var $_explicitGroup = false;
                   16833:     /**
                   16834:      * Package type local|url
                   16835:      * @var string
                   16836:      */
                   16837:     var $_type;
                   16838:     /**
                   16839:      * Contents of package.xml, if downloaded from a remote channel
                   16840:      * @var string|false
                   16841:      * @access private
                   16842:      */
                   16843:     var $_rawpackagefile;
                   16844:     /**
                   16845:      * @var boolean
                   16846:      * @access private
                   16847:      */
                   16848:     var $_validated = false;
                   16849: 
                   16850:     /**
                   16851:      * @param PEAR_Downloader
                   16852:      */
                   16853:     function PEAR_Downloader_Package(&$downloader)
                   16854:     {
                   16855:         $this->_downloader = &$downloader;
                   16856:         $this->_config = &$this->_downloader->config;
                   16857:         $this->_registry = &$this->_config->getRegistry();
                   16858:         $options = $downloader->getOptions();
                   16859:         if (isset($options['packagingroot'])) {
                   16860:             $this->_config->setInstallRoot($options['packagingroot']);
                   16861:             $this->_installRegistry = &$this->_config->getRegistry();
                   16862:             $this->_config->setInstallRoot(false);
                   16863:         } else {
                   16864:             $this->_installRegistry = &$this->_registry;
                   16865:         }
                   16866:         $this->_valid = $this->_analyzed = false;
                   16867:     }
                   16868: 
                   16869:     /**
                   16870:      * Parse the input and determine whether this is a local file, a remote uri, or an
                   16871:      * abstract package name.
                   16872:      *
                   16873:      * This is the heart of the PEAR_Downloader_Package(), and is used in
                   16874:      * {@link PEAR_Downloader::download()}
                   16875:      * @param string
                   16876:      * @return bool|PEAR_Error
                   16877:      */
                   16878:     function initialize($param)
                   16879:     {
                   16880:         $origErr = $this->_fromFile($param);
                   16881:         if ($this->_valid) {
                   16882:             return true;
                   16883:         }
                   16884: 
                   16885:         $options = $this->_downloader->getOptions();
                   16886:         if (isset($options['offline'])) {
                   16887:             if (PEAR::isError($origErr) && !isset($options['soft'])) {
                   16888:                 foreach ($origErr->getUserInfo() as $userInfo) {
                   16889:                     if (isset($userInfo['message'])) {
                   16890:                         $this->_downloader->log(0, $userInfo['message']);
                   16891:                     }
                   16892:                 }
                   16893: 
                   16894:                 $this->_downloader->log(0, $origErr->getMessage());
                   16895:             }
                   16896: 
                   16897:             return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
                   16898:         }
                   16899: 
                   16900:         $err = $this->_fromUrl($param);
                   16901:         if (PEAR::isError($err) || !$this->_valid) {
                   16902:             if ($this->_type == 'url') {
                   16903:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   16904:                     $this->_downloader->log(0, $err->getMessage());
                   16905:                 }
                   16906: 
                   16907:                 return PEAR::raiseError("Invalid or missing remote package file");
                   16908:             }
                   16909: 
                   16910:             $err = $this->_fromString($param);
                   16911:             if (PEAR::isError($err) || !$this->_valid) {
                   16912:                 if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
                   16913:                     return false; // instruct the downloader to silently skip
                   16914:                 }
                   16915: 
                   16916:                 if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
                   16917:                     if (is_array($origErr->getUserInfo())) {
                   16918:                         foreach ($origErr->getUserInfo() as $err) {
                   16919:                             if (is_array($err)) {
                   16920:                                 $err = $err['message'];
                   16921:                             }
                   16922: 
                   16923:                             if (!isset($options['soft'])) {
                   16924:                                 $this->_downloader->log(0, $err);
                   16925:                             }
                   16926:                         }
                   16927:                     }
                   16928: 
                   16929:                     if (!isset($options['soft'])) {
                   16930:                         $this->_downloader->log(0, $origErr->getMessage());
                   16931:                     }
                   16932: 
                   16933:                     if (is_array($param)) {
                   16934:                         $param = $this->_registry->parsedPackageNameToString($param, true);
                   16935:                     }
                   16936: 
                   16937:                     if (!isset($options['soft'])) {
                   16938:                         $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   16939:                     }
                   16940: 
                   16941:                     // Passing no message back - already logged above
                   16942:                     return PEAR::raiseError();
                   16943:                 }
                   16944: 
                   16945:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   16946:                     $this->_downloader->log(0, $err->getMessage());
                   16947:                 }
                   16948: 
                   16949:                 if (is_array($param)) {
                   16950:                     $param = $this->_registry->parsedPackageNameToString($param, true);
                   16951:                 }
                   16952: 
                   16953:                 if (!isset($options['soft'])) {
                   16954:                     $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   16955:                 }
                   16956: 
                   16957:                 // Passing no message back - already logged above
                   16958:                 return PEAR::raiseError();
                   16959:             }
                   16960:         }
                   16961: 
                   16962:         return true;
                   16963:     }
                   16964: 
                   16965:     /**
                   16966:      * Retrieve any non-local packages
                   16967:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
                   16968:      */
                   16969:     function &download()
                   16970:     {
                   16971:         if (isset($this->_packagefile)) {
                   16972:             return $this->_packagefile;
                   16973:         }
                   16974: 
                   16975:         if (isset($this->_downloadURL['url'])) {
                   16976:             $this->_isvalid = false;
                   16977:             $info = $this->getParsedPackage();
                   16978:             foreach ($info as $i => $p) {
                   16979:                 $info[$i] = strtolower($p);
                   16980:             }
                   16981: 
                   16982:             $err = $this->_fromUrl($this->_downloadURL['url'],
                   16983:                 $this->_registry->parsedPackageNameToString($this->_parsedname, true));
                   16984:             $newinfo = $this->getParsedPackage();
                   16985:             foreach ($newinfo as $i => $p) {
                   16986:                 $newinfo[$i] = strtolower($p);
                   16987:             }
                   16988: 
                   16989:             if ($info != $newinfo) {
                   16990:                 do {
                   16991:                     if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
                   16992:                         $info['channel'] = 'pear.php.net';
                   16993:                         if ($info == $newinfo) {
                   16994:                             // skip the channel check if a pecl package says it's a PEAR package
                   16995:                             break;
                   16996:                         }
                   16997:                     }
                   16998:                     if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
                   16999:                         $info['channel'] = 'pecl.php.net';
                   17000:                         if ($info == $newinfo) {
                   17001:                             // skip the channel check if a pecl package says it's a PEAR package
                   17002:                             break;
                   17003:                         }
                   17004:                     }
                   17005: 
                   17006:                     return PEAR::raiseError('CRITICAL ERROR: We are ' .
                   17007:                         $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
                   17008:                         'downloaded claims to be ' .
                   17009:                         $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
                   17010:                 } while (false);
                   17011:             }
                   17012: 
                   17013:             if (PEAR::isError($err) || !$this->_valid) {
                   17014:                 return $err;
                   17015:             }
                   17016:         }
                   17017: 
                   17018:         $this->_type = 'local';
                   17019:         return $this->_packagefile;
                   17020:     }
                   17021: 
                   17022:     function &getPackageFile()
                   17023:     {
                   17024:         return $this->_packagefile;
                   17025:     }
                   17026: 
                   17027:     function &getDownloader()
                   17028:     {
                   17029:         return $this->_downloader;
                   17030:     }
                   17031: 
                   17032:     function getType()
                   17033:     {
                   17034:         return $this->_type;
                   17035:     }
                   17036: 
                   17037:     /**
                   17038:      * Like {@link initialize()}, but operates on a dependency
                   17039:      */
                   17040:     function fromDepURL($dep)
                   17041:     {
                   17042:         $this->_downloadURL = $dep;
                   17043:         if (isset($dep['uri'])) {
                   17044:             $options = $this->_downloader->getOptions();
                   17045:             if (!extension_loaded("zlib") || isset($options['nocompress'])) {
                   17046:                 $ext = '.tar';
                   17047:             } else {
                   17048:                 $ext = '.tgz';
                   17049:             }
                   17050: 
                   17051:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17052:             $err = $this->_fromUrl($dep['uri'] . $ext);
                   17053:             PEAR::popErrorHandling();
                   17054:             if (PEAR::isError($err)) {
                   17055:                 if (!isset($options['soft'])) {
                   17056:                     $this->_downloader->log(0, $err->getMessage());
                   17057:                 }
                   17058: 
                   17059:                 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
                   17060:                     'cannot download');
                   17061:             }
                   17062:         } else {
                   17063:             $this->_parsedname =
                   17064:                 array(
                   17065:                     'package' => $dep['info']->getPackage(),
                   17066:                     'channel' => $dep['info']->getChannel(),
                   17067:                     'version' => $dep['version']
                   17068:                 );
                   17069:             if (!isset($dep['nodefault'])) {
                   17070:                 $this->_parsedname['group'] = 'default'; // download the default dependency group
                   17071:                 $this->_explicitGroup = false;
                   17072:             }
                   17073: 
                   17074:             $this->_rawpackagefile = $dep['raw'];
                   17075:         }
                   17076:     }
                   17077: 
                   17078:     function detectDependencies($params)
                   17079:     {
                   17080:         $options = $this->_downloader->getOptions();
                   17081:         if (isset($options['downloadonly'])) {
                   17082:             return;
                   17083:         }
                   17084: 
                   17085:         if (isset($options['offline'])) {
                   17086:             $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
                   17087:             return;
                   17088:         }
                   17089: 
                   17090:         $pname = $this->getParsedPackage();
                   17091:         if (!$pname) {
                   17092:             return;
                   17093:         }
                   17094: 
                   17095:         $deps = $this->getDeps();
                   17096:         if (!$deps) {
                   17097:             return;
                   17098:         }
                   17099: 
                   17100:         if (isset($deps['required'])) { // package.xml 2.0
                   17101:             return $this->_detect2($deps, $pname, $options, $params);
                   17102:         }
                   17103: 
                   17104:         return $this->_detect1($deps, $pname, $options, $params);
                   17105:     }
                   17106: 
                   17107:     function setValidated()
                   17108:     {
                   17109:         $this->_validated = true;
                   17110:     }
                   17111: 
                   17112:     function alreadyValidated()
                   17113:     {
                   17114:         return $this->_validated;
                   17115:     }
                   17116: 
                   17117:     /**
                   17118:      * Remove packages to be downloaded that are already installed
                   17119:      * @param array of PEAR_Downloader_Package objects
                   17120:      * @static
                   17121:      */
                   17122:     function removeInstalled(&$params)
                   17123:     {
                   17124:         if (!isset($params[0])) {
                   17125:             return;
                   17126:         }
                   17127: 
                   17128:         $options = $params[0]->_downloader->getOptions();
                   17129:         if (!isset($options['downloadonly'])) {
                   17130:             foreach ($params as $i => $param) {
                   17131:                 $package = $param->getPackage();
                   17132:                 $channel = $param->getChannel();
                   17133:                 // remove self if already installed with this version
                   17134:                 // this does not need any pecl magic - we only remove exact matches
                   17135:                 if ($param->_installRegistry->packageExists($package, $channel)) {
                   17136:                     $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
                   17137:                     if (version_compare($packageVersion, $param->getVersion(), '==')) {
                   17138:                         if (!isset($options['force'])) {
                   17139:                             $info = $param->getParsedPackage();
                   17140:                             unset($info['version']);
                   17141:                             unset($info['state']);
                   17142:                             if (!isset($options['soft'])) {
                   17143:                                 $param->_downloader->log(1, 'Skipping package "' .
                   17144:                                     $param->getShortName() .
                   17145:                                     '", already installed as version ' . $packageVersion);
                   17146:                             }
                   17147:                             $params[$i] = false;
                   17148:                         }
                   17149:                     } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
                   17150:                           !isset($options['soft'])) {
                   17151:                         $info = $param->getParsedPackage();
                   17152:                         $param->_downloader->log(1, 'Skipping package "' .
                   17153:                             $param->getShortName() .
                   17154:                             '", already installed as version ' . $packageVersion);
                   17155:                         $params[$i] = false;
                   17156:                     }
                   17157:                 }
                   17158:             }
                   17159:         }
                   17160: 
                   17161:         PEAR_Downloader_Package::removeDuplicates($params);
                   17162:     }
                   17163: 
                   17164:     function _detect2($deps, $pname, $options, $params)
                   17165:     {
                   17166:         $this->_downloadDeps = array();
                   17167:         $groupnotfound = false;
                   17168:         foreach (array('package', 'subpackage') as $packagetype) {
                   17169:             // get required dependency group
                   17170:             if (isset($deps['required'][$packagetype])) {
                   17171:                 if (isset($deps['required'][$packagetype][0])) {
                   17172:                     foreach ($deps['required'][$packagetype] as $dep) {
                   17173:                         if (isset($dep['conflicts'])) {
                   17174:                             // skip any package that this package conflicts with
                   17175:                             continue;
                   17176:                         }
                   17177:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   17178:                         if (is_array($ret)) {
                   17179:                             $this->_downloadDeps[] = $ret;
                   17180:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17181:                             $this->_downloader->log(0, $ret->getMessage());
                   17182:                         }
                   17183:                     }
                   17184:                 } else {
                   17185:                     $dep = $deps['required'][$packagetype];
                   17186:                     if (!isset($dep['conflicts'])) {
                   17187:                         // skip any package that this package conflicts with
                   17188:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   17189:                         if (is_array($ret)) {
                   17190:                             $this->_downloadDeps[] = $ret;
                   17191:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17192:                             $this->_downloader->log(0, $ret->getMessage());
                   17193:                         }
                   17194:                     }
                   17195:                 }
                   17196:             }
                   17197: 
                   17198:             // get optional dependency group, if any
                   17199:             if (isset($deps['optional'][$packagetype])) {
                   17200:                 $skipnames = array();
                   17201:                 if (!isset($deps['optional'][$packagetype][0])) {
                   17202:                     $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
                   17203:                 }
                   17204: 
                   17205:                 foreach ($deps['optional'][$packagetype] as $dep) {
                   17206:                     $skip = false;
                   17207:                     if (!isset($options['alldeps'])) {
                   17208:                         $dep['package'] = $dep['name'];
                   17209:                         if (!isset($options['soft'])) {
                   17210:                             $this->_downloader->log(3, 'Notice: package "' .
                   17211:                               $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
                   17212:                                     true) . '" optional dependency "' .
                   17213:                                 $this->_registry->parsedPackageNameToString(array('package' =>
                   17214:                                     $dep['name'], 'channel' => 'pear.php.net'), true) .
                   17215:                                 '" will not be automatically downloaded');
                   17216:                         }
                   17217:                         $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
                   17218:                         $skip = true;
                   17219:                         unset($dep['package']);
                   17220:                     }
                   17221: 
                   17222:                     $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
                   17223:                     if (PEAR::isError($ret) && !isset($options['soft'])) {
                   17224:                         $this->_downloader->log(0, $ret->getMessage());
                   17225:                     }
                   17226: 
                   17227:                     if (!$ret) {
                   17228:                         $dep['package'] = $dep['name'];
                   17229:                         $skip = count($skipnames) ?
                   17230:                             $skipnames[count($skipnames) - 1] : '';
                   17231:                         if ($skip ==
                   17232:                               $this->_registry->parsedPackageNameToString($dep, true)) {
                   17233:                             array_pop($skipnames);
                   17234:                         }
                   17235:                     }
                   17236: 
                   17237:                     if (!$skip && is_array($ret)) {
                   17238:                         $this->_downloadDeps[] = $ret;
                   17239:                     }
                   17240:                 }
                   17241: 
                   17242:                 if (count($skipnames)) {
                   17243:                     if (!isset($options['soft'])) {
                   17244:                         $this->_downloader->log(1, 'Did not download optional dependencies: ' .
                   17245:                             implode(', ', $skipnames) .
                   17246:                             ', use --alldeps to download automatically');
                   17247:                     }
                   17248:                 }
                   17249:             }
                   17250: 
                   17251:             // get requested dependency group, if any
                   17252:             $groupname = $this->getGroup();
                   17253:             $explicit  = $this->_explicitGroup;
                   17254:             if (!$groupname) {
                   17255:                 if (!$this->canDefault()) {
                   17256:                     continue;
                   17257:                 }
                   17258: 
                   17259:                 $groupname = 'default'; // try the default dependency group
                   17260:             }
                   17261: 
                   17262:             if ($groupnotfound) {
                   17263:                 continue;
                   17264:             }
                   17265: 
                   17266:             if (isset($deps['group'])) {
                   17267:                 if (isset($deps['group']['attribs'])) {
                   17268:                     if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
                   17269:                         $group = $deps['group'];
                   17270:                     } elseif ($explicit) {
                   17271:                         if (!isset($options['soft'])) {
                   17272:                             $this->_downloader->log(0, 'Warning: package "' .
                   17273:                                 $this->_registry->parsedPackageNameToString($pname, true) .
                   17274:                                 '" has no dependency ' . 'group named "' . $groupname . '"');
                   17275:                         }
                   17276: 
                   17277:                         $groupnotfound = true;
                   17278:                         continue;
                   17279:                     }
                   17280:                 } else {
                   17281:                     $found = false;
                   17282:                     foreach ($deps['group'] as $group) {
                   17283:                         if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
                   17284:                             $found = true;
                   17285:                             break;
                   17286:                         }
                   17287:                     }
                   17288: 
                   17289:                     if (!$found) {
                   17290:                         if ($explicit) {
                   17291:                             if (!isset($options['soft'])) {
                   17292:                                 $this->_downloader->log(0, 'Warning: package "' .
                   17293:                                     $this->_registry->parsedPackageNameToString($pname, true) .
                   17294:                                     '" has no dependency ' . 'group named "' . $groupname . '"');
                   17295:                             }
                   17296:                         }
                   17297: 
                   17298:                         $groupnotfound = true;
                   17299:                         continue;
                   17300:                     }
                   17301:                 }
                   17302:             }
                   17303: 
                   17304:             if (isset($group) && isset($group[$packagetype])) {
                   17305:                 if (isset($group[$packagetype][0])) {
                   17306:                     foreach ($group[$packagetype] as $dep) {
                   17307:                         $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
                   17308:                             $group['attribs']['name'] . '"', $params);
                   17309:                         if (is_array($ret)) {
                   17310:                             $this->_downloadDeps[] = $ret;
                   17311:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17312:                             $this->_downloader->log(0, $ret->getMessage());
                   17313:                         }
                   17314:                     }
                   17315:                 } else {
                   17316:                     $ret = $this->_detect2Dep($group[$packagetype], $pname,
                   17317:                         'dependency group "' .
                   17318:                         $group['attribs']['name'] . '"', $params);
                   17319:                     if (is_array($ret)) {
                   17320:                         $this->_downloadDeps[] = $ret;
                   17321:                     } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17322:                         $this->_downloader->log(0, $ret->getMessage());
                   17323:                     }
                   17324:                 }
                   17325:             }
                   17326:         }
                   17327:     }
                   17328: 
                   17329:     function _detect2Dep($dep, $pname, $group, $params)
                   17330:     {
                   17331:         if (isset($dep['conflicts'])) {
                   17332:             return true;
                   17333:         }
                   17334: 
                   17335:         $options = $this->_downloader->getOptions();
                   17336:         if (isset($dep['uri'])) {
                   17337:             return array('uri' => $dep['uri'], 'dep' => $dep);;
                   17338:         }
                   17339: 
                   17340:         $testdep = $dep;
                   17341:         $testdep['package'] = $dep['name'];
                   17342:         if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
                   17343:             $dep['package'] = $dep['name'];
                   17344:             if (!isset($options['soft'])) {
                   17345:                 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
                   17346:                     ' dependency "' .
                   17347:                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17348:                     '", will be installed');
                   17349:             }
                   17350:             return false;
                   17351:         }
                   17352: 
                   17353:         $options = $this->_downloader->getOptions();
                   17354:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17355:         if ($this->_explicitState) {
                   17356:             $pname['state'] = $this->_explicitState;
                   17357:         }
                   17358: 
                   17359:         $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   17360:         if (PEAR::isError($url)) {
                   17361:             PEAR::popErrorHandling();
                   17362:             return $url;
                   17363:         }
                   17364: 
                   17365:         $dep['package'] = $dep['name'];
                   17366:         $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
                   17367:             !isset($options['alldeps']), true);
                   17368:         PEAR::popErrorHandling();
                   17369:         if (PEAR::isError($ret)) {
                   17370:             if (!isset($options['soft'])) {
                   17371:                 $this->_downloader->log(0, $ret->getMessage());
                   17372:             }
                   17373: 
                   17374:             return false;
                   17375:         }
                   17376: 
                   17377:         // check to see if a dep is already installed and is the same or newer
                   17378:         if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
                   17379:             $oper = 'has';
                   17380:         } else {
                   17381:             $oper = 'gt';
                   17382:         }
                   17383: 
                   17384:         // do not try to move this before getDepPackageDownloadURL
                   17385:         // we can't determine whether upgrade is necessary until we know what
                   17386:         // version would be downloaded
                   17387:         if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
                   17388:             $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
                   17389:             $dep['package'] = $dep['name'];
                   17390:             if (!isset($options['soft'])) {
                   17391:                 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   17392:                     ' dependency "' .
                   17393:                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17394:                     '" version ' . $url['version'] . ', already installed as version ' .
                   17395:                     $version);
                   17396:             }
                   17397: 
                   17398:             return false;
                   17399:         }
                   17400: 
                   17401:         if (isset($dep['nodefault'])) {
                   17402:             $ret['nodefault'] = true;
                   17403:         }
                   17404: 
                   17405:         return $ret;
                   17406:     }
                   17407: 
                   17408:     function _detect1($deps, $pname, $options, $params)
                   17409:     {
                   17410:         $this->_downloadDeps = array();
                   17411:         $skipnames = array();
                   17412:         foreach ($deps as $dep) {
                   17413:             $nodownload = false;
                   17414:             if (isset ($dep['type']) && $dep['type'] === 'pkg') {
                   17415:                 $dep['channel'] = 'pear.php.net';
                   17416:                 $dep['package'] = $dep['name'];
                   17417:                 switch ($dep['rel']) {
                   17418:                     case 'not' :
                   17419:                         continue 2;
                   17420:                     case 'ge' :
                   17421:                     case 'eq' :
                   17422:                     case 'gt' :
                   17423:                     case 'has' :
                   17424:                         $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17425:                             'required' :
                   17426:                             'optional';
                   17427:                         if (PEAR_Downloader_Package::willDownload($dep, $params)) {
                   17428:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   17429:                                 . ' dependency "' .
                   17430:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17431:                                 '", will be installed');
                   17432:                             continue 2;
                   17433:                         }
                   17434:                         $fakedp = new PEAR_PackageFile_v1;
                   17435:                         $fakedp->setPackage($dep['name']);
                   17436:                         // skip internet check if we are not upgrading (bug #5810)
                   17437:                         if (!isset($options['upgrade']) && $this->isInstalled(
                   17438:                               $fakedp, $dep['rel'])) {
                   17439:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   17440:                                 . ' dependency "' .
                   17441:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17442:                                 '", is already installed');
                   17443:                             continue 2;
                   17444:                         }
                   17445:                 }
                   17446: 
                   17447:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17448:                 if ($this->_explicitState) {
                   17449:                     $pname['state'] = $this->_explicitState;
                   17450:                 }
                   17451: 
                   17452:                 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   17453:                 $chan = 'pear.php.net';
                   17454:                 if (PEAR::isError($url)) {
                   17455:                     // check to see if this is a pecl package that has jumped
                   17456:                     // from pear.php.net to pecl.php.net channel
                   17457:                     if (!class_exists('PEAR_Dependency2')) {
                   17458:                         require_once 'PEAR/Dependency2.php';
                   17459:                     }
                   17460: 
                   17461:                     $newdep = PEAR_Dependency2::normalizeDep($dep);
                   17462:                     $newdep = $newdep[0];
                   17463:                     $newdep['channel'] = 'pecl.php.net';
                   17464:                     $chan = 'pecl.php.net';
                   17465:                     $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
                   17466:                     $obj = &$this->_installRegistry->getPackage($dep['name']);
                   17467:                     if (PEAR::isError($url)) {
                   17468:                         PEAR::popErrorHandling();
                   17469:                         if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
                   17470:                             $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17471:                                 'required' :
                   17472:                                 'optional';
                   17473:                             $dep['package'] = $dep['name'];
                   17474:                             if (!isset($options['soft'])) {
                   17475:                                 $this->_downloader->log(3, $this->getShortName() .
                   17476:                                     ': Skipping ' . $group . ' dependency "' .
                   17477:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17478:                                     '", already installed as version ' . $obj->getVersion());
                   17479:                             }
                   17480:                             $skip = count($skipnames) ?
                   17481:                                 $skipnames[count($skipnames) - 1] : '';
                   17482:                             if ($skip ==
                   17483:                                   $this->_registry->parsedPackageNameToString($dep, true)) {
                   17484:                                 array_pop($skipnames);
                   17485:                             }
                   17486:                             continue;
                   17487:                         } else {
                   17488:                             if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   17489:                                 $this->_downloader->log(2, $this->getShortName() .
                   17490:                                     ': Skipping optional dependency "' .
                   17491:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17492:                                     '", no releases exist');
                   17493:                                 continue;
                   17494:                             } else {
                   17495:                                 return $url;
                   17496:                             }
                   17497:                         }
                   17498:                     }
                   17499:                 }
                   17500: 
                   17501:                 PEAR::popErrorHandling();
                   17502:                 if (!isset($options['alldeps'])) {
                   17503:                     if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   17504:                         if (!isset($options['soft'])) {
                   17505:                             $this->_downloader->log(3, 'Notice: package "' .
                   17506:                                 $this->getShortName() .
                   17507:                                 '" optional dependency "' .
                   17508:                                 $this->_registry->parsedPackageNameToString(
                   17509:                                     array('channel' => $chan, 'package' =>
                   17510:                                     $dep['name']), true) .
                   17511:                                 '" will not be automatically downloaded');
                   17512:                         }
                   17513:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   17514:                                 array('channel' => $chan, 'package' =>
                   17515:                                 $dep['name']), true);
                   17516:                         $nodownload = true;
                   17517:                     }
                   17518:                 }
                   17519: 
                   17520:                 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
                   17521:                     if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   17522:                         if (!isset($options['soft'])) {
                   17523:                             $this->_downloader->log(3, 'Notice: package "' .
                   17524:                                 $this->getShortName() .
                   17525:                                 '" required dependency "' .
                   17526:                                 $this->_registry->parsedPackageNameToString(
                   17527:                                     array('channel' => $chan, 'package' =>
                   17528:                                     $dep['name']), true) .
                   17529:                                 '" will not be automatically downloaded');
                   17530:                         }
                   17531:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   17532:                                 array('channel' => $chan, 'package' =>
                   17533:                                 $dep['name']), true);
                   17534:                         $nodownload = true;
                   17535:                     }
                   17536:                 }
                   17537: 
                   17538:                 // check to see if a dep is already installed
                   17539:                 // do not try to move this before getDepPackageDownloadURL
                   17540:                 // we can't determine whether upgrade is necessary until we know what
                   17541:                 // version would be downloaded
                   17542:                 if (!isset($options['force']) && $this->isInstalled(
                   17543:                         $url, $dep['rel'])) {
                   17544:                     $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17545:                         'required' :
                   17546:                         'optional';
                   17547:                     $dep['package'] = $dep['name'];
                   17548:                     if (isset($newdep)) {
                   17549:                         $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
                   17550:                     } else {
                   17551:                         $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
                   17552:                     }
                   17553: 
                   17554:                     $dep['version'] = $url['version'];
                   17555:                     if (!isset($options['soft'])) {
                   17556:                         $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   17557:                             ' dependency "' .
                   17558:                             $this->_registry->parsedPackageNameToString($dep, true) .
                   17559:                             '", already installed as version ' . $version);
                   17560:                     }
                   17561: 
                   17562:                     $skip = count($skipnames) ?
                   17563:                         $skipnames[count($skipnames) - 1] : '';
                   17564:                     if ($skip ==
                   17565:                           $this->_registry->parsedPackageNameToString($dep, true)) {
                   17566:                         array_pop($skipnames);
                   17567:                     }
                   17568: 
                   17569:                     continue;
                   17570:                 }
                   17571: 
                   17572:                 if ($nodownload) {
                   17573:                     continue;
                   17574:                 }
                   17575: 
                   17576:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17577:                 if (isset($newdep)) {
                   17578:                     $dep = $newdep;
                   17579:                 }
                   17580: 
                   17581:                 $dep['package'] = $dep['name'];
                   17582:                 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
                   17583:                     isset($dep['optional']) && $dep['optional'] == 'yes' &&
                   17584:                     !isset($options['alldeps']), true);
                   17585:                 PEAR::popErrorHandling();
                   17586:                 if (PEAR::isError($ret)) {
                   17587:                     if (!isset($options['soft'])) {
                   17588:                         $this->_downloader->log(0, $ret->getMessage());
                   17589:                     }
                   17590:                     continue;
                   17591:                 }
                   17592: 
                   17593:                 $this->_downloadDeps[] = $ret;
                   17594:             }
                   17595:         }
                   17596: 
                   17597:         if (count($skipnames)) {
                   17598:             if (!isset($options['soft'])) {
                   17599:                 $this->_downloader->log(1, 'Did not download dependencies: ' .
                   17600:                     implode(', ', $skipnames) .
                   17601:                     ', use --alldeps or --onlyreqdeps to download automatically');
                   17602:             }
                   17603:         }
                   17604:     }
                   17605: 
                   17606:     function setDownloadURL($pkg)
                   17607:     {
                   17608:         $this->_downloadURL = $pkg;
                   17609:     }
                   17610: 
                   17611:     /**
                   17612:      * Set the package.xml object for this downloaded package
                   17613:      *
                   17614:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
                   17615:      */
                   17616:     function setPackageFile(&$pkg)
                   17617:     {
                   17618:         $this->_packagefile = &$pkg;
                   17619:     }
                   17620: 
                   17621:     function getShortName()
                   17622:     {
                   17623:         return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
                   17624:             'package' => $this->getPackage()), true);
                   17625:     }
                   17626: 
                   17627:     function getParsedPackage()
                   17628:     {
                   17629:         if (isset($this->_packagefile) || isset($this->_parsedname)) {
                   17630:             return array('channel' => $this->getChannel(),
                   17631:                 'package' => $this->getPackage(),
                   17632:                 'version' => $this->getVersion());
                   17633:         }
                   17634: 
                   17635:         return false;
                   17636:     }
                   17637: 
                   17638:     function getDownloadURL()
                   17639:     {
                   17640:         return $this->_downloadURL;
                   17641:     }
                   17642: 
                   17643:     function canDefault()
                   17644:     {
                   17645:         if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
                   17646:             return false;
                   17647:         }
                   17648: 
                   17649:         return true;
                   17650:     }
                   17651: 
                   17652:     function getPackage()
                   17653:     {
                   17654:         if (isset($this->_packagefile)) {
                   17655:             return $this->_packagefile->getPackage();
                   17656:         } elseif (isset($this->_downloadURL['info'])) {
                   17657:             return $this->_downloadURL['info']->getPackage();
                   17658:         }
                   17659: 
                   17660:         return false;
                   17661:     }
                   17662: 
                   17663:     /**
                   17664:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   17665:      */
                   17666:     function isSubpackage(&$pf)
                   17667:     {
                   17668:         if (isset($this->_packagefile)) {
                   17669:             return $this->_packagefile->isSubpackage($pf);
                   17670:         } elseif (isset($this->_downloadURL['info'])) {
                   17671:             return $this->_downloadURL['info']->isSubpackage($pf);
                   17672:         }
                   17673: 
                   17674:         return false;
                   17675:     }
                   17676: 
                   17677:     function getPackageType()
                   17678:     {
                   17679:         if (isset($this->_packagefile)) {
                   17680:             return $this->_packagefile->getPackageType();
                   17681:         } elseif (isset($this->_downloadURL['info'])) {
                   17682:             return $this->_downloadURL['info']->getPackageType();
                   17683:         }
                   17684: 
                   17685:         return false;
                   17686:     }
                   17687: 
                   17688:     function isBundle()
                   17689:     {
                   17690:         if (isset($this->_packagefile)) {
                   17691:             return $this->_packagefile->getPackageType() == 'bundle';
                   17692:         }
                   17693: 
                   17694:         return false;
                   17695:     }
                   17696: 
                   17697:     function getPackageXmlVersion()
                   17698:     {
                   17699:         if (isset($this->_packagefile)) {
                   17700:             return $this->_packagefile->getPackagexmlVersion();
                   17701:         } elseif (isset($this->_downloadURL['info'])) {
                   17702:             return $this->_downloadURL['info']->getPackagexmlVersion();
                   17703:         }
                   17704: 
                   17705:         return '1.0';
                   17706:     }
                   17707: 
                   17708:     function getChannel()
                   17709:     {
                   17710:         if (isset($this->_packagefile)) {
                   17711:             return $this->_packagefile->getChannel();
                   17712:         } elseif (isset($this->_downloadURL['info'])) {
                   17713:             return $this->_downloadURL['info']->getChannel();
                   17714:         }
                   17715: 
                   17716:         return false;
                   17717:     }
                   17718: 
                   17719:     function getURI()
                   17720:     {
                   17721:         if (isset($this->_packagefile)) {
                   17722:             return $this->_packagefile->getURI();
                   17723:         } elseif (isset($this->_downloadURL['info'])) {
                   17724:             return $this->_downloadURL['info']->getURI();
                   17725:         }
                   17726: 
                   17727:         return false;
                   17728:     }
                   17729: 
                   17730:     function getVersion()
                   17731:     {
                   17732:         if (isset($this->_packagefile)) {
                   17733:             return $this->_packagefile->getVersion();
                   17734:         } elseif (isset($this->_downloadURL['version'])) {
                   17735:             return $this->_downloadURL['version'];
                   17736:         }
                   17737: 
                   17738:         return false;
                   17739:     }
                   17740: 
                   17741:     function isCompatible($pf)
                   17742:     {
                   17743:         if (isset($this->_packagefile)) {
                   17744:             return $this->_packagefile->isCompatible($pf);
                   17745:         } elseif (isset($this->_downloadURL['info'])) {
                   17746:             return $this->_downloadURL['info']->isCompatible($pf);
                   17747:         }
                   17748: 
                   17749:         return true;
                   17750:     }
                   17751: 
                   17752:     function setGroup($group)
                   17753:     {
                   17754:         $this->_parsedname['group'] = $group;
                   17755:     }
                   17756: 
                   17757:     function getGroup()
                   17758:     {
                   17759:         if (isset($this->_parsedname['group'])) {
                   17760:             return $this->_parsedname['group'];
                   17761:         }
                   17762: 
                   17763:         return '';
                   17764:     }
                   17765: 
                   17766:     function isExtension($name)
                   17767:     {
                   17768:         if (isset($this->_packagefile)) {
                   17769:             return $this->_packagefile->isExtension($name);
                   17770:         } elseif (isset($this->_downloadURL['info'])) {
                   17771:             if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
                   17772:                 return $this->_downloadURL['info']->getProvidesExtension() == $name;
                   17773:             }
                   17774: 
                   17775:             return false;
                   17776:         }
                   17777: 
                   17778:         return false;
                   17779:     }
                   17780: 
                   17781:     function getDeps()
                   17782:     {
                   17783:         if (isset($this->_packagefile)) {
                   17784:             $ver = $this->_packagefile->getPackagexmlVersion();
                   17785:             if (version_compare($ver, '2.0', '>=')) {
                   17786:                 return $this->_packagefile->getDeps(true);
                   17787:             }
                   17788: 
                   17789:             return $this->_packagefile->getDeps();
                   17790:         } elseif (isset($this->_downloadURL['info'])) {
                   17791:             $ver = $this->_downloadURL['info']->getPackagexmlVersion();
                   17792:             if (version_compare($ver, '2.0', '>=')) {
                   17793:                 return $this->_downloadURL['info']->getDeps(true);
                   17794:             }
                   17795: 
                   17796:             return $this->_downloadURL['info']->getDeps();
                   17797:         }
                   17798: 
                   17799:         return array();
                   17800:     }
                   17801: 
                   17802:     /**
                   17803:      * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
                   17804:      *                     returned from getDepDownloadURL()
                   17805:      */
                   17806:     function isEqual($param)
                   17807:     {
                   17808:         if (is_object($param)) {
                   17809:             $channel = $param->getChannel();
                   17810:             $package = $param->getPackage();
                   17811:             if ($param->getURI()) {
                   17812:                 $param = array(
                   17813:                     'channel' => $param->getChannel(),
                   17814:                     'package' => $param->getPackage(),
                   17815:                     'version' => $param->getVersion(),
                   17816:                     'uri' => $param->getURI(),
                   17817:                 );
                   17818:             } else {
                   17819:                 $param = array(
                   17820:                     'channel' => $param->getChannel(),
                   17821:                     'package' => $param->getPackage(),
                   17822:                     'version' => $param->getVersion(),
                   17823:                 );
                   17824:             }
                   17825:         } else {
                   17826:             if (isset($param['uri'])) {
                   17827:                 if ($this->getChannel() != '__uri') {
                   17828:                     return false;
                   17829:                 }
                   17830:                 return $param['uri'] == $this->getURI();
                   17831:             }
                   17832: 
                   17833:             $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
                   17834:             $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
                   17835:             if (isset($param['rel'])) {
                   17836:                 if (!class_exists('PEAR_Dependency2')) {
                   17837:                     require_once 'PEAR/Dependency2.php';
                   17838:                 }
                   17839: 
                   17840:                 $newdep = PEAR_Dependency2::normalizeDep($param);
                   17841:                 $newdep = $newdep[0];
                   17842:             } elseif (isset($param['min'])) {
                   17843:                 $newdep = $param;
                   17844:             }
                   17845:         }
                   17846: 
                   17847:         if (isset($newdep)) {
                   17848:             if (!isset($newdep['min'])) {
                   17849:                 $newdep['min'] = '0';
                   17850:             }
                   17851: 
                   17852:             if (!isset($newdep['max'])) {
                   17853:                 $newdep['max'] = '100000000000000000000';
                   17854:             }
                   17855: 
                   17856:             // use magic to support pecl packages suddenly jumping to the pecl channel
                   17857:             // we need to support both dependency possibilities
                   17858:             if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
                   17859:                 if ($package == $this->getPackage()) {
                   17860:                     $channel = 'pecl.php.net';
                   17861:                 }
                   17862:             }
                   17863:             if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   17864:                 if ($package == $this->getPackage()) {
                   17865:                     $channel = 'pear.php.net';
                   17866:                 }
                   17867:             }
                   17868: 
                   17869:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   17870:                 $channel == $this->getChannel() &&
                   17871:                 version_compare($newdep['min'], $this->getVersion(), '<=') &&
                   17872:                 version_compare($newdep['max'], $this->getVersion(), '>='));
                   17873:         }
                   17874: 
                   17875:         // use magic to support pecl packages suddenly jumping to the pecl channel
                   17876:         if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   17877:             if (strtolower($package) == strtolower($this->getPackage())) {
                   17878:                 $channel = 'pear.php.net';
                   17879:             }
                   17880:         }
                   17881: 
                   17882:         if (isset($param['version'])) {
                   17883:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   17884:                 $channel == $this->getChannel() &&
                   17885:                 $param['version'] == $this->getVersion());
                   17886:         }
                   17887: 
                   17888:         return strtolower($package) == strtolower($this->getPackage()) &&
                   17889:             $channel == $this->getChannel();
                   17890:     }
                   17891: 
                   17892:     function isInstalled($dep, $oper = '==')
                   17893:     {
                   17894:         if (!$dep) {
                   17895:             return false;
                   17896:         }
                   17897: 
                   17898:         if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
                   17899:             return false;
                   17900:         }
                   17901: 
                   17902:         if (is_object($dep)) {
                   17903:             $package = $dep->getPackage();
                   17904:             $channel = $dep->getChannel();
                   17905:             if ($dep->getURI()) {
                   17906:                 $dep = array(
                   17907:                     'uri' => $dep->getURI(),
                   17908:                     'version' => $dep->getVersion(),
                   17909:                 );
                   17910:             } else {
                   17911:                 $dep = array(
                   17912:                     'version' => $dep->getVersion(),
                   17913:                 );
                   17914:             }
                   17915:         } else {
                   17916:             if (isset($dep['uri'])) {
                   17917:                 $channel = '__uri';
                   17918:                 $package = $dep['dep']['name'];
                   17919:             } else {
                   17920:                 $channel = $dep['info']->getChannel();
                   17921:                 $package = $dep['info']->getPackage();
                   17922:             }
                   17923:         }
                   17924: 
                   17925:         $options = $this->_downloader->getOptions();
                   17926:         $test    = $this->_installRegistry->packageExists($package, $channel);
                   17927:         if (!$test && $channel == 'pecl.php.net') {
                   17928:             // do magic to allow upgrading from old pecl packages to new ones
                   17929:             $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
                   17930:             $channel = 'pear.php.net';
                   17931:         }
                   17932: 
                   17933:         if ($test) {
                   17934:             if (isset($dep['uri'])) {
                   17935:                 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
                   17936:                     return true;
                   17937:                 }
                   17938:             }
                   17939: 
                   17940:             if (isset($options['upgrade'])) {
                   17941:                 $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
                   17942:                 if (version_compare($packageVersion, $dep['version'], '>=')) {
                   17943:                     return true;
                   17944:                 }
                   17945: 
                   17946:                 return false;
                   17947:             }
                   17948: 
                   17949:             return true;
                   17950:         }
                   17951: 
                   17952:         return false;
                   17953:     }
                   17954: 
                   17955:     /**
                   17956:      * Detect duplicate package names with differing versions
                   17957:      *
                   17958:      * If a user requests to install Date 1.4.6 and Date 1.4.7,
                   17959:      * for instance, this is a logic error.  This method
                   17960:      * detects this situation.
                   17961:      *
                   17962:      * @param array $params array of PEAR_Downloader_Package objects
                   17963:      * @param array $errorparams empty array
                   17964:      * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
                   17965:      */
                   17966:     function detectStupidDuplicates($params, &$errorparams)
                   17967:     {
                   17968:         $existing = array();
                   17969:         foreach ($params as $i => $param) {
                   17970:             $package = $param->getPackage();
                   17971:             $channel = $param->getChannel();
                   17972:             $group   = $param->getGroup();
                   17973:             if (!isset($existing[$channel . '/' . $package])) {
                   17974:                 $existing[$channel . '/' . $package] = array();
                   17975:             }
                   17976: 
                   17977:             if (!isset($existing[$channel . '/' . $package][$group])) {
                   17978:                 $existing[$channel . '/' . $package][$group] = array();
                   17979:             }
                   17980: 
                   17981:             $existing[$channel . '/' . $package][$group][] = $i;
                   17982:         }
                   17983: 
                   17984:         $indices = array();
                   17985:         foreach ($existing as $package => $groups) {
                   17986:             foreach ($groups as $group => $dupes) {
                   17987:                 if (count($dupes) > 1) {
                   17988:                     $indices = $indices + $dupes;
                   17989:                 }
                   17990:             }
                   17991:         }
                   17992: 
                   17993:         $indices = array_unique($indices);
                   17994:         foreach ($indices as $index) {
                   17995:             $errorparams[] = $params[$index];
                   17996:         }
                   17997: 
                   17998:         return count($errorparams);
                   17999:     }
                   18000: 
                   18001:     /**
                   18002:      * @param array
                   18003:      * @param bool ignore install groups - for final removal of dupe packages
                   18004:      * @static
                   18005:      */
                   18006:     function removeDuplicates(&$params, $ignoreGroups = false)
                   18007:     {
                   18008:         $pnames = array();
                   18009:         foreach ($params as $i => $param) {
                   18010:             if (!$param) {
                   18011:                 continue;
                   18012:             }
                   18013: 
                   18014:             if ($param->getPackage()) {
                   18015:                 $group = $ignoreGroups ? '' : $param->getGroup();
                   18016:                 $pnames[$i] = $param->getChannel() . '/' .
                   18017:                     $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
                   18018:             }
                   18019:         }
                   18020: 
                   18021:         $pnames = array_unique($pnames);
                   18022:         $unset  = array_diff(array_keys($params), array_keys($pnames));
                   18023:         $testp  = array_flip($pnames);
                   18024:         foreach ($params as $i => $param) {
                   18025:             if (!$param) {
                   18026:                 $unset[] = $i;
                   18027:                 continue;
                   18028:             }
                   18029: 
                   18030:             if (!is_a($param, 'PEAR_Downloader_Package')) {
                   18031:                 $unset[] = $i;
                   18032:                 continue;
                   18033:             }
                   18034: 
                   18035:             $group = $ignoreGroups ? '' : $param->getGroup();
                   18036:             if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
                   18037:                   $param->getVersion() . '#' . $group])) {
                   18038:                 $unset[] = $i;
                   18039:             }
                   18040:         }
                   18041: 
                   18042:         foreach ($unset as $i) {
                   18043:             unset($params[$i]);
                   18044:         }
                   18045: 
                   18046:         $ret = array();
                   18047:         foreach ($params as $i => $param) {
                   18048:             $ret[] = &$params[$i];
                   18049:         }
                   18050: 
                   18051:         $params = array();
                   18052:         foreach ($ret as $i => $param) {
                   18053:             $params[] = &$ret[$i];
                   18054:         }
                   18055:     }
                   18056: 
                   18057:     function explicitState()
                   18058:     {
                   18059:         return $this->_explicitState;
                   18060:     }
                   18061: 
                   18062:     function setExplicitState($s)
                   18063:     {
                   18064:         $this->_explicitState = $s;
                   18065:     }
                   18066: 
                   18067:     /**
                   18068:      * @static
                   18069:      */
                   18070:     function mergeDependencies(&$params)
                   18071:     {
                   18072:         $bundles = $newparams = array();
                   18073:         foreach ($params as $i => $param) {
                   18074:             if (!$param->isBundle()) {
                   18075:                 continue;
                   18076:             }
                   18077: 
                   18078:             $bundles[] = $i;
                   18079:             $pf = &$param->getPackageFile();
                   18080:             $newdeps = array();
                   18081:             $contents = $pf->getBundledPackages();
                   18082:             if (!is_array($contents)) {
                   18083:                 $contents = array($contents);
                   18084:             }
                   18085: 
                   18086:             foreach ($contents as $file) {
                   18087:                 $filecontents = $pf->getFileContents($file);
                   18088:                 $dl = &$param->getDownloader();
                   18089:                 $options = $dl->getOptions();
                   18090:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   18091:                     return $dir;
                   18092:                 }
                   18093: 
                   18094:                 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
                   18095:                 if (!$fp) {
                   18096:                     continue;
                   18097:                 }
                   18098: 
                   18099:                 // FIXME do symlink check
                   18100: 
                   18101:                 fwrite($fp, $filecontents, strlen($filecontents));
                   18102:                 fclose($fp);
                   18103:                 if ($s = $params[$i]->explicitState()) {
                   18104:                     $obj->setExplicitState($s);
                   18105:                 }
                   18106: 
                   18107:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   18108:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18109:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   18110:                     PEAR::popErrorHandling();
                   18111:                     return $dir;
                   18112:                 }
                   18113: 
                   18114:                 $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file);
                   18115:                 PEAR::popErrorHandling();
                   18116:                 if (PEAR::isError($e)) {
                   18117:                     if (!isset($options['soft'])) {
                   18118:                         $dl->log(0, $e->getMessage());
                   18119:                     }
                   18120:                     continue;
                   18121:                 }
                   18122: 
                   18123:                 $j = &$obj;
                   18124:                 if (!PEAR_Downloader_Package::willDownload($j,
                   18125:                       array_merge($params, $newparams)) && !$param->isInstalled($j)) {
                   18126:                     $newparams[] = &$j;
                   18127:                 }
                   18128:             }
                   18129:         }
                   18130: 
                   18131:         foreach ($bundles as $i) {
                   18132:             unset($params[$i]); // remove bundles - only their contents matter for installation
                   18133:         }
                   18134: 
                   18135:         PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
                   18136:         if (count($newparams)) { // add in bundled packages for install
                   18137:             foreach ($newparams as $i => $unused) {
                   18138:                 $params[] = &$newparams[$i];
                   18139:             }
                   18140:             $newparams = array();
                   18141:         }
                   18142: 
                   18143:         foreach ($params as $i => $param) {
                   18144:             $newdeps = array();
                   18145:             foreach ($param->_downloadDeps as $dep) {
                   18146:                 $merge = array_merge($params, $newparams);
                   18147:                 if (!PEAR_Downloader_Package::willDownload($dep, $merge)
                   18148:                     && !$param->isInstalled($dep)
                   18149:                 ) {
                   18150:                     $newdeps[] = $dep;
                   18151:                 } else {
                   18152:                     //var_dump($dep);
                   18153:                     // detect versioning conflicts here
                   18154:                 }
                   18155:             }
                   18156: 
                   18157:             // convert the dependencies into PEAR_Downloader_Package objects for the next time around
                   18158:             $params[$i]->_downloadDeps = array();
                   18159:             foreach ($newdeps as $dep) {
                   18160:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   18161:                 if ($s = $params[$i]->explicitState()) {
                   18162:                     $obj->setExplicitState($s);
                   18163:                 }
                   18164: 
                   18165:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18166:                 $e = $obj->fromDepURL($dep);
                   18167:                 PEAR::popErrorHandling();
                   18168:                 if (PEAR::isError($e)) {
                   18169:                     if (!isset($options['soft'])) {
                   18170:                         $obj->_downloader->log(0, $e->getMessage());
                   18171:                     }
                   18172:                     continue;
                   18173:                 }
                   18174: 
                   18175:                 $e = $obj->detectDependencies($params);
                   18176:                 if (PEAR::isError($e)) {
                   18177:                     if (!isset($options['soft'])) {
                   18178:                         $obj->_downloader->log(0, $e->getMessage());
                   18179:                     }
                   18180:                 }
                   18181: 
                   18182:                 $j = &$obj;
                   18183:                 $newparams[] = &$j;
                   18184:             }
                   18185:         }
                   18186: 
                   18187:         if (count($newparams)) {
                   18188:             foreach ($newparams as $i => $unused) {
                   18189:                 $params[] = &$newparams[$i];
                   18190:             }
                   18191:             return true;
                   18192:         }
                   18193: 
                   18194:         return false;
                   18195:     }
                   18196: 
                   18197: 
                   18198:     /**
                   18199:      * @static
                   18200:      */
                   18201:     function willDownload($param, $params)
                   18202:     {
                   18203:         if (!is_array($params)) {
                   18204:             return false;
                   18205:         }
                   18206: 
                   18207:         foreach ($params as $obj) {
                   18208:             if ($obj->isEqual($param)) {
                   18209:                 return true;
                   18210:             }
                   18211:         }
                   18212: 
                   18213:         return false;
                   18214:     }
                   18215: 
                   18216:     /**
                   18217:      * For simpler unit-testing
                   18218:      * @param PEAR_Config
                   18219:      * @param int
                   18220:      * @param string
                   18221:      */
                   18222:     function &getPackagefileObject(&$c, $d)
                   18223:     {
                   18224:         $a = &new PEAR_PackageFile($c, $d);
                   18225:         return $a;
                   18226:     }
                   18227: 
                   18228:     /**
                   18229:      * This will retrieve from a local file if possible, and parse out
                   18230:      * a group name as well.  The original parameter will be modified to reflect this.
                   18231:      * @param string|array can be a parsed package name as well
                   18232:      * @access private
                   18233:      */
                   18234:     function _fromFile(&$param)
                   18235:     {
                   18236:         $saveparam = $param;
                   18237:         if (is_string($param)) {
                   18238:             if (!@file_exists($param)) {
                   18239:                 $test = explode('#', $param);
                   18240:                 $group = array_pop($test);
                   18241:                 if (@file_exists(implode('#', $test))) {
                   18242:                     $this->setGroup($group);
                   18243:                     $param = implode('#', $test);
                   18244:                     $this->_explicitGroup = true;
                   18245:                 }
                   18246:             }
                   18247: 
                   18248:             if (@is_file($param)) {
                   18249:                 $this->_type = 'local';
                   18250:                 $options = $this->_downloader->getOptions();
                   18251:                 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
                   18252:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18253:                 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
                   18254:                 PEAR::popErrorHandling();
                   18255:                 if (PEAR::isError($pf)) {
                   18256:                     $this->_valid = false;
                   18257:                     $param = $saveparam;
                   18258:                     return $pf;
                   18259:                 }
                   18260:                 $this->_packagefile = &$pf;
                   18261:                 if (!$this->getGroup()) {
                   18262:                     $this->setGroup('default'); // install the default dependency group
                   18263:                 }
                   18264:                 return $this->_valid = true;
                   18265:             }
                   18266:         }
                   18267:         $param = $saveparam;
                   18268:         return $this->_valid = false;
                   18269:     }
                   18270: 
                   18271:     function _fromUrl($param, $saveparam = '')
                   18272:     {
                   18273:         if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
                   18274:             $options = $this->_downloader->getOptions();
                   18275:             $this->_type = 'url';
                   18276:             $callback = $this->_downloader->ui ?
                   18277:                 array(&$this->_downloader, '_downloadCallback') : null;
                   18278:             $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
                   18279:             if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
                   18280:                 $this->_downloader->popErrorHandling();
                   18281:                 return $dir;
                   18282:             }
                   18283: 
                   18284:             $this->_downloader->log(3, 'Downloading "' . $param . '"');
                   18285:             $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
                   18286:                 $dir, $callback, null, false, $this->getChannel());
                   18287:             $this->_downloader->popErrorHandling();
                   18288:             if (PEAR::isError($file)) {
                   18289:                 if (!empty($saveparam)) {
                   18290:                     $saveparam = ", cannot download \"$saveparam\"";
                   18291:                 }
                   18292:                 $err = PEAR::raiseError('Could not download from "' . $param .
                   18293:                     '"' . $saveparam . ' (' . $file->getMessage() . ')');
                   18294:                     return $err;
                   18295:             }
                   18296: 
                   18297:             if ($this->_rawpackagefile) {
                   18298:                 require_once 'Archive/Tar.php';
                   18299:                 $tar = &new Archive_Tar($file);
                   18300:                 $packagexml = $tar->extractInString('package2.xml');
                   18301:                 if (!$packagexml) {
                   18302:                     $packagexml = $tar->extractInString('package.xml');
                   18303:                 }
                   18304: 
                   18305:                 if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
                   18306:                       str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
                   18307:                     if ($this->getChannel() != 'pear.php.net') {
                   18308:                         return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
                   18309:                             'not match value returned from xml-rpc');
                   18310:                     }
                   18311: 
                   18312:                     // be more lax for the existing PEAR packages that have not-ok
                   18313:                     // characters in their package.xml
                   18314:                     $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
                   18315:                         $this->getPackage() . '" package has invalid characters in its ' .
                   18316:                         'package.xml.  The next version of PEAR may not be able to install ' .
                   18317:                         'this package for security reasons.  Please open a bug report at ' .
                   18318:                         'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
                   18319:                 }
                   18320:             }
                   18321: 
                   18322:             // whew, download worked!
                   18323:             $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
                   18324: 
                   18325:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18326:             $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
                   18327:             PEAR::popErrorHandling();
                   18328:             if (PEAR::isError($pf)) {
                   18329:                 if (is_array($pf->getUserInfo())) {
                   18330:                     foreach ($pf->getUserInfo() as $err) {
                   18331:                         if (is_array($err)) {
                   18332:                             $err = $err['message'];
                   18333:                         }
                   18334: 
                   18335:                         if (!isset($options['soft'])) {
                   18336:                             $this->_downloader->log(0, "Validation Error: $err");
                   18337:                         }
                   18338:                     }
                   18339:                 }
                   18340: 
                   18341:                 if (!isset($options['soft'])) {
                   18342:                     $this->_downloader->log(0, $pf->getMessage());
                   18343:                 }
                   18344: 
                   18345:                 ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
                   18346:                 /// At least stop all deps of this package from being installed
                   18347:                 $out = $saveparam ? $saveparam : $param;
                   18348:                 $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
                   18349:                 $this->_valid = false;
                   18350:                 return $err;
                   18351:             }
                   18352: 
                   18353:             $this->_packagefile = &$pf;
                   18354:             $this->setGroup('default'); // install the default dependency group
                   18355:             return $this->_valid = true;
                   18356:         }
                   18357: 
                   18358:         return $this->_valid = false;
                   18359:     }
                   18360: 
                   18361:     /**
                   18362:      *
                   18363:      * @param string|array pass in an array of format
                   18364:      *                     array(
                   18365:      *                      'package' => 'pname',
                   18366:      *                     ['channel' => 'channame',]
                   18367:      *                     ['version' => 'version',]
                   18368:      *                     ['state' => 'state',])
                   18369:      *                     or a string of format [channame/]pname[-version|-state]
                   18370:      */
                   18371:     function _fromString($param)
                   18372:     {
                   18373:         $options = $this->_downloader->getOptions();
                   18374:         $channel = $this->_config->get('default_channel');
                   18375:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18376:         $pname = $this->_registry->parsePackageName($param, $channel);
                   18377:         PEAR::popErrorHandling();
                   18378:         if (PEAR::isError($pname)) {
                   18379:             if ($pname->getCode() == 'invalid') {
                   18380:                 $this->_valid = false;
                   18381:                 return false;
                   18382:             }
                   18383: 
                   18384:             if ($pname->getCode() == 'channel') {
                   18385:                 $parsed = $pname->getUserInfo();
                   18386:                 if ($this->_downloader->discover($parsed['channel'])) {
                   18387:                     if ($this->_config->get('auto_discover')) {
                   18388:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18389:                         $pname = $this->_registry->parsePackageName($param, $channel);
                   18390:                         PEAR::popErrorHandling();
                   18391:                     } else {
                   18392:                         if (!isset($options['soft'])) {
                   18393:                             $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
                   18394:                                 '" is not initialized, use ' .
                   18395:                                 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
                   18396:                                 'or pear config-set auto_discover 1');
                   18397:                         }
                   18398:                     }
                   18399:                 }
                   18400: 
                   18401:                 if (PEAR::isError($pname)) {
                   18402:                     if (!isset($options['soft'])) {
                   18403:                         $this->_downloader->log(0, $pname->getMessage());
                   18404:                     }
                   18405: 
                   18406:                     if (is_array($param)) {
                   18407:                         $param = $this->_registry->parsedPackageNameToString($param);
                   18408:                     }
                   18409: 
                   18410:                     $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   18411:                     $this->_valid = false;
                   18412:                     return $err;
                   18413:                 }
                   18414:             } else {
                   18415:                 if (!isset($options['soft'])) {
                   18416:                     $this->_downloader->log(0, $pname->getMessage());
                   18417:                 }
                   18418: 
                   18419:                 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   18420:                 $this->_valid = false;
                   18421:                 return $err;
                   18422:             }
                   18423:         }
                   18424: 
                   18425:         if (!isset($this->_type)) {
                   18426:             $this->_type = 'rest';
                   18427:         }
                   18428: 
                   18429:         $this->_parsedname    = $pname;
                   18430:         $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
                   18431:         $this->_explicitGroup = isset($pname['group']) ? true : false;
                   18432: 
                   18433:         $info = $this->_downloader->_getPackageDownloadUrl($pname);
                   18434:         if (PEAR::isError($info)) {
                   18435:             if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
                   18436:                 // try pecl
                   18437:                 $pname['channel'] = 'pecl.php.net';
                   18438:                 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
                   18439:                     if (!PEAR::isError($test)) {
                   18440:                         $info = PEAR::raiseError($info->getMessage() . ' - package ' .
                   18441:                             $this->_registry->parsedPackageNameToString($pname, true) .
                   18442:                             ' can be installed with "pecl install ' . $pname['package'] .
                   18443:                             '"');
                   18444:                     } else {
                   18445:                         $pname['channel'] = 'pear.php.net';
                   18446:                     }
                   18447:                 } else {
                   18448:                     $pname['channel'] = 'pear.php.net';
                   18449:                 }
                   18450:             }
                   18451: 
                   18452:             return $info;
                   18453:         }
                   18454: 
                   18455:         $this->_rawpackagefile = $info['raw'];
                   18456:         $ret = $this->_analyzeDownloadURL($info, $param, $pname);
                   18457:         if (PEAR::isError($ret)) {
                   18458:             return $ret;
                   18459:         }
                   18460: 
                   18461:         if ($ret) {
                   18462:             $this->_downloadURL = $ret;
                   18463:             return $this->_valid = (bool) $ret;
                   18464:         }
                   18465:     }
                   18466: 
                   18467:     /**
                   18468:      * @param array output of package.getDownloadURL
                   18469:      * @param string|array|object information for detecting packages to be downloaded, and
                   18470:      *                            for errors
                   18471:      * @param array name information of the package
                   18472:      * @param array|null packages to be downloaded
                   18473:      * @param bool is this an optional dependency?
                   18474:      * @param bool is this any kind of dependency?
                   18475:      * @access private
                   18476:      */
                   18477:     function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
                   18478:                                  $isdependency = false)
                   18479:     {
                   18480:         if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
                   18481:             return false;
                   18482:         }
                   18483: 
                   18484:         if ($info === false) {
                   18485:             $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
                   18486: 
                   18487:             // no releases exist
                   18488:             return PEAR::raiseError('No releases for package "' .
                   18489:                 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
                   18490:         }
                   18491: 
                   18492:         if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
                   18493:             $err = false;
                   18494:             if ($pname['channel'] == 'pecl.php.net') {
                   18495:                 if ($info['info']->getChannel() != 'pear.php.net') {
                   18496:                     $err = true;
                   18497:                 }
                   18498:             } elseif ($info['info']->getChannel() == 'pecl.php.net') {
                   18499:                 if ($pname['channel'] != 'pear.php.net') {
                   18500:                     $err = true;
                   18501:                 }
                   18502:             } else {
                   18503:                 $err = true;
                   18504:             }
                   18505: 
                   18506:             if ($err) {
                   18507:                 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
                   18508:                     '" retrieved another channel\'s name for download! ("' .
                   18509:                     $info['info']->getChannel() . '")');
                   18510:             }
                   18511:         }
                   18512: 
                   18513:         $preferred_state = $this->_config->get('preferred_state');
                   18514:         if (!isset($info['url'])) {
                   18515:             $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
                   18516:             'version', $info['info']->getChannel());
                   18517:             if ($this->isInstalled($info)) {
                   18518:                 if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
                   18519:                     // ignore bogus errors of "failed to download dependency"
                   18520:                     // if it is already installed and the one that would be
                   18521:                     // downloaded is older or the same version (Bug #7219)
                   18522:                     return false;
                   18523:                 }
                   18524:             }
                   18525: 
                   18526:             if ($info['version'] === $package_version) {
                   18527:                 if (!isset($options['soft'])) {
                   18528:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18529:                         '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
                   18530:                         ' (' . $package_version . ') is the same as the locally installed one.');
                   18531:                 }
                   18532: 
                   18533:                 return false;
                   18534:             }
                   18535: 
                   18536:             if (version_compare($info['version'], $package_version, '<=')) {
                   18537:                 if (!isset($options['soft'])) {
                   18538:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18539:                         '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
                   18540:                         ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
                   18541:                 }
                   18542: 
                   18543:                 return false;
                   18544:             }
                   18545: 
                   18546:             $instead =  ', will instead download version ' . $info['version'] .
                   18547:                         ', stability "' . $info['info']->getState() . '"';
                   18548:             // releases exist, but we failed to get any
                   18549:             if (isset($this->_downloader->_options['force'])) {
                   18550:                 if (isset($pname['version'])) {
                   18551:                     $vs = ', version "' . $pname['version'] . '"';
                   18552:                 } elseif (isset($pname['state'])) {
                   18553:                     $vs = ', stability "' . $pname['state'] . '"';
                   18554:                 } elseif ($param == 'dependency') {
                   18555:                     if (!class_exists('PEAR_Common')) {
                   18556:                         require_once 'PEAR/Common.php';
                   18557:                     }
                   18558: 
                   18559:                     if (!in_array($info['info']->getState(),
                   18560:                           PEAR_Common::betterStates($preferred_state, true))) {
                   18561:                         if ($optional) {
                   18562:                             // don't spit out confusing error message
                   18563:                             return $this->_downloader->_getPackageDownloadUrl(
                   18564:                                 array('package' => $pname['package'],
                   18565:                                       'channel' => $pname['channel'],
                   18566:                                       'version' => $info['version']));
                   18567:                         }
                   18568:                         $vs = ' within preferred state "' . $preferred_state .
                   18569:                             '"';
                   18570:                     } else {
                   18571:                         if (!class_exists('PEAR_Dependency2')) {
                   18572:                             require_once 'PEAR/Dependency2.php';
                   18573:                         }
                   18574: 
                   18575:                         if ($optional) {
                   18576:                             // don't spit out confusing error message
                   18577:                             return $this->_downloader->_getPackageDownloadUrl(
                   18578:                                 array('package' => $pname['package'],
                   18579:                                       'channel' => $pname['channel'],
                   18580:                                       'version' => $info['version']));
                   18581:                         }
                   18582:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   18583:                         $instead = '';
                   18584:                     }
                   18585:                 } else {
                   18586:                     $vs = ' within preferred state "' . $preferred_state . '"';
                   18587:                 }
                   18588: 
                   18589:                 if (!isset($options['soft'])) {
                   18590:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18591:                         '/' . $pname['package'] . $vs . $instead);
                   18592:                 }
                   18593: 
                   18594:                 // download the latest release
                   18595:                 return $this->_downloader->_getPackageDownloadUrl(
                   18596:                     array('package' => $pname['package'],
                   18597:                           'channel' => $pname['channel'],
                   18598:                           'version' => $info['version']));
                   18599:             } else {
                   18600:                 if (isset($info['php']) && $info['php']) {
                   18601:                     $err = PEAR::raiseError('Failed to download ' .
                   18602:                         $this->_registry->parsedPackageNameToString(
                   18603:                             array('channel' => $pname['channel'],
                   18604:                                   'package' => $pname['package']),
                   18605:                                 true) .
                   18606:                         ', latest release is version ' . $info['php']['v'] .
                   18607:                         ', but it requires PHP version "' .
                   18608:                         $info['php']['m'] . '", use "' .
                   18609:                         $this->_registry->parsedPackageNameToString(
                   18610:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18611:                             'version' => $info['php']['v'])) . '" to install',
                   18612:                             PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
                   18613:                     return $err;
                   18614:                 }
                   18615: 
                   18616:                 // construct helpful error message
                   18617:                 if (isset($pname['version'])) {
                   18618:                     $vs = ', version "' . $pname['version'] . '"';
                   18619:                 } elseif (isset($pname['state'])) {
                   18620:                     $vs = ', stability "' . $pname['state'] . '"';
                   18621:                 } elseif ($param == 'dependency') {
                   18622:                     if (!class_exists('PEAR_Common')) {
                   18623:                         require_once 'PEAR/Common.php';
                   18624:                     }
                   18625: 
                   18626:                     if (!in_array($info['info']->getState(),
                   18627:                           PEAR_Common::betterStates($preferred_state, true))) {
                   18628:                         if ($optional) {
                   18629:                             // don't spit out confusing error message, and don't die on
                   18630:                             // optional dep failure!
                   18631:                             return $this->_downloader->_getPackageDownloadUrl(
                   18632:                                 array('package' => $pname['package'],
                   18633:                                       'channel' => $pname['channel'],
                   18634:                                       'version' => $info['version']));
                   18635:                         }
                   18636:                         $vs = ' within preferred state "' . $preferred_state . '"';
                   18637:                     } else {
                   18638:                         if (!class_exists('PEAR_Dependency2')) {
                   18639:                             require_once 'PEAR/Dependency2.php';
                   18640:                         }
                   18641: 
                   18642:                         if ($optional) {
                   18643:                             // don't spit out confusing error message, and don't die on
                   18644:                             // optional dep failure!
                   18645:                             return $this->_downloader->_getPackageDownloadUrl(
                   18646:                                 array('package' => $pname['package'],
                   18647:                                       'channel' => $pname['channel'],
                   18648:                                       'version' => $info['version']));
                   18649:                         }
                   18650:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   18651:                     }
                   18652:                 } else {
                   18653:                     $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
                   18654:                 }
                   18655: 
                   18656:                 $options = $this->_downloader->getOptions();
                   18657:                 // this is only set by the "download-all" command
                   18658:                 if (isset($options['ignorepreferred_state'])) {
                   18659:                     $err = PEAR::raiseError(
                   18660:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   18661:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   18662:                                 true)
                   18663:                          . $vs .
                   18664:                         ', latest release is version ' . $info['version'] .
                   18665:                         ', stability "' . $info['info']->getState() . '", use "' .
                   18666:                         $this->_registry->parsedPackageNameToString(
                   18667:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18668:                             'version' => $info['version'])) . '" to install',
                   18669:                             PEAR_DOWNLOADER_PACKAGE_STATE);
                   18670:                     return $err;
                   18671:                 }
                   18672: 
                   18673:                 // Checks if the user has a package installed already and checks the release against
                   18674:                 // the state against the installed package, this allows upgrades for packages
                   18675:                 // with lower stability than the preferred_state
                   18676:                 $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
                   18677:                 if (!$this->isInstalled($info)
                   18678:                     || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
                   18679:                 ) {
                   18680:                     $err = PEAR::raiseError(
                   18681:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   18682:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   18683:                                 true)
                   18684:                          . $vs .
                   18685:                         ', latest release is version ' . $info['version'] .
                   18686:                         ', stability "' . $info['info']->getState() . '", use "' .
                   18687:                         $this->_registry->parsedPackageNameToString(
                   18688:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18689:                             'version' => $info['version'])) . '" to install');
                   18690:                     return $err;
                   18691:                 }
                   18692:             }
                   18693:         }
                   18694: 
                   18695:         if (isset($info['deprecated']) && $info['deprecated']) {
                   18696:             $this->_downloader->log(0,
                   18697:                 'WARNING: "' .
                   18698:                     $this->_registry->parsedPackageNameToString(
                   18699:                             array('channel' => $info['info']->getChannel(),
                   18700:                                   'package' => $info['info']->getPackage()), true) .
                   18701:                 '" is deprecated in favor of "' .
                   18702:                     $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
                   18703:                 '"');
                   18704:         }
                   18705: 
                   18706:         return $info;
                   18707:     }
                   18708: }PEAR-1.9.4/PEAR/Frontend/CLI.php0000644000076500000240000006221611605156760014673 0ustar  helgistaff<?php
                   18709: /**
                   18710:  * PEAR_Frontend_CLI
                   18711:  *
                   18712:  * PHP versions 4 and 5
                   18713:  *
                   18714:  * @category   pear
                   18715:  * @package    PEAR
                   18716:  * @author     Stig Bakken <ssb@php.net>
                   18717:  * @author     Greg Beaver <cellog@php.net>
                   18718:  * @copyright  1997-2009 The Authors
                   18719:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   18720:  * @version    CVS: $Id: CLI.php 313023 2011-07-06 19:17:11Z dufuz $
                   18721:  * @link       http://pear.php.net/package/PEAR
                   18722:  * @since      File available since Release 0.1
                   18723:  */
                   18724: /**
                   18725:  * base class
                   18726:  */
                   18727: require_once 'PEAR/Frontend.php';
                   18728: 
                   18729: /**
                   18730:  * Command-line Frontend for the PEAR Installer
                   18731:  * @category   pear
                   18732:  * @package    PEAR
                   18733:  * @author     Stig Bakken <ssb@php.net>
                   18734:  * @author     Greg Beaver <cellog@php.net>
                   18735:  * @copyright  1997-2009 The Authors
                   18736:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   18737:  * @version    Release: 1.9.4
                   18738:  * @link       http://pear.php.net/package/PEAR
                   18739:  * @since      Class available since Release 0.1
                   18740:  */
                   18741: class PEAR_Frontend_CLI extends PEAR_Frontend
                   18742: {
                   18743:     /**
                   18744:      * What type of user interface this frontend is for.
                   18745:      * @var string
                   18746:      * @access public
                   18747:      */
                   18748:     var $type = 'CLI';
                   18749:     var $lp = ''; // line prefix
                   18750: 
                   18751:     var $params = array();
                   18752:     var $term = array(
                   18753:         'bold'   => '',
                   18754:         'normal' => '',
                   18755:     );
                   18756: 
                   18757:     function PEAR_Frontend_CLI()
                   18758:     {
                   18759:         parent::PEAR();
                   18760:         $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
                   18761:         if (function_exists('posix_isatty') && !posix_isatty(1)) {
                   18762:             // output is being redirected to a file or through a pipe
                   18763:         } elseif ($term) {
                   18764:             if (preg_match('/^(xterm|vt220|linux)/', $term)) {
                   18765:                 $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
                   18766:                 $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
                   18767:             } elseif (preg_match('/^vt100/', $term)) {
                   18768:                 $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
                   18769:                 $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
                   18770:             }
                   18771:         } elseif (OS_WINDOWS) {
                   18772:             // XXX add ANSI codes here
                   18773:         }
                   18774:     }
                   18775: 
                   18776:     /**
                   18777:      * @param object PEAR_Error object
                   18778:      */
                   18779:     function displayError($e)
                   18780:     {
                   18781:         return $this->_displayLine($e->getMessage());
                   18782:     }
                   18783: 
                   18784:     /**
                   18785:      * @param object PEAR_Error object
                   18786:      */
                   18787:     function displayFatalError($eobj)
                   18788:     {
                   18789:         $this->displayError($eobj);
                   18790:         if (class_exists('PEAR_Config')) {
                   18791:             $config = &PEAR_Config::singleton();
                   18792:             if ($config->get('verbose') > 5) {
                   18793:                 if (function_exists('debug_print_backtrace')) {
                   18794:                     debug_print_backtrace();
                   18795:                     exit(1);
                   18796:                 }
                   18797: 
                   18798:                 $raised = false;
                   18799:                 foreach (debug_backtrace() as $i => $frame) {
                   18800:                     if (!$raised) {
                   18801:                         if (isset($frame['class'])
                   18802:                             && strtolower($frame['class']) == 'pear'
                   18803:                             && strtolower($frame['function']) == 'raiseerror'
                   18804:                         ) {
                   18805:                             $raised = true;
                   18806:                         } else {
                   18807:                             continue;
                   18808:                         }
                   18809:                     }
                   18810: 
                   18811:                     $frame['class']    = !isset($frame['class'])    ? '' : $frame['class'];
                   18812:                     $frame['type']     = !isset($frame['type'])     ? '' : $frame['type'];
                   18813:                     $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
                   18814:                     $frame['line']     = !isset($frame['line'])     ? '' : $frame['line'];
                   18815:                     $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
                   18816:                 }
                   18817:             }
                   18818:         }
                   18819: 
                   18820:         exit(1);
                   18821:     }
                   18822: 
                   18823:     /**
                   18824:      * Instruct the runInstallScript method to skip a paramgroup that matches the
                   18825:      * id value passed in.
                   18826:      *
                   18827:      * This method is useful for dynamically configuring which sections of a post-install script
                   18828:      * will be run based on the user's setup, which is very useful for making flexible
                   18829:      * post-install scripts without losing the cross-Frontend ability to retrieve user input
                   18830:      * @param string
                   18831:      */
                   18832:     function skipParamgroup($id)
                   18833:     {
                   18834:         $this->_skipSections[$id] = true;
                   18835:     }
                   18836: 
                   18837:     function runPostinstallScripts(&$scripts)
                   18838:     {
                   18839:         foreach ($scripts as $i => $script) {
                   18840:             $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
                   18841:         }
                   18842:     }
                   18843: 
                   18844:     /**
                   18845:      * @param array $xml contents of postinstallscript tag
                   18846:      * @param object $script post-installation script
                   18847:      * @param string install|upgrade
                   18848:      */
                   18849:     function runInstallScript($xml, &$script)
                   18850:     {
                   18851:         $this->_skipSections = array();
                   18852:         if (!is_array($xml) || !isset($xml['paramgroup'])) {
                   18853:             $script->run(array(), '_default');
                   18854:             return;
                   18855:         }
                   18856: 
                   18857:         $completedPhases = array();
                   18858:         if (!isset($xml['paramgroup'][0])) {
                   18859:             $xml['paramgroup'] = array($xml['paramgroup']);
                   18860:         }
                   18861: 
                   18862:         foreach ($xml['paramgroup'] as $group) {
                   18863:             if (isset($this->_skipSections[$group['id']])) {
                   18864:                 // the post-install script chose to skip this section dynamically
                   18865:                 continue;
                   18866:             }
                   18867: 
                   18868:             if (isset($group['name'])) {
                   18869:                 $paramname = explode('::', $group['name']);
                   18870:                 if ($lastgroup['id'] != $paramname[0]) {
                   18871:                     continue;
                   18872:                 }
                   18873: 
                   18874:                 $group['name'] = $paramname[1];
                   18875:                 if (!isset($answers)) {
                   18876:                     return;
                   18877:                 }
                   18878: 
                   18879:                 if (isset($answers[$group['name']])) {
                   18880:                     switch ($group['conditiontype']) {
                   18881:                         case '=' :
                   18882:                             if ($answers[$group['name']] != $group['value']) {
                   18883:                                 continue 2;
                   18884:                             }
                   18885:                         break;
                   18886:                         case '!=' :
                   18887:                             if ($answers[$group['name']] == $group['value']) {
                   18888:                                 continue 2;
                   18889:                             }
                   18890:                         break;
                   18891:                         case 'preg_match' :
                   18892:                             if (!@preg_match('/' . $group['value'] . '/',
                   18893:                                   $answers[$group['name']])) {
                   18894:                                 continue 2;
                   18895:                             }
                   18896:                         break;
                   18897:                         default :
                   18898:                         return;
                   18899:                     }
                   18900:                 }
                   18901:             }
                   18902: 
                   18903:             $lastgroup = $group;
                   18904:             if (isset($group['instructions'])) {
                   18905:                 $this->_display($group['instructions']);
                   18906:             }
                   18907: 
                   18908:             if (!isset($group['param'][0])) {
                   18909:                 $group['param'] = array($group['param']);
                   18910:             }
                   18911: 
                   18912:             if (isset($group['param'])) {
                   18913:                 if (method_exists($script, 'postProcessPrompts')) {
                   18914:                     $prompts = $script->postProcessPrompts($group['param'], $group['id']);
                   18915:                     if (!is_array($prompts) || count($prompts) != count($group['param'])) {
                   18916:                         $this->outputData('postinstall', 'Error: post-install script did not ' .
                   18917:                             'return proper post-processed prompts');
                   18918:                         $prompts = $group['param'];
                   18919:                     } else {
                   18920:                         foreach ($prompts as $i => $var) {
                   18921:                             if (!is_array($var) || !isset($var['prompt']) ||
                   18922:                                   !isset($var['name']) ||
                   18923:                                   ($var['name'] != $group['param'][$i]['name']) ||
                   18924:                                   ($var['type'] != $group['param'][$i]['type'])
                   18925:                             ) {
                   18926:                                 $this->outputData('postinstall', 'Error: post-install script ' .
                   18927:                                     'modified the variables or prompts, severe security risk. ' .
                   18928:                                     'Will instead use the defaults from the package.xml');
                   18929:                                 $prompts = $group['param'];
                   18930:                             }
                   18931:                         }
                   18932:                     }
                   18933: 
                   18934:                     $answers = $this->confirmDialog($prompts);
                   18935:                 } else {
                   18936:                     $answers = $this->confirmDialog($group['param']);
                   18937:                 }
                   18938:             }
                   18939: 
                   18940:             if ((isset($answers) && $answers) || !isset($group['param'])) {
                   18941:                 if (!isset($answers)) {
                   18942:                     $answers = array();
                   18943:                 }
                   18944: 
                   18945:                 array_unshift($completedPhases, $group['id']);
                   18946:                 if (!$script->run($answers, $group['id'])) {
                   18947:                     $script->run($completedPhases, '_undoOnError');
                   18948:                     return;
                   18949:                 }
                   18950:             } else {
                   18951:                 $script->run($completedPhases, '_undoOnError');
                   18952:                 return;
                   18953:             }
                   18954:         }
                   18955:     }
                   18956: 
                   18957:     /**
                   18958:      * Ask for user input, confirm the answers and continue until the user is satisfied
                   18959:      * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
                   18960:      *              'text to display', 'type' => 'string'[, default => 'default value'])
                   18961:      * @return array
                   18962:      */
                   18963:     function confirmDialog($params)
                   18964:     {
                   18965:         $answers = $prompts = $types = array();
                   18966:         foreach ($params as $param) {
                   18967:             $prompts[$param['name']] = $param['prompt'];
                   18968:             $types[$param['name']]   = $param['type'];
                   18969:             $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
                   18970:         }
                   18971: 
                   18972:         $tried = false;
                   18973:         do {
                   18974:             if ($tried) {
                   18975:                 $i = 1;
                   18976:                 foreach ($answers as $var => $value) {
                   18977:                     if (!strlen($value)) {
                   18978:                         echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
                   18979:                     }
                   18980:                     $i++;
                   18981:                 }
                   18982:             }
                   18983: 
                   18984:             $answers = $this->userDialog('', $prompts, $types, $answers);
                   18985:             $tried   = true;
                   18986:         } while (is_array($answers) && count(array_filter($answers)) != count($prompts));
                   18987: 
                   18988:         return $answers;
                   18989:     }
                   18990: 
                   18991:     function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
                   18992:     {
                   18993:         if (!is_array($prompts)) {
                   18994:             return array();
                   18995:         }
                   18996: 
                   18997:         $testprompts = array_keys($prompts);
                   18998:         $result      = $defaults;
                   18999: 
                   19000:         reset($prompts);
                   19001:         if (count($prompts) === 1) {
                   19002:             foreach ($prompts as $key => $prompt) {
                   19003:                 $type    = $types[$key];
                   19004:                 $default = @$defaults[$key];
                   19005:                 print "$prompt ";
                   19006:                 if ($default) {
                   19007:                     print "[$default] ";
                   19008:                 }
                   19009:                 print ": ";
                   19010: 
                   19011:                 $line         = fgets(STDIN, 2048);
                   19012:                 $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
                   19013:             }
                   19014: 
                   19015:             return $result;
                   19016:         }
                   19017: 
                   19018:         $first_run = true;
                   19019:         while (true) {
                   19020:             $descLength = max(array_map('strlen', $prompts));
                   19021:             $descFormat = "%-{$descLength}s";
                   19022:             $last       = count($prompts);
                   19023: 
                   19024:             $i = 0;
                   19025:             foreach ($prompts as $n => $var) {
                   19026:                 $res = isset($result[$n]) ? $result[$n] : null;
                   19027:                 printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
                   19028:             }
                   19029:             print "\n1-$last, 'all', 'abort', or Enter to continue: ";
                   19030: 
                   19031:             $tmp = trim(fgets(STDIN, 1024));
                   19032:             if (empty($tmp)) {
                   19033:                 break;
                   19034:             }
                   19035: 
                   19036:             if ($tmp == 'abort') {
                   19037:                 return false;
                   19038:             }
                   19039: 
                   19040:             if (isset($testprompts[(int)$tmp - 1])) {
                   19041:                 $var     = $testprompts[(int)$tmp - 1];
                   19042:                 $desc    = $prompts[$var];
                   19043:                 $current = @$result[$var];
                   19044:                 print "$desc [$current] : ";
                   19045:                 $tmp = trim(fgets(STDIN, 1024));
                   19046:                 if ($tmp !== '') {
                   19047:                     $result[$var] = $tmp;
                   19048:                 }
                   19049:             } elseif ($tmp == 'all') {
                   19050:                 foreach ($prompts as $var => $desc) {
                   19051:                     $current = $result[$var];
                   19052:                     print "$desc [$current] : ";
                   19053:                     $tmp = trim(fgets(STDIN, 1024));
                   19054:                     if (trim($tmp) !== '') {
                   19055:                         $result[$var] = trim($tmp);
                   19056:                     }
                   19057:                 }
                   19058:             }
                   19059: 
                   19060:             $first_run = false;
                   19061:         }
                   19062: 
                   19063:         return $result;
                   19064:     }
                   19065: 
                   19066:     function userConfirm($prompt, $default = 'yes')
                   19067:     {
                   19068:         trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
                   19069:         static $positives = array('y', 'yes', 'on', '1');
                   19070:         static $negatives = array('n', 'no', 'off', '0');
                   19071:         print "$this->lp$prompt [$default] : ";
                   19072:         $fp = fopen("php://stdin", "r");
                   19073:         $line = fgets($fp, 2048);
                   19074:         fclose($fp);
                   19075:         $answer = strtolower(trim($line));
                   19076:         if (empty($answer)) {
                   19077:             $answer = $default;
                   19078:         }
                   19079:         if (in_array($answer, $positives)) {
                   19080:             return true;
                   19081:         }
                   19082:         if (in_array($answer, $negatives)) {
                   19083:             return false;
                   19084:         }
                   19085:         if (in_array($default, $positives)) {
                   19086:             return true;
                   19087:         }
                   19088:         return false;
                   19089:     }
                   19090: 
                   19091:     function outputData($data, $command = '_default')
                   19092:     {
                   19093:         switch ($command) {
                   19094:             case 'channel-info':
                   19095:                 foreach ($data as $type => $section) {
                   19096:                     if ($type == 'main') {
                   19097:                         $section['data'] = array_values($section['data']);
                   19098:                     }
                   19099: 
                   19100:                     $this->outputData($section);
                   19101:                 }
                   19102:                 break;
                   19103:             case 'install':
                   19104:             case 'upgrade':
                   19105:             case 'upgrade-all':
                   19106:                 if (is_array($data) && isset($data['release_warnings'])) {
                   19107:                     $this->_displayLine('');
                   19108:                     $this->_startTable(array(
                   19109:                         'border' => false,
                   19110:                         'caption' => 'Release Warnings'
                   19111:                     ));
                   19112:                     $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
                   19113:                     $this->_endTable();
                   19114:                     $this->_displayLine('');
                   19115:                 }
                   19116: 
                   19117:                 $this->_displayLine(is_array($data) ? $data['data'] : $data);
                   19118:                 break;
                   19119:             case 'search':
                   19120:                 $this->_startTable($data);
                   19121:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19122:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   19123:                 }
                   19124: 
                   19125:                 $packages = array();
                   19126:                 foreach($data['data'] as $category) {
                   19127:                     foreach($category as $name => $pkg) {
                   19128:                         $packages[$pkg[0]] = $pkg;
                   19129:                     }
                   19130:                 }
                   19131: 
                   19132:                 $p = array_keys($packages);
                   19133:                 natcasesort($p);
                   19134:                 foreach ($p as $name) {
                   19135:                     $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
                   19136:                 }
                   19137: 
                   19138:                 $this->_endTable();
                   19139:                 break;
                   19140:             case 'list-all':
                   19141:                 if (!isset($data['data'])) {
                   19142:                       $this->_displayLine('No packages in channel');
                   19143:                       break;
                   19144:                 }
                   19145: 
                   19146:                 $this->_startTable($data);
                   19147:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19148:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   19149:                 }
                   19150: 
                   19151:                 $packages = array();
                   19152:                 foreach($data['data'] as $category) {
                   19153:                     foreach($category as $name => $pkg) {
                   19154:                         $packages[$pkg[0]] = $pkg;
                   19155:                     }
                   19156:                 }
                   19157: 
                   19158:                 $p = array_keys($packages);
                   19159:                 natcasesort($p);
                   19160:                 foreach ($p as $name) {
                   19161:                     $pkg = $packages[$name];
                   19162:                     unset($pkg[4], $pkg[5]);
                   19163:                     $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
                   19164:                 }
                   19165: 
                   19166:                 $this->_endTable();
                   19167:                 break;
                   19168:             case 'config-show':
                   19169:                 $data['border'] = false;
                   19170:                 $opts = array(
                   19171:                     0 => array('wrap' => 30),
                   19172:                     1 => array('wrap' => 20),
                   19173:                     2 => array('wrap' => 35)
                   19174:                 );
                   19175: 
                   19176:                 $this->_startTable($data);
                   19177:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19178:                     $this->_tableRow($data['headline'], array('bold' => true), $opts);
                   19179:                 }
                   19180: 
                   19181:                 foreach ($data['data'] as $group) {
                   19182:                     foreach ($group as $value) {
                   19183:                         if ($value[2] == '') {
                   19184:                             $value[2] = "<not set>";
                   19185:                         }
                   19186: 
                   19187:                         $this->_tableRow($value, null, $opts);
                   19188:                     }
                   19189:                 }
                   19190: 
                   19191:                 $this->_endTable();
                   19192:                 break;
                   19193:             case 'remote-info':
                   19194:                 $d = $data;
                   19195:                 $data = array(
                   19196:                     'caption' => 'Package details:',
                   19197:                     'border'  => false,
                   19198:                     'data'    => array(
                   19199:                         array("Latest",      $data['stable']),
                   19200:                         array("Installed",   $data['installed']),
                   19201:                         array("Package",     $data['name']),
                   19202:                         array("License",     $data['license']),
                   19203:                         array("Category",    $data['category']),
                   19204:                         array("Summary",     $data['summary']),
                   19205:                         array("Description", $data['description']),
                   19206:                     ),
                   19207:                 );
                   19208: 
                   19209:                 if (isset($d['deprecated']) && $d['deprecated']) {
                   19210:                     $conf = &PEAR_Config::singleton();
                   19211:                     $reg = $conf->getRegistry();
                   19212:                     $name = $reg->parsedPackageNameToString($d['deprecated'], true);
                   19213:                     $data['data'][] = array('Deprecated! use', $name);
                   19214:                 }
                   19215:             default: {
                   19216:                 if (is_array($data)) {
                   19217:                     $this->_startTable($data);
                   19218:                     $count = count($data['data'][0]);
                   19219:                     if ($count == 2) {
                   19220:                         $opts = array(0 => array('wrap' => 25),
                   19221:                                       1 => array('wrap' => 48)
                   19222:                         );
                   19223:                     } elseif ($count == 3) {
                   19224:                         $opts = array(0 => array('wrap' => 30),
                   19225:                                       1 => array('wrap' => 20),
                   19226:                                       2 => array('wrap' => 35)
                   19227:                         );
                   19228:                     } else {
                   19229:                         $opts = null;
                   19230:                     }
                   19231:                     if (isset($data['headline']) && is_array($data['headline'])) {
                   19232:                         $this->_tableRow($data['headline'],
                   19233:                                          array('bold' => true),
                   19234:                                          $opts);
                   19235:                     }
                   19236: 
                   19237:                     if (is_array($data['data'])) {
                   19238:                         foreach($data['data'] as $row) {
                   19239:                             $this->_tableRow($row, null, $opts);
                   19240:                         }
                   19241:                     } else {
                   19242:                         $this->_tableRow(array($data['data']), null, $opts);
                   19243:                      }
                   19244:                     $this->_endTable();
                   19245:                 } else {
                   19246:                     $this->_displayLine($data);
                   19247:                 }
                   19248:             }
                   19249:         }
                   19250:     }
                   19251: 
                   19252:     function log($text, $append_crlf = true)
                   19253:     {
                   19254:         if ($append_crlf) {
                   19255:             return $this->_displayLine($text);
                   19256:         }
                   19257: 
                   19258:         return $this->_display($text);
                   19259:     }
                   19260: 
                   19261:     function bold($text)
                   19262:     {
                   19263:         if (empty($this->term['bold'])) {
                   19264:             return strtoupper($text);
                   19265:         }
                   19266: 
                   19267:         return $this->term['bold'] . $text . $this->term['normal'];
                   19268:     }
                   19269: 
                   19270:     function _displayHeading($title)
                   19271:     {
                   19272:         print $this->lp.$this->bold($title)."\n";
                   19273:         print $this->lp.str_repeat("=", strlen($title))."\n";
                   19274:     }
                   19275: 
                   19276:     function _startTable($params = array())
                   19277:     {
                   19278:         $params['table_data'] = array();
                   19279:         $params['widest']     = array();  // indexed by column
                   19280:         $params['highest']    = array(); // indexed by row
                   19281:         $params['ncols']      = 0;
                   19282:         $this->params         = $params;
                   19283:     }
                   19284: 
                   19285:     function _tableRow($columns, $rowparams = array(), $colparams = array())
                   19286:     {
                   19287:         $highest = 1;
                   19288:         for ($i = 0; $i < count($columns); $i++) {
                   19289:             $col = &$columns[$i];
                   19290:             if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
                   19291:                 $col = wordwrap($col, $colparams[$i]['wrap']);
                   19292:             }
                   19293: 
                   19294:             if (strpos($col, "\n") !== false) {
                   19295:                 $multiline = explode("\n", $col);
                   19296:                 $w = 0;
                   19297:                 foreach ($multiline as $n => $line) {
                   19298:                     $len = strlen($line);
                   19299:                     if ($len > $w) {
                   19300:                         $w = $len;
                   19301:                     }
                   19302:                 }
                   19303:                 $lines = count($multiline);
                   19304:             } else {
                   19305:                 $w = strlen($col);
                   19306:             }
                   19307: 
                   19308:             if (isset($this->params['widest'][$i])) {
                   19309:                 if ($w > $this->params['widest'][$i]) {
                   19310:                     $this->params['widest'][$i] = $w;
                   19311:                 }
                   19312:             } else {
                   19313:                 $this->params['widest'][$i] = $w;
                   19314:             }
                   19315: 
                   19316:             $tmp = count_chars($columns[$i], 1);
                   19317:             // handle unix, mac and windows formats
                   19318:             $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
                   19319:             if ($lines > $highest) {
                   19320:                 $highest = $lines;
                   19321:             }
                   19322:         }
                   19323: 
                   19324:         if (count($columns) > $this->params['ncols']) {
                   19325:             $this->params['ncols'] = count($columns);
                   19326:         }
                   19327: 
                   19328:         $new_row = array(
                   19329:             'data'      => $columns,
                   19330:             'height'    => $highest,
                   19331:             'rowparams' => $rowparams,
                   19332:             'colparams' => $colparams,
                   19333:         );
                   19334:         $this->params['table_data'][] = $new_row;
                   19335:     }
                   19336: 
                   19337:     function _endTable()
                   19338:     {
                   19339:         extract($this->params);
                   19340:         if (!empty($caption)) {
                   19341:             $this->_displayHeading($caption);
                   19342:         }
                   19343: 
                   19344:         if (count($table_data) === 0) {
                   19345:             return;
                   19346:         }
                   19347: 
                   19348:         if (!isset($width)) {
                   19349:             $width = $widest;
                   19350:         } else {
                   19351:             for ($i = 0; $i < $ncols; $i++) {
                   19352:                 if (!isset($width[$i])) {
                   19353:                     $width[$i] = $widest[$i];
                   19354:                 }
                   19355:             }
                   19356:         }
                   19357: 
                   19358:         $border = false;
                   19359:         if (empty($border)) {
                   19360:             $cellstart  = '';
                   19361:             $cellend    = ' ';
                   19362:             $rowend     = '';
                   19363:             $padrowend  = false;
                   19364:             $borderline = '';
                   19365:         } else {
                   19366:             $cellstart  = '| ';
                   19367:             $cellend    = ' ';
                   19368:             $rowend     = '|';
                   19369:             $padrowend  = true;
                   19370:             $borderline = '+';
                   19371:             foreach ($width as $w) {
                   19372:                 $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
                   19373:                 $borderline .= '+';
                   19374:             }
                   19375:         }
                   19376: 
                   19377:         if ($borderline) {
                   19378:             $this->_displayLine($borderline);
                   19379:         }
                   19380: 
                   19381:         for ($i = 0; $i < count($table_data); $i++) {
                   19382:             extract($table_data[$i]);
                   19383:             if (!is_array($rowparams)) {
                   19384:                 $rowparams = array();
                   19385:             }
                   19386: 
                   19387:             if (!is_array($colparams)) {
                   19388:                 $colparams = array();
                   19389:             }
                   19390: 
                   19391:             $rowlines = array();
                   19392:             if ($height > 1) {
                   19393:                 for ($c = 0; $c < count($data); $c++) {
                   19394:                     $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
                   19395:                     if (count($rowlines[$c]) < $height) {
                   19396:                         $rowlines[$c] = array_pad($rowlines[$c], $height, '');
                   19397:                     }
                   19398:                 }
                   19399:             } else {
                   19400:                 for ($c = 0; $c < count($data); $c++) {
                   19401:                     $rowlines[$c] = array($data[$c]);
                   19402:                 }
                   19403:             }
                   19404: 
                   19405:             for ($r = 0; $r < $height; $r++) {
                   19406:                 $rowtext = '';
                   19407:                 for ($c = 0; $c < count($data); $c++) {
                   19408:                     if (isset($colparams[$c])) {
                   19409:                         $attribs = array_merge($rowparams, $colparams);
                   19410:                     } else {
                   19411:                         $attribs = $rowparams;
                   19412:                     }
                   19413: 
                   19414:                     $w = isset($width[$c]) ? $width[$c] : 0;
                   19415:                     //$cell = $data[$c];
                   19416:                     $cell = $rowlines[$c][$r];
                   19417:                     $l = strlen($cell);
                   19418:                     if ($l > $w) {
                   19419:                         $cell = substr($cell, 0, $w);
                   19420:                     }
                   19421: 
                   19422:                     if (isset($attribs['bold'])) {
                   19423:                         $cell = $this->bold($cell);
                   19424:                     }
                   19425: 
                   19426:                     if ($l < $w) {
                   19427:                         // not using str_pad here because we may
                   19428:                         // add bold escape characters to $cell
                   19429:                         $cell .= str_repeat(' ', $w - $l);
                   19430:                     }
                   19431: 
                   19432:                     $rowtext .= $cellstart . $cell . $cellend;
                   19433:                 }
                   19434: 
                   19435:                 if (!$border) {
                   19436:                     $rowtext = rtrim($rowtext);
                   19437:                 }
                   19438: 
                   19439:                 $rowtext .= $rowend;
                   19440:                 $this->_displayLine($rowtext);
                   19441:             }
                   19442:         }
                   19443: 
                   19444:         if ($borderline) {
                   19445:             $this->_displayLine($borderline);
                   19446:         }
                   19447:     }
                   19448: 
                   19449:     function _displayLine($text)
                   19450:     {
                   19451:         print "$this->lp$text\n";
                   19452:     }
                   19453: 
                   19454:     function _display($text)
                   19455:     {
                   19456:         print $text;
                   19457:     }
                   19458: }PEAR-1.9.4/PEAR/Installer/Role/Common.php0000644000076500000240000001423311605156760016567 0ustar  helgistaff<?php
                   19459: /**
                   19460:  * Base class for all installation roles.
                   19461:  *
                   19462:  * PHP versions 4 and 5
                   19463:  *
                   19464:  * @category   pear
                   19465:  * @package    PEAR
                   19466:  * @author     Greg Beaver <cellog@php.net>
                   19467:  * @copyright  1997-2006 The PHP Group
                   19468:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19469:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   19470:  * @link       http://pear.php.net/package/PEAR
                   19471:  * @since      File available since Release 1.4.0a1
                   19472:  */
                   19473: /**
                   19474:  * Base class for all installation roles.
                   19475:  *
                   19476:  * This class allows extensibility of file roles.  Packages with complex
                   19477:  * customization can now provide custom file roles along with the possibility of
                   19478:  * adding configuration values to match.
                   19479:  * @category   pear
                   19480:  * @package    PEAR
                   19481:  * @author     Greg Beaver <cellog@php.net>
                   19482:  * @copyright  1997-2006 The PHP Group
                   19483:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19484:  * @version    Release: 1.9.4
                   19485:  * @link       http://pear.php.net/package/PEAR
                   19486:  * @since      Class available since Release 1.4.0a1
                   19487:  */
                   19488: class PEAR_Installer_Role_Common
                   19489: {
                   19490:     /**
                   19491:      * @var PEAR_Config
                   19492:      * @access protected
                   19493:      */
                   19494:     var $config;
                   19495: 
                   19496:     /**
                   19497:      * @param PEAR_Config
                   19498:      */
                   19499:     function PEAR_Installer_Role_Common(&$config)
                   19500:     {
                   19501:         $this->config = $config;
                   19502:     }
                   19503: 
                   19504:     /**
                   19505:      * Retrieve configuration information about a file role from its XML info
                   19506:      *
                   19507:      * @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
                   19508:      * @return array
                   19509:      */
                   19510:     function getInfo($role)
                   19511:     {
                   19512:         if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
                   19513:             return PEAR::raiseError('Unknown Role class: "' . $role . '"');
                   19514:         }
                   19515:         return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
                   19516:     }
                   19517: 
                   19518:     /**
                   19519:      * This is called for each file to set up the directories and files
                   19520:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   19521:      * @param array attributes from the <file> tag
                   19522:      * @param string file name
                   19523:      * @return array an array consisting of:
                   19524:      *
                   19525:      *    1 the original, pre-baseinstalldir installation directory
                   19526:      *    2 the final installation directory
                   19527:      *    3 the full path to the final location of the file
                   19528:      *    4 the location of the pre-installation file
                   19529:      */
                   19530:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
                   19531:     {
                   19532:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19533:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19534:         if (PEAR::isError($roleInfo)) {
                   19535:             return $roleInfo;
                   19536:         }
                   19537:         if (!$roleInfo['locationconfig']) {
                   19538:             return false;
                   19539:         }
                   19540:         if ($roleInfo['honorsbaseinstall']) {
                   19541:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
                   19542:                 $pkg->getChannel());
                   19543:             if (!empty($atts['baseinstalldir'])) {
                   19544:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   19545:             }
                   19546:         } elseif ($roleInfo['unusualbaseinstall']) {
                   19547:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                   19548:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   19549:             if (!empty($atts['baseinstalldir'])) {
                   19550:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   19551:             }
                   19552:         } else {
                   19553:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                   19554:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   19555:         }
                   19556:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   19557:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   19558:         }
                   19559:         if (empty($atts['install-as'])) {
                   19560:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   19561:         } else {
                   19562:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   19563:         }
                   19564:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   19565: 
                   19566:         // Clean up the DIRECTORY_SEPARATOR mess
                   19567:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   19568:         
                   19569:         list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   19570:                                                     array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
                   19571:                                                           DIRECTORY_SEPARATOR),
                   19572:                                                     array($dest_dir, $dest_file, $orig_file));
                   19573:         return array($save_destdir, $dest_dir, $dest_file, $orig_file);
                   19574:     }
                   19575: 
                   19576:     /**
                   19577:      * Get the name of the configuration variable that specifies the location of this file
                   19578:      * @return string|false
                   19579:      */
                   19580:     function getLocationConfig()
                   19581:     {
                   19582:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19583:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19584:         if (PEAR::isError($roleInfo)) {
                   19585:             return $roleInfo;
                   19586:         }
                   19587:         return $roleInfo['locationconfig'];
                   19588:     }
                   19589: 
                   19590:     /**
                   19591:      * Do any unusual setup here
                   19592:      * @param PEAR_Installer
                   19593:      * @param PEAR_PackageFile_v2
                   19594:      * @param array file attributes
                   19595:      * @param string file name
                   19596:      */
                   19597:     function setup(&$installer, $pkg, $atts, $file)
                   19598:     {
                   19599:     }
                   19600: 
                   19601:     function isExecutable()
                   19602:     {
                   19603:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19604:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19605:         if (PEAR::isError($roleInfo)) {
                   19606:             return $roleInfo;
                   19607:         }
                   19608:         return $roleInfo['executable'];
                   19609:     }
                   19610: 
                   19611:     function isInstallable()
                   19612:     {
                   19613:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19614:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19615:         if (PEAR::isError($roleInfo)) {
                   19616:             return $roleInfo;
                   19617:         }
                   19618:         return $roleInfo['installable'];
                   19619:     }
                   19620: 
                   19621:     function isExtension()
                   19622:     {
                   19623:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19624:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19625:         if (PEAR::isError($roleInfo)) {
                   19626:             return $roleInfo;
                   19627:         }
                   19628:         return $roleInfo['phpextension'];
                   19629:     }
                   19630: }
                   19631: ?>PEAR-1.9.4/PEAR/Installer/Role/Cfg.xml0000644000076500000240000000064511605156760016051 0ustar  helgistaff<role version="1.0">
                   19632:  <releasetypes>php</releasetypes>
                   19633:  <releasetypes>extsrc</releasetypes>
                   19634:  <releasetypes>extbin</releasetypes>
                   19635:  <releasetypes>zendextsrc</releasetypes>
                   19636:  <releasetypes>zendextbin</releasetypes>
                   19637:  <installable>1</installable>
                   19638:  <locationconfig>cfg_dir</locationconfig>
                   19639:  <honorsbaseinstall />
                   19640:  <unusualbaseinstall>1</unusualbaseinstall>
                   19641:  <phpfile />
                   19642:  <executable />
                   19643:  <phpextension />
                   19644:  <config_vars />
                   19645: </role>PEAR-1.9.4/PEAR/Installer/Role/Cfg.php0000644000076500000240000000770211605156760016041 0ustar  helgistaff<?php
                   19646: /**
                   19647:  * PEAR_Installer_Role_Cfg
                   19648:  *
                   19649:  * PHP versions 4 and 5
                   19650:  *
                   19651:  * @category   pear
                   19652:  * @package    PEAR
                   19653:  * @author     Greg Beaver <cellog@php.net>
                   19654:  * @copyright  2007-2009 The Authors
                   19655:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19656:  * @version    CVS: $Id: Cfg.php 313023 2011-07-06 19:17:11Z dufuz $
                   19657:  * @link       http://pear.php.net/package/PEAR
                   19658:  * @since      File available since Release 1.7.0
                   19659:  */
                   19660: 
                   19661: /**
                   19662:  * @category   pear
                   19663:  * @package    PEAR
                   19664:  * @author     Greg Beaver <cellog@php.net>
                   19665:  * @copyright  2007-2009 The Authors
                   19666:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19667:  * @version    Release: 1.9.4
                   19668:  * @link       http://pear.php.net/package/PEAR
                   19669:  * @since      Class available since Release 1.7.0
                   19670:  */
                   19671: class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
                   19672: {
                   19673:     /**
                   19674:      * @var PEAR_Installer
                   19675:      */
                   19676:     var $installer;
                   19677: 
                   19678:     /**
                   19679:      * the md5 of the original file
                   19680:      *
                   19681:      * @var unknown_type
                   19682:      */
                   19683:     var $md5 = null;
                   19684: 
                   19685:     /**
                   19686:      * Do any unusual setup here
                   19687:      * @param PEAR_Installer
                   19688:      * @param PEAR_PackageFile_v2
                   19689:      * @param array file attributes
                   19690:      * @param string file name
                   19691:      */
                   19692:     function setup(&$installer, $pkg, $atts, $file)
                   19693:     {
                   19694:         $this->installer = &$installer;
                   19695:         $reg = &$this->installer->config->getRegistry();
                   19696:         $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
                   19697:         if ($package) {
                   19698:             $filelist = $package->getFilelist();
                   19699:             if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
                   19700:                 $this->md5 = $filelist[$file]['md5sum'];
                   19701:             }
                   19702:         }
                   19703:     }
                   19704: 
                   19705:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
                   19706:     {
                   19707:         $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
                   19708:         if (@file_exists($test[2]) && @file_exists($test[3])) {
                   19709:             $md5 = md5_file($test[2]);
                   19710:             // configuration has already been installed, check for mods
                   19711:             if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
                   19712:                 // configuration has been modified, so save our version as
                   19713:                 // configfile-version
                   19714:                 $old = $test[2];
                   19715:                 $test[2] .= '.new-' . $pkg->getVersion();
                   19716:                 // backup original and re-install it
                   19717:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   19718:                 $tmpcfg = $this->config->get('temp_dir');
                   19719:                 $newloc = System::mkdir(array('-p', $tmpcfg));
                   19720:                 if (!$newloc) {
                   19721:                     // try temp_dir
                   19722:                     $newloc = System::mktemp(array('-d'));
                   19723:                     if (!$newloc || PEAR::isError($newloc)) {
                   19724:                         PEAR::popErrorHandling();
                   19725:                         return PEAR::raiseError('Could not save existing configuration file '.
                   19726:                             $old . ', unable to install.  Please set temp_dir ' .
                   19727:                             'configuration variable to a writeable location and try again');
                   19728:                     }
                   19729:                 } else {
                   19730:                     $newloc = $tmpcfg;
                   19731:                 }
                   19732: 
                   19733:                 $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
                   19734:                 if (!@copy($old, $temp_file)) {
                   19735:                     PEAR::popErrorHandling();
                   19736:                     return PEAR::raiseError('Could not save existing configuration file '.
                   19737:                         $old . ', unable to install.  Please set temp_dir ' .
                   19738:                         'configuration variable to a writeable location and try again');
                   19739:                 }
                   19740: 
                   19741:                 PEAR::popErrorHandling();
                   19742:                 $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");
                   19743:                 $this->installer->addFileOperation('rename', array($temp_file, $old, false));
                   19744:                 $this->installer->addFileOperation('delete', array($temp_file));
                   19745:             }
                   19746:         }
                   19747: 
                   19748:         return $test;
                   19749:     }
                   19750: }PEAR-1.9.4/PEAR/Installer/Role/Data.xml0000644000076500000240000000062211605156760016216 0ustar  helgistaff<role version="1.0">
                   19751:  <releasetypes>php</releasetypes>
                   19752:  <releasetypes>extsrc</releasetypes>
                   19753:  <releasetypes>extbin</releasetypes>
                   19754:  <releasetypes>zendextsrc</releasetypes>
                   19755:  <releasetypes>zendextbin</releasetypes>
                   19756:  <installable>1</installable>
                   19757:  <locationconfig>data_dir</locationconfig>
                   19758:  <honorsbaseinstall />
                   19759:  <unusualbaseinstall />
                   19760:  <phpfile />
                   19761:  <executable />
                   19762:  <phpextension />
                   19763:  <config_vars />
                   19764: </role>PEAR-1.9.4/PEAR/Installer/Role/Data.php0000644000076500000240000000152311605156760016206 0ustar  helgistaff<?php
                   19765: /**
                   19766:  * PEAR_Installer_Role_Data
                   19767:  *
                   19768:  * PHP versions 4 and 5
                   19769:  *
                   19770:  * @category   pear
                   19771:  * @package    PEAR
                   19772:  * @author     Greg Beaver <cellog@php.net>
                   19773:  * @copyright  1997-2009 The Authors
                   19774:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19775:  * @version    CVS: $Id: Data.php 313023 2011-07-06 19:17:11Z dufuz $
                   19776:  * @link       http://pear.php.net/package/PEAR
                   19777:  * @since      File available since Release 1.4.0a1
                   19778:  */
                   19779: 
                   19780: /**
                   19781:  * @category   pear
                   19782:  * @package    PEAR
                   19783:  * @author     Greg Beaver <cellog@php.net>
                   19784:  * @copyright  1997-2009 The Authors
                   19785:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19786:  * @version    Release: 1.9.4
                   19787:  * @link       http://pear.php.net/package/PEAR
                   19788:  * @since      Class available since Release 1.4.0a1
                   19789:  */
                   19790: class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
                   19791: ?>PEAR-1.9.4/PEAR/Installer/Role/Doc.xml0000644000076500000240000000062111605156760016051 0ustar  helgistaff<role version="1.0">
                   19792:  <releasetypes>php</releasetypes>
                   19793:  <releasetypes>extsrc</releasetypes>
                   19794:  <releasetypes>extbin</releasetypes>
                   19795:  <releasetypes>zendextsrc</releasetypes>
                   19796:  <releasetypes>zendextbin</releasetypes>
                   19797:  <installable>1</installable>
                   19798:  <locationconfig>doc_dir</locationconfig>
                   19799:  <honorsbaseinstall />
                   19800:  <unusualbaseinstall />
                   19801:  <phpfile />
                   19802:  <executable />
                   19803:  <phpextension />
                   19804:  <config_vars />
                   19805: </role>PEAR-1.9.4/PEAR/Installer/Role/Doc.php0000644000076500000240000000152011605156760016037 0ustar  helgistaff<?php
                   19806: /**
                   19807:  * PEAR_Installer_Role_Doc
                   19808:  *
                   19809:  * PHP versions 4 and 5
                   19810:  *
                   19811:  * @category   pear
                   19812:  * @package    PEAR
                   19813:  * @author     Greg Beaver <cellog@php.net>
                   19814:  * @copyright  1997-2009 The Authors
                   19815:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19816:  * @version    CVS: $Id: Doc.php 313023 2011-07-06 19:17:11Z dufuz $
                   19817:  * @link       http://pear.php.net/package/PEAR
                   19818:  * @since      File available since Release 1.4.0a1
                   19819:  */
                   19820: 
                   19821: /**
                   19822:  * @category   pear
                   19823:  * @package    PEAR
                   19824:  * @author     Greg Beaver <cellog@php.net>
                   19825:  * @copyright  1997-2009 The Authors
                   19826:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19827:  * @version    Release: 1.9.4
                   19828:  * @link       http://pear.php.net/package/PEAR
                   19829:  * @since      Class available since Release 1.4.0a1
                   19830:  */
                   19831: class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
                   19832: ?>PEAR-1.9.4/PEAR/Installer/Role/Ext.xml0000644000076500000240000000050211605156760016102 0ustar  helgistaff<role version="1.0">
                   19833:  <releasetypes>extbin</releasetypes>
                   19834:  <releasetypes>zendextbin</releasetypes>
                   19835:  <installable>1</installable>
                   19836:  <locationconfig>ext_dir</locationconfig>
                   19837:  <honorsbaseinstall>1</honorsbaseinstall>
                   19838:  <unusualbaseinstall />
                   19839:  <phpfile />
                   19840:  <executable />
                   19841:  <phpextension>1</phpextension>
                   19842:  <config_vars />
                   19843: </role>PEAR-1.9.4/PEAR/Installer/Role/Ext.php0000644000076500000240000000152011605156760016072 0ustar  helgistaff<?php
                   19844: /**
                   19845:  * PEAR_Installer_Role_Ext
                   19846:  *
                   19847:  * PHP versions 4 and 5
                   19848:  *
                   19849:  * @category   pear
                   19850:  * @package    PEAR
                   19851:  * @author     Greg Beaver <cellog@php.net>
                   19852:  * @copyright  1997-2009 The Authors
                   19853:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19854:  * @version    CVS: $Id: Ext.php 313023 2011-07-06 19:17:11Z dufuz $
                   19855:  * @link       http://pear.php.net/package/PEAR
                   19856:  * @since      File available since Release 1.4.0a1
                   19857:  */
                   19858: 
                   19859: /**
                   19860:  * @category   pear
                   19861:  * @package    PEAR
                   19862:  * @author     Greg Beaver <cellog@php.net>
                   19863:  * @copyright  1997-2009 The Authors
                   19864:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19865:  * @version    Release: 1.9.4
                   19866:  * @link       http://pear.php.net/package/PEAR
                   19867:  * @since      Class available since Release 1.4.0a1
                   19868:  */
                   19869: class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
                   19870: ?>PEAR-1.9.4/PEAR/Installer/Role/Php.xml0000644000076500000240000000065511605156760016102 0ustar  helgistaff<role version="1.0">
                   19871:  <releasetypes>php</releasetypes>
                   19872:  <releasetypes>extsrc</releasetypes>
                   19873:  <releasetypes>extbin</releasetypes>
                   19874:  <releasetypes>zendextsrc</releasetypes>
                   19875:  <releasetypes>zendextbin</releasetypes>
                   19876:  <installable>1</installable>
                   19877:  <locationconfig>php_dir</locationconfig>
                   19878:  <honorsbaseinstall>1</honorsbaseinstall>
                   19879:  <unusualbaseinstall />
                   19880:  <phpfile>1</phpfile>
                   19881:  <executable />
                   19882:  <phpextension />
                   19883:  <config_vars />
                   19884: </role>PEAR-1.9.4/PEAR/Installer/Role/Php.php0000644000076500000240000000152011605156760016061 0ustar  helgistaff<?php
                   19885: /**
                   19886:  * PEAR_Installer_Role_Php
                   19887:  *
                   19888:  * PHP versions 4 and 5
                   19889:  *
                   19890:  * @category   pear
                   19891:  * @package    PEAR
                   19892:  * @author     Greg Beaver <cellog@php.net>
                   19893:  * @copyright  1997-2009 The Authors
                   19894:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19895:  * @version    CVS: $Id: Php.php 313023 2011-07-06 19:17:11Z dufuz $
                   19896:  * @link       http://pear.php.net/package/PEAR
                   19897:  * @since      File available since Release 1.4.0a1
                   19898:  */
                   19899: 
                   19900: /**
                   19901:  * @category   pear
                   19902:  * @package    PEAR
                   19903:  * @author     Greg Beaver <cellog@php.net>
                   19904:  * @copyright  1997-2009 The Authors
                   19905:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19906:  * @version    Release: 1.9.4
                   19907:  * @link       http://pear.php.net/package/PEAR
                   19908:  * @since      Class available since Release 1.4.0a1
                   19909:  */
                   19910: class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
                   19911: ?>PEAR-1.9.4/PEAR/Installer/Role/Script.xml0000644000076500000240000000066011605156760016613 0ustar  helgistaff<role version="1.0">
                   19912:  <releasetypes>php</releasetypes>
                   19913:  <releasetypes>extsrc</releasetypes>
                   19914:  <releasetypes>extbin</releasetypes>
                   19915:  <releasetypes>zendextsrc</releasetypes>
                   19916:  <releasetypes>zendextbin</releasetypes>
                   19917:  <installable>1</installable>
                   19918:  <locationconfig>bin_dir</locationconfig>
                   19919:  <honorsbaseinstall>1</honorsbaseinstall>
                   19920:  <unusualbaseinstall />
                   19921:  <phpfile />
                   19922:  <executable>1</executable>
                   19923:  <phpextension />
                   19924:  <config_vars />
                   19925: </role>PEAR-1.9.4/PEAR/Installer/Role/Script.php0000644000076500000240000000153111605156760016600 0ustar  helgistaff<?php
                   19926: /**
                   19927:  * PEAR_Installer_Role_Script
                   19928:  *
                   19929:  * PHP versions 4 and 5
                   19930:  *
                   19931:  * @category   pear
                   19932:  * @package    PEAR
                   19933:  * @author     Greg Beaver <cellog@php.net>
                   19934:  * @copyright  1997-2009 The Authors
                   19935:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19936:  * @version    CVS: $Id: Script.php 313023 2011-07-06 19:17:11Z dufuz $
                   19937:  * @link       http://pear.php.net/package/PEAR
                   19938:  * @since      File available since Release 1.4.0a1
                   19939:  */
                   19940: 
                   19941: /**
                   19942:  * @category   pear
                   19943:  * @package    PEAR
                   19944:  * @author     Greg Beaver <cellog@php.net>
                   19945:  * @copyright  1997-2009 The Authors
                   19946:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19947:  * @version    Release: 1.9.4
                   19948:  * @link       http://pear.php.net/package/PEAR
                   19949:  * @since      Class available since Release 1.4.0a1
                   19950:  */
                   19951: class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
                   19952: ?>PEAR-1.9.4/PEAR/Installer/Role/Src.xml0000644000076500000240000000044211605156760016074 0ustar  helgistaff<role version="1.0">
                   19953:  <releasetypes>extsrc</releasetypes>
                   19954:  <releasetypes>zendextsrc</releasetypes>
                   19955:  <installable>1</installable>
                   19956:  <locationconfig>temp_dir</locationconfig>
                   19957:  <honorsbaseinstall />
                   19958:  <unusualbaseinstall />
                   19959:  <phpfile />
                   19960:  <executable />
                   19961:  <phpextension />
                   19962:  <config_vars />
                   19963: </role>PEAR-1.9.4/PEAR/Installer/Role/Src.php0000644000076500000240000000166511605156760016073 0ustar  helgistaff<?php
                   19964: /**
                   19965:  * PEAR_Installer_Role_Src
                   19966:  *
                   19967:  * PHP versions 4 and 5
                   19968:  *
                   19969:  * @category   pear
                   19970:  * @package    PEAR
                   19971:  * @author     Greg Beaver <cellog@php.net>
                   19972:  * @copyright  1997-2009 The Authors
                   19973:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19974:  * @version    CVS: $Id: Src.php 313023 2011-07-06 19:17:11Z dufuz $
                   19975:  * @link       http://pear.php.net/package/PEAR
                   19976:  * @since      File available since Release 1.4.0a1
                   19977:  */
                   19978: 
                   19979: /**
                   19980:  * @category   pear
                   19981:  * @package    PEAR
                   19982:  * @author     Greg Beaver <cellog@php.net>
                   19983:  * @copyright  1997-2009 The Authors
                   19984:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19985:  * @version    Release: 1.9.4
                   19986:  * @link       http://pear.php.net/package/PEAR
                   19987:  * @since      Class available since Release 1.4.0a1
                   19988:  */
                   19989: class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
                   19990: {
                   19991:     function setup(&$installer, $pkg, $atts, $file)
                   19992:     {
                   19993:         $installer->source_files++;
                   19994:     }
                   19995: }
                   19996: ?>PEAR-1.9.4/PEAR/Installer/Role/Test.xml0000644000076500000240000000062211605156760016264 0ustar  helgistaff<role version="1.0">
                   19997:  <releasetypes>php</releasetypes>
                   19998:  <releasetypes>extsrc</releasetypes>
                   19999:  <releasetypes>extbin</releasetypes>
                   20000:  <releasetypes>zendextsrc</releasetypes>
                   20001:  <releasetypes>zendextbin</releasetypes>
                   20002:  <installable>1</installable>
                   20003:  <locationconfig>test_dir</locationconfig>
                   20004:  <honorsbaseinstall />
                   20005:  <unusualbaseinstall />
                   20006:  <phpfile />
                   20007:  <executable />
                   20008:  <phpextension />
                   20009:  <config_vars />
                   20010: </role>PEAR-1.9.4/PEAR/Installer/Role/Test.php0000644000076500000240000000152311605156760016254 0ustar  helgistaff<?php
                   20011: /**
                   20012:  * PEAR_Installer_Role_Test
                   20013:  *
                   20014:  * PHP versions 4 and 5
                   20015:  *
                   20016:  * @category   pear
                   20017:  * @package    PEAR
                   20018:  * @author     Greg Beaver <cellog@php.net>
                   20019:  * @copyright  1997-2009 The Authors
                   20020:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20021:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
                   20022:  * @link       http://pear.php.net/package/PEAR
                   20023:  * @since      File available since Release 1.4.0a1
                   20024:  */
                   20025: 
                   20026: /**
                   20027:  * @category   pear
                   20028:  * @package    PEAR
                   20029:  * @author     Greg Beaver <cellog@php.net>
                   20030:  * @copyright  1997-2009 The Authors
                   20031:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20032:  * @version    Release: 1.9.4
                   20033:  * @link       http://pear.php.net/package/PEAR
                   20034:  * @since      Class available since Release 1.4.0a1
                   20035:  */
                   20036: class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
                   20037: ?>PEAR-1.9.4/PEAR/Installer/Role/Www.xml0000644000076500000240000000064411605156760016135 0ustar  helgistaff<role version="1.0">
                   20038:  <releasetypes>php</releasetypes>
                   20039:  <releasetypes>extsrc</releasetypes>
                   20040:  <releasetypes>extbin</releasetypes>
                   20041:  <releasetypes>zendextsrc</releasetypes>
                   20042:  <releasetypes>zendextbin</releasetypes>
                   20043:  <installable>1</installable>
                   20044:  <locationconfig>www_dir</locationconfig>
                   20045:  <honorsbaseinstall>1</honorsbaseinstall>
                   20046:  <unusualbaseinstall />
                   20047:  <phpfile />
                   20048:  <executable />
                   20049:  <phpextension />
                   20050:  <config_vars />
                   20051: </role>PEAR-1.9.4/PEAR/Installer/Role/Www.php0000644000076500000240000000151411605156760016121 0ustar  helgistaff<?php
                   20052: /**
                   20053:  * PEAR_Installer_Role_Www
                   20054:  *
                   20055:  * PHP versions 4 and 5
                   20056:  *
                   20057:  * @category   pear
                   20058:  * @package    PEAR
                   20059:  * @author     Greg Beaver <cellog@php.net>
                   20060:  * @copyright  2007-2009 The Authors
                   20061:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20062:  * @version    CVS: $Id: Www.php 313023 2011-07-06 19:17:11Z dufuz $
                   20063:  * @link       http://pear.php.net/package/PEAR
                   20064:  * @since      File available since Release 1.7.0
                   20065:  */
                   20066: 
                   20067: /**
                   20068:  * @category   pear
                   20069:  * @package    PEAR
                   20070:  * @author     Greg Beaver <cellog@php.net>
                   20071:  * @copyright  2007-2009 The Authors
                   20072:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20073:  * @version    Release: 1.9.4
                   20074:  * @link       http://pear.php.net/package/PEAR
                   20075:  * @since      Class available since Release 1.7.0
                   20076:  */
                   20077: class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
                   20078: ?>PEAR-1.9.4/PEAR/Installer/Role.php0000644000076500000240000001746411605156760015350 0ustar  helgistaff<?php
                   20079: /**
                   20080:  * PEAR_Installer_Role
                   20081:  *
                   20082:  * PHP versions 4 and 5
                   20083:  *
                   20084:  * @category   pear
                   20085:  * @package    PEAR
                   20086:  * @author     Greg Beaver <cellog@php.net>
                   20087:  * @copyright  1997-2009 The Authors
                   20088:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20089:  * @version    CVS: $Id: Role.php 313023 2011-07-06 19:17:11Z dufuz $
                   20090:  * @link       http://pear.php.net/package/PEAR
                   20091:  * @since      File available since Release 1.4.0a1
                   20092:  */
                   20093: 
                   20094: /**
                   20095:  * base class for installer roles
                   20096:  */
                   20097: require_once 'PEAR/Installer/Role/Common.php';
                   20098: require_once 'PEAR/XMLParser.php';
                   20099: /**
                   20100:  * @category   pear
                   20101:  * @package    PEAR
                   20102:  * @author     Greg Beaver <cellog@php.net>
                   20103:  * @copyright  1997-2009 The Authors
                   20104:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20105:  * @version    Release: 1.9.4
                   20106:  * @link       http://pear.php.net/package/PEAR
                   20107:  * @since      Class available since Release 1.4.0a1
                   20108:  */
                   20109: class PEAR_Installer_Role
                   20110: {
                   20111:     /**
                   20112:      * Set up any additional configuration variables that file roles require
                   20113:      *
                   20114:      * Never call this directly, it is called by the PEAR_Config constructor
                   20115:      * @param PEAR_Config
                   20116:      * @access private
                   20117:      * @static
                   20118:      */
                   20119:     function initializeConfig(&$config)
                   20120:     {
                   20121:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20122:             PEAR_Installer_Role::registerRoles();
                   20123:         }
                   20124: 
                   20125:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
                   20126:             if (!$info['config_vars']) {
                   20127:                 continue;
                   20128:             }
                   20129: 
                   20130:             $config->_addConfigVars($class, $info['config_vars']);
                   20131:         }
                   20132:     }
                   20133: 
                   20134:     /**
                   20135:      * @param PEAR_PackageFile_v2
                   20136:      * @param string role name
                   20137:      * @param PEAR_Config
                   20138:      * @return PEAR_Installer_Role_Common
                   20139:      * @static
                   20140:      */
                   20141:     function &factory($pkg, $role, &$config)
                   20142:     {
                   20143:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20144:             PEAR_Installer_Role::registerRoles();
                   20145:         }
                   20146: 
                   20147:         if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
                   20148:             $a = false;
                   20149:             return $a;
                   20150:         }
                   20151: 
                   20152:         $a = 'PEAR_Installer_Role_' . ucfirst($role);
                   20153:         if (!class_exists($a)) {
                   20154:             require_once str_replace('_', '/', $a) . '.php';
                   20155:         }
                   20156: 
                   20157:         $b = new $a($config);
                   20158:         return $b;
                   20159:     }
                   20160: 
                   20161:     /**
                   20162:      * Get a list of file roles that are valid for the particular release type.
                   20163:      *
                   20164:      * For instance, src files serve no purpose in regular php releases.
                   20165:      * @param string
                   20166:      * @param bool clear cache
                   20167:      * @return array
                   20168:      * @static
                   20169:      */
                   20170:     function getValidRoles($release, $clear = false)
                   20171:     {
                   20172:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20173:             PEAR_Installer_Role::registerRoles();
                   20174:         }
                   20175: 
                   20176:         static $ret = array();
                   20177:         if ($clear) {
                   20178:             $ret = array();
                   20179:         }
                   20180: 
                   20181:         if (isset($ret[$release])) {
                   20182:             return $ret[$release];
                   20183:         }
                   20184: 
                   20185:         $ret[$release] = array();
                   20186:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20187:             if (in_array($release, $okreleases['releasetypes'])) {
                   20188:                 $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20189:             }
                   20190:         }
                   20191: 
                   20192:         return $ret[$release];
                   20193:     }
                   20194: 
                   20195:     /**
                   20196:      * Get a list of roles that require their files to be installed
                   20197:      *
                   20198:      * Most roles must be installed, but src and package roles, for instance
                   20199:      * are pseudo-roles.  src files are compiled into a new extension.  Package
                   20200:      * roles are actually fully bundled releases of a package
                   20201:      * @param bool clear cache
                   20202:      * @return array
                   20203:      * @static
                   20204:      */
                   20205:     function getInstallableRoles($clear = false)
                   20206:     {
                   20207:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20208:             PEAR_Installer_Role::registerRoles();
                   20209:         }
                   20210: 
                   20211:         static $ret;
                   20212:         if ($clear) {
                   20213:             unset($ret);
                   20214:         }
                   20215: 
                   20216:         if (isset($ret)) {
                   20217:             return $ret;
                   20218:         }
                   20219: 
                   20220:         $ret = array();
                   20221:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20222:             if ($okreleases['installable']) {
                   20223:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20224:             }
                   20225:         }
                   20226: 
                   20227:         return $ret;
                   20228:     }
                   20229: 
                   20230:     /**
                   20231:      * Return an array of roles that are affected by the baseinstalldir attribute
                   20232:      *
                   20233:      * Most roles ignore this attribute, and instead install directly into:
                   20234:      * PackageName/filepath
                   20235:      * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
                   20236:      * @param bool clear cache
                   20237:      * @return array
                   20238:      * @static
                   20239:      */
                   20240:     function getBaseinstallRoles($clear = false)
                   20241:     {
                   20242:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20243:             PEAR_Installer_Role::registerRoles();
                   20244:         }
                   20245: 
                   20246:         static $ret;
                   20247:         if ($clear) {
                   20248:             unset($ret);
                   20249:         }
                   20250: 
                   20251:         if (isset($ret)) {
                   20252:             return $ret;
                   20253:         }
                   20254: 
                   20255:         $ret = array();
                   20256:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20257:             if ($okreleases['honorsbaseinstall']) {
                   20258:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20259:             }
                   20260:         }
                   20261: 
                   20262:         return $ret;
                   20263:     }
                   20264: 
                   20265:     /**
                   20266:      * Return an array of file roles that should be analyzed for PHP content at package time,
                   20267:      * like the "php" role.
                   20268:      * @param bool clear cache
                   20269:      * @return array
                   20270:      * @static
                   20271:      */
                   20272:     function getPhpRoles($clear = false)
                   20273:     {
                   20274:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20275:             PEAR_Installer_Role::registerRoles();
                   20276:         }
                   20277: 
                   20278:         static $ret;
                   20279:         if ($clear) {
                   20280:             unset($ret);
                   20281:         }
                   20282: 
                   20283:         if (isset($ret)) {
                   20284:             return $ret;
                   20285:         }
                   20286: 
                   20287:         $ret = array();
                   20288:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20289:             if ($okreleases['phpfile']) {
                   20290:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20291:             }
                   20292:         }
                   20293: 
                   20294:         return $ret;
                   20295:     }
                   20296: 
                   20297:     /**
                   20298:      * Scan through the Command directory looking for classes
                   20299:      * and see what commands they implement.
                   20300:      * @param string which directory to look for classes, defaults to
                   20301:      *               the Installer/Roles subdirectory of
                   20302:      *               the directory from where this file (__FILE__) is
                   20303:      *               included.
                   20304:      *
                   20305:      * @return bool TRUE on success, a PEAR error on failure
                   20306:      * @access public
                   20307:      * @static
                   20308:      */
                   20309:     function registerRoles($dir = null)
                   20310:     {
                   20311:         $GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
                   20312:         $parser = new PEAR_XMLParser;
                   20313:         if ($dir === null) {
                   20314:             $dir = dirname(__FILE__) . '/Role';
                   20315:         }
                   20316: 
                   20317:         if (!file_exists($dir) || !is_dir($dir)) {
                   20318:             return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
                   20319:         }
                   20320: 
                   20321:         $dp = @opendir($dir);
                   20322:         if (empty($dp)) {
                   20323:             return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
                   20324:         }
                   20325: 
                   20326:         while ($entry = readdir($dp)) {
                   20327:             if ($entry{0} == '.' || substr($entry, -4) != '.xml') {
                   20328:                 continue;
                   20329:             }
                   20330: 
                   20331:             $class = "PEAR_Installer_Role_".substr($entry, 0, -4);
                   20332:             // List of roles
                   20333:             if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
                   20334:                 $file = "$dir/$entry";
                   20335:                 $parser->parse(file_get_contents($file));
                   20336:                 $data = $parser->getData();
                   20337:                 if (!is_array($data['releasetypes'])) {
                   20338:                     $data['releasetypes'] = array($data['releasetypes']);
                   20339:                 }
                   20340: 
                   20341:                 $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
                   20342:             }
                   20343:         }
                   20344: 
                   20345:         closedir($dp);
                   20346:         ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
                   20347:         PEAR_Installer_Role::getBaseinstallRoles(true);
                   20348:         PEAR_Installer_Role::getInstallableRoles(true);
                   20349:         PEAR_Installer_Role::getPhpRoles(true);
                   20350:         PEAR_Installer_Role::getValidRoles('****', true);
                   20351:         return true;
                   20352:     }
                   20353: }PEAR-1.9.4/PEAR/PackageFile/Generator/v1.php0000644000076500000240000014234211605156760017113 0ustar  helgistaff<?php
                   20354: /**
                   20355:  * package.xml generation class, package.xml version 1.0
                   20356:  *
                   20357:  * PHP versions 4 and 5
                   20358:  *
                   20359:  * @category   pear
                   20360:  * @package    PEAR
                   20361:  * @author     Greg Beaver <cellog@php.net>
                   20362:  * @copyright  1997-2009 The Authors
                   20363:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20364:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   20365:  * @link       http://pear.php.net/package/PEAR
                   20366:  * @since      File available since Release 1.4.0a1
                   20367:  */
                   20368: /**
                   20369:  * needed for PEAR_VALIDATE_* constants
                   20370:  */
                   20371: require_once 'PEAR/Validate.php';
                   20372: require_once 'System.php';
                   20373: require_once 'PEAR/PackageFile/v2.php';
                   20374: /**
                   20375:  * This class converts a PEAR_PackageFile_v1 object into any output format.
                   20376:  *
                   20377:  * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
                   20378:  * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
                   20379:  * @category   pear
                   20380:  * @package    PEAR
                   20381:  * @author     Greg Beaver <cellog@php.net>
                   20382:  * @copyright  1997-2009 The Authors
                   20383:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20384:  * @version    Release: 1.9.4
                   20385:  * @link       http://pear.php.net/package/PEAR
                   20386:  * @since      Class available since Release 1.4.0a1
                   20387:  */
                   20388: class PEAR_PackageFile_Generator_v1
                   20389: {
                   20390:     /**
                   20391:      * @var PEAR_PackageFile_v1
                   20392:      */
                   20393:     var $_packagefile;
                   20394:     function PEAR_PackageFile_Generator_v1(&$packagefile)
                   20395:     {
                   20396:         $this->_packagefile = &$packagefile;
                   20397:     }
                   20398: 
                   20399:     function getPackagerVersion()
                   20400:     {
                   20401:         return '1.9.4';
                   20402:     }
                   20403: 
                   20404:     /**
                   20405:      * @param PEAR_Packager
                   20406:      * @param bool if true, a .tgz is written, otherwise a .tar is written
                   20407:      * @param string|null directory in which to save the .tgz
                   20408:      * @return string|PEAR_Error location of package or error object
                   20409:      */
                   20410:     function toTgz(&$packager, $compress = true, $where = null)
                   20411:     {
                   20412:         require_once 'Archive/Tar.php';
                   20413:         if ($where === null) {
                   20414:             if (!($where = System::mktemp(array('-d')))) {
                   20415:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
                   20416:             }
                   20417:         } elseif (!@System::mkDir(array('-p', $where))) {
                   20418:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
                   20419:                 ' not be created');
                   20420:         }
                   20421:         if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
                   20422:               !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
                   20423:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
                   20424:                 ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
                   20425:         }
                   20426:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   20427:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
                   20428:         }
                   20429:         $pkginfo = $this->_packagefile->getArray();
                   20430:         $ext = $compress ? '.tgz' : '.tar';
                   20431:         $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
                   20432:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   20433:         if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
                   20434:               !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
                   20435:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
                   20436:                 getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
                   20437:         }
                   20438:         if ($pkgfile = $this->_packagefile->getPackageFile()) {
                   20439:             $pkgdir = dirname(realpath($pkgfile));
                   20440:             $pkgfile = basename($pkgfile);
                   20441:         } else {
                   20442:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
                   20443:                 'be created from a real file');
                   20444:         }
                   20445:         // {{{ Create the package file list
                   20446:         $filelist = array();
                   20447:         $i = 0;
                   20448: 
                   20449:         foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
                   20450:             $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   20451:             if (!file_exists($file)) {
                   20452:                 return PEAR::raiseError("File does not exist: $fname");
                   20453:             } else {
                   20454:                 $filelist[$i++] = $file;
                   20455:                 if (!isset($atts['md5sum'])) {
                   20456:                     $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
                   20457:                 }
                   20458:                 $packager->log(2, "Adding file $fname");
                   20459:             }
                   20460:         }
                   20461:         // }}}
                   20462:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   20463:         if ($packagexml) {
                   20464:             $tar =& new Archive_Tar($dest_package, $compress);
                   20465:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   20466:             // ----- Creates with the package.xml file
                   20467:             $ok = $tar->createModify(array($packagexml), '', $where);
                   20468:             if (PEAR::isError($ok)) {
                   20469:                 return $ok;
                   20470:             } elseif (!$ok) {
                   20471:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   20472:             }
                   20473:             // ----- Add the content of the package
                   20474:             if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
                   20475:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   20476:             }
                   20477:             return $dest_package;
                   20478:         }
                   20479:     }
                   20480: 
                   20481:     /**
                   20482:      * @param string|null directory to place the package.xml in, or null for a temporary dir
                   20483:      * @param int one of the PEAR_VALIDATE_* constants
                   20484:      * @param string name of the generated file
                   20485:      * @param bool if true, then no analysis will be performed on role="php" files
                   20486:      * @return string|PEAR_Error path to the created file on success
                   20487:      */
                   20488:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
                   20489:                            $nofilechecking = false)
                   20490:     {
                   20491:         if (!$this->_packagefile->validate($state, $nofilechecking)) {
                   20492:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
                   20493:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   20494:         }
                   20495:         if ($where === null) {
                   20496:             if (!($where = System::mktemp(array('-d')))) {
                   20497:                 return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
                   20498:             }
                   20499:         } elseif (!@System::mkDir(array('-p', $where))) {
                   20500:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
                   20501:                 ' not be created');
                   20502:         }
                   20503:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   20504:         $np = @fopen($newpkgfile, 'wb');
                   20505:         if (!$np) {
                   20506:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
                   20507:                "$name as $newpkgfile");
                   20508:         }
                   20509:         fwrite($np, $this->toXml($state, true));
                   20510:         fclose($np);
                   20511:         return $newpkgfile;
                   20512:     }
                   20513: 
                   20514:     /**
                   20515:      * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
                   20516:      *
                   20517:      * @param string $string
                   20518:      * @return string
                   20519:      * @access private
                   20520:      */
                   20521:     function _fixXmlEncoding($string)
                   20522:     {
                   20523:         if (version_compare(phpversion(), '5.0.0', 'lt')) {
                   20524:             $string = utf8_encode($string);
                   20525:         }
                   20526:         return strtr($string, array(
                   20527:                                           '&'  => '&amp;',
                   20528:                                           '>'  => '&gt;',
                   20529:                                           '<'  => '&lt;',
                   20530:                                           '"'  => '&quot;',
                   20531:                                           '\'' => '&apos;' ));
                   20532:     }
                   20533: 
                   20534:     /**
                   20535:      * Return an XML document based on the package info (as returned
                   20536:      * by the PEAR_Common::infoFrom* methods).
                   20537:      *
                   20538:      * @return string XML data
                   20539:      */
                   20540:     function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
                   20541:     {
                   20542:         $this->_packagefile->setDate(date('Y-m-d'));
                   20543:         if (!$this->_packagefile->validate($state, $nofilevalidation)) {
                   20544:             return false;
                   20545:         }
                   20546:         $pkginfo = $this->_packagefile->getArray();
                   20547:         static $maint_map = array(
                   20548:             "handle" => "user",
                   20549:             "name" => "name",
                   20550:             "email" => "email",
                   20551:             "role" => "role",
                   20552:             );
                   20553:         $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
                   20554:         $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
                   20555:         $ret .= "<package version=\"1.0\" packagerversion=\"1.9.4\">\n" .
                   20556: " <name>$pkginfo[package]</name>";
                   20557:         if (isset($pkginfo['extends'])) {
                   20558:             $ret .= "\n<extends>$pkginfo[extends]</extends>";
                   20559:         }
                   20560:         $ret .=
                   20561:  "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
                   20562: " <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
                   20563: " <maintainers>\n";
                   20564:         foreach ($pkginfo['maintainers'] as $maint) {
                   20565:             $ret .= "  <maintainer>\n";
                   20566:             foreach ($maint_map as $idx => $elm) {
                   20567:                 $ret .= "   <$elm>";
                   20568:                 $ret .= $this->_fixXmlEncoding($maint[$idx]);
                   20569:                 $ret .= "</$elm>\n";
                   20570:             }
                   20571:             $ret .= "  </maintainer>\n";
                   20572:         }
                   20573:         $ret .= "  </maintainers>\n";
                   20574:         $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
                   20575:         if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
                   20576:             $ret .= " <changelog>\n";
                   20577:             foreach ($pkginfo['changelog'] as $oldrelease) {
                   20578:                 $ret .= $this->_makeReleaseXml($oldrelease, true);
                   20579:             }
                   20580:             $ret .= " </changelog>\n";
                   20581:         }
                   20582:         $ret .= "</package>\n";
                   20583:         return $ret;
                   20584:     }
                   20585: 
                   20586:     // }}}
                   20587:     // {{{ _makeReleaseXml()
                   20588: 
                   20589:     /**
                   20590:      * Generate part of an XML description with release information.
                   20591:      *
                   20592:      * @param array  $pkginfo    array with release information
                   20593:      * @param bool   $changelog  whether the result will be in a changelog element
                   20594:      *
                   20595:      * @return string XML data
                   20596:      *
                   20597:      * @access private
                   20598:      */
                   20599:     function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
                   20600:     {
                   20601:         // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
                   20602:         $indent = $changelog ? "  " : "";
                   20603:         $ret = "$indent <release>\n";
                   20604:         if (!empty($pkginfo['version'])) {
                   20605:             $ret .= "$indent  <version>$pkginfo[version]</version>\n";
                   20606:         }
                   20607:         if (!empty($pkginfo['release_date'])) {
                   20608:             $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
                   20609:         }
                   20610:         if (!empty($pkginfo['release_license'])) {
                   20611:             $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
                   20612:         }
                   20613:         if (!empty($pkginfo['release_state'])) {
                   20614:             $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
                   20615:         }
                   20616:         if (!empty($pkginfo['release_notes'])) {
                   20617:             $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
                   20618:             ."\n$indent  </notes>\n";
                   20619:         }
                   20620:         if (!empty($pkginfo['release_warnings'])) {
                   20621:             $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
                   20622:         }
                   20623:         if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
                   20624:             $ret .= "$indent  <deps>\n";
                   20625:             foreach ($pkginfo['release_deps'] as $dep) {
                   20626:                 $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
                   20627:                 if (isset($dep['version'])) {
                   20628:                     $ret .= " version=\"$dep[version]\"";
                   20629:                 }
                   20630:                 if (isset($dep['optional'])) {
                   20631:                     $ret .= " optional=\"$dep[optional]\"";
                   20632:                 }
                   20633:                 if (isset($dep['name'])) {
                   20634:                     $ret .= ">$dep[name]</dep>\n";
                   20635:                 } else {
                   20636:                     $ret .= "/>\n";
                   20637:                 }
                   20638:             }
                   20639:             $ret .= "$indent  </deps>\n";
                   20640:         }
                   20641:         if (isset($pkginfo['configure_options'])) {
                   20642:             $ret .= "$indent  <configureoptions>\n";
                   20643:             foreach ($pkginfo['configure_options'] as $c) {
                   20644:                 $ret .= "$indent   <configureoption name=\"".
                   20645:                     $this->_fixXmlEncoding($c['name']) . "\"";
                   20646:                 if (isset($c['default'])) {
                   20647:                     $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
                   20648:                 }
                   20649:                 $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
                   20650:                 $ret .= "/>\n";
                   20651:             }
                   20652:             $ret .= "$indent  </configureoptions>\n";
                   20653:         }
                   20654:         if (isset($pkginfo['provides'])) {
                   20655:             foreach ($pkginfo['provides'] as $key => $what) {
                   20656:                 $ret .= "$indent  <provides type=\"$what[type]\" ";
                   20657:                 $ret .= "name=\"$what[name]\" ";
                   20658:                 if (isset($what['extends'])) {
                   20659:                     $ret .= "extends=\"$what[extends]\" ";
                   20660:                 }
                   20661:                 $ret .= "/>\n";
                   20662:             }
                   20663:         }
                   20664:         if (isset($pkginfo['filelist'])) {
                   20665:             $ret .= "$indent  <filelist>\n";
                   20666:             if ($state ^ PEAR_VALIDATE_PACKAGING) {
                   20667:                 $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
                   20668:             } else {
                   20669:                 foreach ($pkginfo['filelist'] as $file => $fa) {
                   20670:                     if (!isset($fa['role'])) {
                   20671:                         $fa['role'] = '';
                   20672:                     }
                   20673:                     $ret .= "$indent   <file role=\"$fa[role]\"";
                   20674:                     if (isset($fa['baseinstalldir'])) {
                   20675:                         $ret .= ' baseinstalldir="' .
                   20676:                             $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
                   20677:                     }
                   20678:                     if (isset($fa['md5sum'])) {
                   20679:                         $ret .= " md5sum=\"$fa[md5sum]\"";
                   20680:                     }
                   20681:                     if (isset($fa['platform'])) {
                   20682:                         $ret .= " platform=\"$fa[platform]\"";
                   20683:                     }
                   20684:                     if (!empty($fa['install-as'])) {
                   20685:                         $ret .= ' install-as="' .
                   20686:                             $this->_fixXmlEncoding($fa['install-as']) . '"';
                   20687:                     }
                   20688:                     $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   20689:                     if (empty($fa['replacements'])) {
                   20690:                         $ret .= "/>\n";
                   20691:                     } else {
                   20692:                         $ret .= ">\n";
                   20693:                         foreach ($fa['replacements'] as $r) {
                   20694:                             $ret .= "$indent    <replace";
                   20695:                             foreach ($r as $k => $v) {
                   20696:                                 $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   20697:                             }
                   20698:                             $ret .= "/>\n";
                   20699:                         }
                   20700:                         $ret .= "$indent   </file>\n";
                   20701:                     }
                   20702:                 }
                   20703:             }
                   20704:             $ret .= "$indent  </filelist>\n";
                   20705:         }
                   20706:         $ret .= "$indent </release>\n";
                   20707:         return $ret;
                   20708:     }
                   20709: 
                   20710:     /**
                   20711:      * @param array
                   20712:      * @access protected
                   20713:      */
                   20714:     function recursiveXmlFilelist($list)
                   20715:     {
                   20716:         $this->_dirs = array();
                   20717:         foreach ($list as $file => $attributes) {
                   20718:             $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
                   20719:         }
                   20720:         return $this->_formatDir($this->_dirs);
                   20721:     }
                   20722: 
                   20723:     /**
                   20724:      * @param array
                   20725:      * @param array
                   20726:      * @param string|null
                   20727:      * @param array|null
                   20728:      * @access private
                   20729:      */
                   20730:     function _addDir(&$dirs, $dir, $file = null, $attributes = null)
                   20731:     {
                   20732:         if ($dir == array() || $dir == array('.')) {
                   20733:             $dirs['files'][basename($file)] = $attributes;
                   20734:             return;
                   20735:         }
                   20736:         $curdir = array_shift($dir);
                   20737:         if (!isset($dirs['dirs'][$curdir])) {
                   20738:             $dirs['dirs'][$curdir] = array();
                   20739:         }
                   20740:         $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
                   20741:     }
                   20742: 
                   20743:     /**
                   20744:      * @param array
                   20745:      * @param string
                   20746:      * @param string
                   20747:      * @access private
                   20748:      */
                   20749:     function _formatDir($dirs, $indent = '', $curdir = '')
                   20750:     {
                   20751:         $ret = '';
                   20752:         if (!count($dirs)) {
                   20753:             return '';
                   20754:         }
                   20755:         if (isset($dirs['dirs'])) {
                   20756:             uksort($dirs['dirs'], 'strnatcasecmp');
                   20757:             foreach ($dirs['dirs'] as $dir => $contents) {
                   20758:                 $usedir = "$curdir/$dir";
                   20759:                 $ret .= "$indent   <dir name=\"$dir\">\n";
                   20760:                 $ret .= $this->_formatDir($contents, "$indent ", $usedir);
                   20761:                 $ret .= "$indent   </dir> <!-- $usedir -->\n";
                   20762:             }
                   20763:         }
                   20764:         if (isset($dirs['files'])) {
                   20765:             uksort($dirs['files'], 'strnatcasecmp');
                   20766:             foreach ($dirs['files'] as $file => $attribs) {
                   20767:                 $ret .= $this->_formatFile($file, $attribs, $indent);
                   20768:             }
                   20769:         }
                   20770:         return $ret;
                   20771:     }
                   20772: 
                   20773:     /**
                   20774:      * @param string
                   20775:      * @param array
                   20776:      * @param string
                   20777:      * @access private
                   20778:      */
                   20779:     function _formatFile($file, $attributes, $indent)
                   20780:     {
                   20781:         $ret = "$indent   <file role=\"$attributes[role]\"";
                   20782:         if (isset($attributes['baseinstalldir'])) {
                   20783:             $ret .= ' baseinstalldir="' .
                   20784:                 $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
                   20785:         }
                   20786:         if (isset($attributes['md5sum'])) {
                   20787:             $ret .= " md5sum=\"$attributes[md5sum]\"";
                   20788:         }
                   20789:         if (isset($attributes['platform'])) {
                   20790:             $ret .= " platform=\"$attributes[platform]\"";
                   20791:         }
                   20792:         if (!empty($attributes['install-as'])) {
                   20793:             $ret .= ' install-as="' .
                   20794:                 $this->_fixXmlEncoding($attributes['install-as']) . '"';
                   20795:         }
                   20796:         $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   20797:         if (empty($attributes['replacements'])) {
                   20798:             $ret .= "/>\n";
                   20799:         } else {
                   20800:             $ret .= ">\n";
                   20801:             foreach ($attributes['replacements'] as $r) {
                   20802:                 $ret .= "$indent    <replace";
                   20803:                 foreach ($r as $k => $v) {
                   20804:                     $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   20805:                 }
                   20806:                 $ret .= "/>\n";
                   20807:             }
                   20808:             $ret .= "$indent   </file>\n";
                   20809:         }
                   20810:         return $ret;
                   20811:     }
                   20812: 
                   20813:     // {{{ _unIndent()
                   20814: 
                   20815:     /**
                   20816:      * Unindent given string (?)
                   20817:      *
                   20818:      * @param string $str The string that has to be unindented.
                   20819:      * @return string
                   20820:      * @access private
                   20821:      */
                   20822:     function _unIndent($str)
                   20823:     {
                   20824:         // remove leading newlines
                   20825:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   20826:         // find whitespace at the beginning of the first line
                   20827:         $indent_len = strspn($str, " \t");
                   20828:         $indent = substr($str, 0, $indent_len);
                   20829:         $data = '';
                   20830:         // remove the same amount of whitespace from following lines
                   20831:         foreach (explode("\n", $str) as $line) {
                   20832:             if (substr($line, 0, $indent_len) == $indent) {
                   20833:                 $data .= substr($line, $indent_len) . "\n";
                   20834:             }
                   20835:         }
                   20836:         return $data;
                   20837:     }
                   20838: 
                   20839:     /**
                   20840:      * @return array
                   20841:      */
                   20842:     function dependenciesToV2()
                   20843:     {
                   20844:         $arr = array();
                   20845:         $this->_convertDependencies2_0($arr);
                   20846:         return $arr['dependencies'];
                   20847:     }
                   20848: 
                   20849:     /**
                   20850:      * Convert a package.xml version 1.0 into version 2.0
                   20851:      *
                   20852:      * Note that this does a basic conversion, to allow more advanced
                   20853:      * features like bundles and multiple releases
                   20854:      * @param string the classname to instantiate and return.  This must be
                   20855:      *               PEAR_PackageFile_v2 or a descendant
                   20856:      * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
                   20857:      *                strictest parameters will be converted
                   20858:      * @return PEAR_PackageFile_v2|PEAR_Error
                   20859:      */
                   20860:     function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
                   20861:     {
                   20862:         if ($strict) {
                   20863:             if (!$this->_packagefile->validate()) {
                   20864:                 $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
                   20865:                     ' to version 2.0', null, null, null,
                   20866:                     $this->_packagefile->getValidationWarnings(true));
                   20867:                 return $a;
                   20868:             }
                   20869:         }
                   20870: 
                   20871:         $arr = array(
                   20872:             'attribs' => array(
                   20873:                              'version' => '2.0',
                   20874:                              'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   20875:                              'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   20876:                              'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   20877:                              'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
                   20878: "http://pear.php.net/dtd/tasks-1.0.xsd\n" .
                   20879: "http://pear.php.net/dtd/package-2.0\n" .
                   20880: 'http://pear.php.net/dtd/package-2.0.xsd',
                   20881:                          ),
                   20882:             'name' => $this->_packagefile->getPackage(),
                   20883:             'channel' => 'pear.php.net',
                   20884:         );
                   20885:         $arr['summary'] = $this->_packagefile->getSummary();
                   20886:         $arr['description'] = $this->_packagefile->getDescription();
                   20887:         $maintainers = $this->_packagefile->getMaintainers();
                   20888:         foreach ($maintainers as $maintainer) {
                   20889:             if ($maintainer['role'] != 'lead') {
                   20890:                 continue;
                   20891:             }
                   20892:             $new = array(
                   20893:                 'name' => $maintainer['name'],
                   20894:                 'user' => $maintainer['handle'],
                   20895:                 'email' => $maintainer['email'],
                   20896:                 'active' => 'yes',
                   20897:             );
                   20898:             $arr['lead'][] = $new;
                   20899:         }
                   20900: 
                   20901:         if (!isset($arr['lead'])) { // some people... you know?
                   20902:             $arr['lead'] = array(
                   20903:                 'name' => 'unknown',
                   20904:                 'user' => 'unknown',
                   20905:                 'email' => 'noleadmaintainer@example.com',
                   20906:                 'active' => 'no',
                   20907:             );
                   20908:         }
                   20909: 
                   20910:         if (count($arr['lead']) == 1) {
                   20911:             $arr['lead'] = $arr['lead'][0];
                   20912:         }
                   20913: 
                   20914:         foreach ($maintainers as $maintainer) {
                   20915:             if ($maintainer['role'] == 'lead') {
                   20916:                 continue;
                   20917:             }
                   20918:             $new = array(
                   20919:                 'name' => $maintainer['name'],
                   20920:                 'user' => $maintainer['handle'],
                   20921:                 'email' => $maintainer['email'],
                   20922:                 'active' => 'yes',
                   20923:             );
                   20924:             $arr[$maintainer['role']][] = $new;
                   20925:         }
                   20926: 
                   20927:         if (isset($arr['developer']) && count($arr['developer']) == 1) {
                   20928:             $arr['developer'] = $arr['developer'][0];
                   20929:         }
                   20930: 
                   20931:         if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
                   20932:             $arr['contributor'] = $arr['contributor'][0];
                   20933:         }
                   20934: 
                   20935:         if (isset($arr['helper']) && count($arr['helper']) == 1) {
                   20936:             $arr['helper'] = $arr['helper'][0];
                   20937:         }
                   20938: 
                   20939:         $arr['date'] = $this->_packagefile->getDate();
                   20940:         $arr['version'] =
                   20941:             array(
                   20942:                 'release' => $this->_packagefile->getVersion(),
                   20943:                 'api' => $this->_packagefile->getVersion(),
                   20944:             );
                   20945:         $arr['stability'] =
                   20946:             array(
                   20947:                 'release' => $this->_packagefile->getState(),
                   20948:                 'api' => $this->_packagefile->getState(),
                   20949:             );
                   20950:         $licensemap =
                   20951:             array(
                   20952:                 'php' => 'http://www.php.net/license',
                   20953:                 'php license' => 'http://www.php.net/license',
                   20954:                 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
                   20955:                 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
                   20956:                 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   20957:                 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   20958:                 'mit' => 'http://www.opensource.org/licenses/mit-license.php',
                   20959:                 'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
                   20960:                 'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
                   20961:             );
                   20962: 
                   20963:         if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
                   20964:             $arr['license'] = array(
                   20965:                 'attribs' => array('uri' =>
                   20966:                     $licensemap[strtolower($this->_packagefile->getLicense())]),
                   20967:                 '_content' => $this->_packagefile->getLicense()
                   20968:                 );
                   20969:         } else {
                   20970:             // don't use bogus uri
                   20971:             $arr['license'] = $this->_packagefile->getLicense();
                   20972:         }
                   20973: 
                   20974:         $arr['notes'] = $this->_packagefile->getNotes();
                   20975:         $temp = array();
                   20976:         $arr['contents'] = $this->_convertFilelist2_0($temp);
                   20977:         $this->_convertDependencies2_0($arr);
                   20978:         $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
                   20979:             'extsrcrelease' : 'phprelease';
                   20980:         if ($release == 'extsrcrelease') {
                   20981:             $arr['channel'] = 'pecl.php.net';
                   20982:             $arr['providesextension'] = $arr['name']; // assumption
                   20983:         }
                   20984: 
                   20985:         $arr[$release] = array();
                   20986:         if ($this->_packagefile->getConfigureOptions()) {
                   20987:             $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
                   20988:             foreach ($arr[$release]['configureoption'] as $i => $opt) {
                   20989:                 $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
                   20990:             }
                   20991:             if (count($arr[$release]['configureoption']) == 1) {
                   20992:                 $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
                   20993:             }
                   20994:         }
                   20995: 
                   20996:         $this->_convertRelease2_0($arr[$release], $temp);
                   20997:         if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
                   20998:             // multiple extsrcrelease tags added in PEAR 1.4.1
                   20999:             $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
                   21000:         }
                   21001: 
                   21002:         if ($cl = $this->_packagefile->getChangelog()) {
                   21003:             foreach ($cl as $release) {
                   21004:                 $rel = array();
                   21005:                 $rel['version'] =
                   21006:                     array(
                   21007:                         'release' => $release['version'],
                   21008:                         'api' => $release['version'],
                   21009:                     );
                   21010:                 if (!isset($release['release_state'])) {
                   21011:                     $release['release_state'] = 'stable';
                   21012:                 }
                   21013: 
                   21014:                 $rel['stability'] =
                   21015:                     array(
                   21016:                         'release' => $release['release_state'],
                   21017:                         'api' => $release['release_state'],
                   21018:                     );
                   21019:                 if (isset($release['release_date'])) {
                   21020:                     $rel['date'] = $release['release_date'];
                   21021:                 } else {
                   21022:                     $rel['date'] = date('Y-m-d');
                   21023:                 }
                   21024: 
                   21025:                 if (isset($release['release_license'])) {
                   21026:                     if (isset($licensemap[strtolower($release['release_license'])])) {
                   21027:                         $uri = $licensemap[strtolower($release['release_license'])];
                   21028:                     } else {
                   21029:                         $uri = 'http://www.example.com';
                   21030:                     }
                   21031:                     $rel['license'] = array(
                   21032:                             'attribs' => array('uri' => $uri),
                   21033:                             '_content' => $release['release_license']
                   21034:                         );
                   21035:                 } else {
                   21036:                     $rel['license'] = $arr['license'];
                   21037:                 }
                   21038: 
                   21039:                 if (!isset($release['release_notes'])) {
                   21040:                     $release['release_notes'] = 'no release notes';
                   21041:                 }
                   21042: 
                   21043:                 $rel['notes'] = $release['release_notes'];
                   21044:                 $arr['changelog']['release'][] = $rel;
                   21045:             }
                   21046:         }
                   21047: 
                   21048:         $ret = new $class;
                   21049:         $ret->setConfig($this->_packagefile->_config);
                   21050:         if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
                   21051:             $ret->setLogger($this->_packagefile->_logger);
                   21052:         }
                   21053: 
                   21054:         $ret->fromArray($arr);
                   21055:         return $ret;
                   21056:     }
                   21057: 
                   21058:     /**
                   21059:      * @param array
                   21060:      * @param bool
                   21061:      * @access private
                   21062:      */
                   21063:     function _convertDependencies2_0(&$release, $internal = false)
                   21064:     {
                   21065:         $peardep = array('pearinstaller' =>
                   21066:             array('min' => '1.4.0b1')); // this is a lot safer
                   21067:         $required = $optional = array();
                   21068:         $release['dependencies'] = array('required' => array());
                   21069:         if ($this->_packagefile->hasDeps()) {
                   21070:             foreach ($this->_packagefile->getDeps() as $dep) {
                   21071:                 if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   21072:                     $required[] = $dep;
                   21073:                 } else {
                   21074:                     $optional[] = $dep;
                   21075:                 }
                   21076:             }
                   21077:             foreach (array('required', 'optional') as $arr) {
                   21078:                 $deps = array();
                   21079:                 foreach ($$arr as $dep) {
                   21080:                     // organize deps by dependency type and name
                   21081:                     if (!isset($deps[$dep['type']])) {
                   21082:                         $deps[$dep['type']] = array();
                   21083:                     }
                   21084:                     if (isset($dep['name'])) {
                   21085:                         $deps[$dep['type']][$dep['name']][] = $dep;
                   21086:                     } else {
                   21087:                         $deps[$dep['type']][] = $dep;
                   21088:                     }
                   21089:                 }
                   21090:                 do {
                   21091:                     if (isset($deps['php'])) {
                   21092:                         $php = array();
                   21093:                         if (count($deps['php']) > 1) {
                   21094:                             $php = $this->_processPhpDeps($deps['php']);
                   21095:                         } else {
                   21096:                             if (!isset($deps['php'][0])) {
                   21097:                                 list($key, $blah) = each ($deps['php']); // stupid buggy versions
                   21098:                                 $deps['php'] = array($blah[0]);
                   21099:                             }
                   21100:                             $php = $this->_processDep($deps['php'][0]);
                   21101:                             if (!$php) {
                   21102:                                 break; // poor mans throw
                   21103:                             }
                   21104:                         }
                   21105:                         $release['dependencies'][$arr]['php'] = $php;
                   21106:                     }
                   21107:                 } while (false);
                   21108:                 do {
                   21109:                     if (isset($deps['pkg'])) {
                   21110:                         $pkg = array();
                   21111:                         $pkg = $this->_processMultipleDepsName($deps['pkg']);
                   21112:                         if (!$pkg) {
                   21113:                             break; // poor mans throw
                   21114:                         }
                   21115:                         $release['dependencies'][$arr]['package'] = $pkg;
                   21116:                     }
                   21117:                 } while (false);
                   21118:                 do {
                   21119:                     if (isset($deps['ext'])) {
                   21120:                         $pkg = array();
                   21121:                         $pkg = $this->_processMultipleDepsName($deps['ext']);
                   21122:                         $release['dependencies'][$arr]['extension'] = $pkg;
                   21123:                     }
                   21124:                 } while (false);
                   21125:                 // skip sapi - it's not supported so nobody will have used it
                   21126:                 // skip os - it's not supported in 1.0
                   21127:             }
                   21128:         }
                   21129:         if (isset($release['dependencies']['required'])) {
                   21130:             $release['dependencies']['required'] =
                   21131:                 array_merge($peardep, $release['dependencies']['required']);
                   21132:         } else {
                   21133:             $release['dependencies']['required'] = $peardep;
                   21134:         }
                   21135:         if (!isset($release['dependencies']['required']['php'])) {
                   21136:             $release['dependencies']['required']['php'] =
                   21137:                 array('min' => '4.0.0');
                   21138:         }
                   21139:         $order = array();
                   21140:         $bewm = $release['dependencies']['required'];
                   21141:         $order['php'] = $bewm['php'];
                   21142:         $order['pearinstaller'] = $bewm['pearinstaller'];
                   21143:         isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
                   21144:         isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
                   21145:         $release['dependencies']['required'] = $order;
                   21146:     }
                   21147: 
                   21148:     /**
                   21149:      * @param array
                   21150:      * @access private
                   21151:      */
                   21152:     function _convertFilelist2_0(&$package)
                   21153:     {
                   21154:         $ret = array('dir' =>
                   21155:                     array(
                   21156:                         'attribs' => array('name' => '/'),
                   21157:                         'file' => array()
                   21158:                         )
                   21159:                     );
                   21160:         $package['platform'] =
                   21161:         $package['install-as'] = array();
                   21162:         $this->_isExtension = false;
                   21163:         foreach ($this->_packagefile->getFilelist() as $name => $file) {
                   21164:             $file['name'] = $name;
                   21165:             if (isset($file['role']) && $file['role'] == 'src') {
                   21166:                 $this->_isExtension = true;
                   21167:             }
                   21168:             if (isset($file['replacements'])) {
                   21169:                 $repl = $file['replacements'];
                   21170:                 unset($file['replacements']);
                   21171:             } else {
                   21172:                 unset($repl);
                   21173:             }
                   21174:             if (isset($file['install-as'])) {
                   21175:                 $package['install-as'][$name] = $file['install-as'];
                   21176:                 unset($file['install-as']);
                   21177:             }
                   21178:             if (isset($file['platform'])) {
                   21179:                 $package['platform'][$name] = $file['platform'];
                   21180:                 unset($file['platform']);
                   21181:             }
                   21182:             $file = array('attribs' => $file);
                   21183:             if (isset($repl)) {
                   21184:                 foreach ($repl as $replace ) {
                   21185:                     $file['tasks:replace'][] = array('attribs' => $replace);
                   21186:                 }
                   21187:                 if (count($repl) == 1) {
                   21188:                     $file['tasks:replace'] = $file['tasks:replace'][0];
                   21189:                 }
                   21190:             }
                   21191:             $ret['dir']['file'][] = $file;
                   21192:         }
                   21193:         return $ret;
                   21194:     }
                   21195: 
                   21196:     /**
                   21197:      * Post-process special files with install-as/platform attributes and
                   21198:      * make the release tag.
                   21199:      *
                   21200:      * This complex method follows this work-flow to create the release tags:
                   21201:      *
                   21202:      * <pre>
                   21203:      * - if any install-as/platform exist, create a generic release and fill it with
                   21204:      *   o <install as=..> tags for <file name=... install-as=...>
                   21205:      *   o <install as=..> tags for <file name=... platform=!... install-as=..>
                   21206:      *   o <ignore> tags for <file name=... platform=...>
                   21207:      *   o <ignore> tags for <file name=... platform=... install-as=..>
                   21208:      * - create a release for each platform encountered and fill with
                   21209:      *   o <install as..> tags for <file name=... install-as=...>
                   21210:      *   o <install as..> tags for <file name=... platform=this platform install-as=..>
                   21211:      *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
                   21212:      *   o <ignore> tags for <file name=... platform=!this platform>
                   21213:      *   o <ignore> tags for <file name=... platform=other platform>
                   21214:      *   o <ignore> tags for <file name=... platform=other platform install-as=..>
                   21215:      *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
                   21216:      * </pre>
                   21217:      *
                   21218:      * It does this by accessing the $package parameter, which contains an array with
                   21219:      * indices:
                   21220:      *
                   21221:      *  - platform: mapping of file => OS the file should be installed on
                   21222:      *  - install-as: mapping of file => installed name
                   21223:      *  - osmap: mapping of OS => list of files that should be installed
                   21224:      *    on that OS
                   21225:      *  - notosmap: mapping of OS => list of files that should not be
                   21226:      *    installed on that OS
                   21227:      *
                   21228:      * @param array
                   21229:      * @param array
                   21230:      * @access private
                   21231:      */
                   21232:     function _convertRelease2_0(&$release, $package)
                   21233:     {
                   21234:         //- if any install-as/platform exist, create a generic release and fill it with
                   21235:         if (count($package['platform']) || count($package['install-as'])) {
                   21236:             $generic = array();
                   21237:             $genericIgnore = array();
                   21238:             foreach ($package['install-as'] as $file => $as) {
                   21239:                 //o <install as=..> tags for <file name=... install-as=...>
                   21240:                 if (!isset($package['platform'][$file])) {
                   21241:                     $generic[] = $file;
                   21242:                     continue;
                   21243:                 }
                   21244:                 //o <install as=..> tags for <file name=... platform=!... install-as=..>
                   21245:                 if (isset($package['platform'][$file]) &&
                   21246:                       $package['platform'][$file]{0} == '!') {
                   21247:                     $generic[] = $file;
                   21248:                     continue;
                   21249:                 }
                   21250:                 //o <ignore> tags for <file name=... platform=... install-as=..>
                   21251:                 if (isset($package['platform'][$file]) &&
                   21252:                       $package['platform'][$file]{0} != '!') {
                   21253:                     $genericIgnore[] = $file;
                   21254:                     continue;
                   21255:                 }
                   21256:             }
                   21257:             foreach ($package['platform'] as $file => $platform) {
                   21258:                 if (isset($package['install-as'][$file])) {
                   21259:                     continue;
                   21260:                 }
                   21261:                 if ($platform{0} != '!') {
                   21262:                     //o <ignore> tags for <file name=... platform=...>
                   21263:                     $genericIgnore[] = $file;
                   21264:                 }
                   21265:             }
                   21266:             if (count($package['platform'])) {
                   21267:                 $oses = $notplatform = $platform = array();
                   21268:                 foreach ($package['platform'] as $file => $os) {
                   21269:                     // get a list of oses
                   21270:                     if ($os{0} == '!') {
                   21271:                         if (isset($oses[substr($os, 1)])) {
                   21272:                             continue;
                   21273:                         }
                   21274:                         $oses[substr($os, 1)] = count($oses);
                   21275:                     } else {
                   21276:                         if (isset($oses[$os])) {
                   21277:                             continue;
                   21278:                         }
                   21279:                         $oses[$os] = count($oses);
                   21280:                     }
                   21281:                 }
                   21282:                 //- create a release for each platform encountered and fill with
                   21283:                 foreach ($oses as $os => $releaseNum) {
                   21284:                     $release[$releaseNum]['installconditions']['os']['name'] = $os;
                   21285:                     $release[$releaseNum]['filelist'] = array('install' => array(),
                   21286:                         'ignore' => array());
                   21287:                     foreach ($package['install-as'] as $file => $as) {
                   21288:                         //o <install as=..> tags for <file name=... install-as=...>
                   21289:                         if (!isset($package['platform'][$file])) {
                   21290:                             $release[$releaseNum]['filelist']['install'][] =
                   21291:                                 array(
                   21292:                                     'attribs' => array(
                   21293:                                         'name' => $file,
                   21294:                                         'as' => $as,
                   21295:                                     ),
                   21296:                                 );
                   21297:                             continue;
                   21298:                         }
                   21299:                         //o <install as..> tags for
                   21300:                         //  <file name=... platform=this platform install-as=..>
                   21301:                         if (isset($package['platform'][$file]) &&
                   21302:                               $package['platform'][$file] == $os) {
                   21303:                             $release[$releaseNum]['filelist']['install'][] =
                   21304:                                 array(
                   21305:                                     'attribs' => array(
                   21306:                                         'name' => $file,
                   21307:                                         'as' => $as,
                   21308:                                     ),
                   21309:                                 );
                   21310:                             continue;
                   21311:                         }
                   21312:                         //o <install as..> tags for
                   21313:                         //  <file name=... platform=!other platform install-as=..>
                   21314:                         if (isset($package['platform'][$file]) &&
                   21315:                               $package['platform'][$file] != "!$os" &&
                   21316:                               $package['platform'][$file]{0} == '!') {
                   21317:                             $release[$releaseNum]['filelist']['install'][] =
                   21318:                                 array(
                   21319:                                     'attribs' => array(
                   21320:                                         'name' => $file,
                   21321:                                         'as' => $as,
                   21322:                                     ),
                   21323:                                 );
                   21324:                             continue;
                   21325:                         }
                   21326:                         //o <ignore> tags for
                   21327:                         //  <file name=... platform=!this platform install-as=..>
                   21328:                         if (isset($package['platform'][$file]) &&
                   21329:                               $package['platform'][$file] == "!$os") {
                   21330:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21331:                                 array(
                   21332:                                     'attribs' => array(
                   21333:                                         'name' => $file,
                   21334:                                     ),
                   21335:                                 );
                   21336:                             continue;
                   21337:                         }
                   21338:                         //o <ignore> tags for
                   21339:                         //  <file name=... platform=other platform install-as=..>
                   21340:                         if (isset($package['platform'][$file]) &&
                   21341:                               $package['platform'][$file]{0} != '!' &&
                   21342:                               $package['platform'][$file] != $os) {
                   21343:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21344:                                 array(
                   21345:                                     'attribs' => array(
                   21346:                                         'name' => $file,
                   21347:                                     ),
                   21348:                                 );
                   21349:                             continue;
                   21350:                         }
                   21351:                     }
                   21352:                     foreach ($package['platform'] as $file => $platform) {
                   21353:                         if (isset($package['install-as'][$file])) {
                   21354:                             continue;
                   21355:                         }
                   21356:                         //o <ignore> tags for <file name=... platform=!this platform>
                   21357:                         if ($platform == "!$os") {
                   21358:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21359:                                 array(
                   21360:                                     'attribs' => array(
                   21361:                                         'name' => $file,
                   21362:                                     ),
                   21363:                                 );
                   21364:                             continue;
                   21365:                         }
                   21366:                         //o <ignore> tags for <file name=... platform=other platform>
                   21367:                         if ($platform{0} != '!' && $platform != $os) {
                   21368:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21369:                                 array(
                   21370:                                     'attribs' => array(
                   21371:                                         'name' => $file,
                   21372:                                     ),
                   21373:                                 );
                   21374:                         }
                   21375:                     }
                   21376:                     if (!count($release[$releaseNum]['filelist']['install'])) {
                   21377:                         unset($release[$releaseNum]['filelist']['install']);
                   21378:                     }
                   21379:                     if (!count($release[$releaseNum]['filelist']['ignore'])) {
                   21380:                         unset($release[$releaseNum]['filelist']['ignore']);
                   21381:                     }
                   21382:                 }
                   21383:                 if (count($generic) || count($genericIgnore)) {
                   21384:                     $release[count($oses)] = array();
                   21385:                     if (count($generic)) {
                   21386:                         foreach ($generic as $file) {
                   21387:                             if (isset($package['install-as'][$file])) {
                   21388:                                 $installas = $package['install-as'][$file];
                   21389:                             } else {
                   21390:                                 $installas = $file;
                   21391:                             }
                   21392:                             $release[count($oses)]['filelist']['install'][] =
                   21393:                                 array(
                   21394:                                     'attribs' => array(
                   21395:                                         'name' => $file,
                   21396:                                         'as' => $installas,
                   21397:                                     )
                   21398:                                 );
                   21399:                         }
                   21400:                     }
                   21401:                     if (count($genericIgnore)) {
                   21402:                         foreach ($genericIgnore as $file) {
                   21403:                             $release[count($oses)]['filelist']['ignore'][] =
                   21404:                                 array(
                   21405:                                     'attribs' => array(
                   21406:                                         'name' => $file,
                   21407:                                     )
                   21408:                                 );
                   21409:                         }
                   21410:                     }
                   21411:                 }
                   21412:                 // cleanup
                   21413:                 foreach ($release as $i => $rel) {
                   21414:                     if (isset($rel['filelist']['install']) &&
                   21415:                           count($rel['filelist']['install']) == 1) {
                   21416:                         $release[$i]['filelist']['install'] =
                   21417:                             $release[$i]['filelist']['install'][0];
                   21418:                     }
                   21419:                     if (isset($rel['filelist']['ignore']) &&
                   21420:                           count($rel['filelist']['ignore']) == 1) {
                   21421:                         $release[$i]['filelist']['ignore'] =
                   21422:                             $release[$i]['filelist']['ignore'][0];
                   21423:                     }
                   21424:                 }
                   21425:                 if (count($release) == 1) {
                   21426:                     $release = $release[0];
                   21427:                 }
                   21428:             } else {
                   21429:                 // no platform atts, but some install-as atts
                   21430:                 foreach ($package['install-as'] as $file => $value) {
                   21431:                     $release['filelist']['install'][] =
                   21432:                         array(
                   21433:                             'attribs' => array(
                   21434:                                 'name' => $file,
                   21435:                                 'as' => $value
                   21436:                             )
                   21437:                         );
                   21438:                 }
                   21439:                 if (count($release['filelist']['install']) == 1) {
                   21440:                     $release['filelist']['install'] = $release['filelist']['install'][0];
                   21441:                 }
                   21442:             }
                   21443:         }
                   21444:     }
                   21445: 
                   21446:     /**
                   21447:      * @param array
                   21448:      * @return array
                   21449:      * @access private
                   21450:      */
                   21451:     function _processDep($dep)
                   21452:     {
                   21453:         if ($dep['type'] == 'php') {
                   21454:             if ($dep['rel'] == 'has') {
                   21455:                 // come on - everyone has php!
                   21456:                 return false;
                   21457:             }
                   21458:         }
                   21459:         $php = array();
                   21460:         if ($dep['type'] != 'php') {
                   21461:             $php['name'] = $dep['name'];
                   21462:             if ($dep['type'] == 'pkg') {
                   21463:                 $php['channel'] = 'pear.php.net';
                   21464:             }
                   21465:         }
                   21466:         switch ($dep['rel']) {
                   21467:             case 'gt' :
                   21468:                 $php['min'] = $dep['version'];
                   21469:                 $php['exclude'] = $dep['version'];
                   21470:             break;
                   21471:             case 'ge' :
                   21472:                 if (!isset($dep['version'])) {
                   21473:                     if ($dep['type'] == 'php') {
                   21474:                         if (isset($dep['name'])) {
                   21475:                             $dep['version'] = $dep['name'];
                   21476:                         }
                   21477:                     }
                   21478:                 }
                   21479:                 $php['min'] = $dep['version'];
                   21480:             break;
                   21481:             case 'lt' :
                   21482:                 $php['max'] = $dep['version'];
                   21483:                 $php['exclude'] = $dep['version'];
                   21484:             break;
                   21485:             case 'le' :
                   21486:                 $php['max'] = $dep['version'];
                   21487:             break;
                   21488:             case 'eq' :
                   21489:                 $php['min'] = $dep['version'];
                   21490:                 $php['max'] = $dep['version'];
                   21491:             break;
                   21492:             case 'ne' :
                   21493:                 $php['exclude'] = $dep['version'];
                   21494:             break;
                   21495:             case 'not' :
                   21496:                 $php['conflicts'] = 'yes';
                   21497:             break;
                   21498:         }
                   21499:         return $php;
                   21500:     }
                   21501: 
                   21502:     /**
                   21503:      * @param array
                   21504:      * @return array
                   21505:      */
                   21506:     function _processPhpDeps($deps)
                   21507:     {
                   21508:         $test = array();
                   21509:         foreach ($deps as $dep) {
                   21510:             $test[] = $this->_processDep($dep);
                   21511:         }
                   21512:         $min = array();
                   21513:         $max = array();
                   21514:         foreach ($test as $dep) {
                   21515:             if (!$dep) {
                   21516:                 continue;
                   21517:             }
                   21518:             if (isset($dep['min'])) {
                   21519:                 $min[$dep['min']] = count($min);
                   21520:             }
                   21521:             if (isset($dep['max'])) {
                   21522:                 $max[$dep['max']] = count($max);
                   21523:             }
                   21524:         }
                   21525:         if (count($min) > 0) {
                   21526:             uksort($min, 'version_compare');
                   21527:         }
                   21528:         if (count($max) > 0) {
                   21529:             uksort($max, 'version_compare');
                   21530:         }
                   21531:         if (count($min)) {
                   21532:             // get the highest minimum
                   21533:             $min = array_pop($a = array_flip($min));
                   21534:         } else {
                   21535:             $min = false;
                   21536:         }
                   21537:         if (count($max)) {
                   21538:             // get the lowest maximum
                   21539:             $max = array_shift($a = array_flip($max));
                   21540:         } else {
                   21541:             $max = false;
                   21542:         }
                   21543:         if ($min) {
                   21544:             $php['min'] = $min;
                   21545:         }
                   21546:         if ($max) {
                   21547:             $php['max'] = $max;
                   21548:         }
                   21549:         $exclude = array();
                   21550:         foreach ($test as $dep) {
                   21551:             if (!isset($dep['exclude'])) {
                   21552:                 continue;
                   21553:             }
                   21554:             $exclude[] = $dep['exclude'];
                   21555:         }
                   21556:         if (count($exclude)) {
                   21557:             $php['exclude'] = $exclude;
                   21558:         }
                   21559:         return $php;
                   21560:     }
                   21561: 
                   21562:     /**
                   21563:      * process multiple dependencies that have a name, like package deps
                   21564:      * @param array
                   21565:      * @return array
                   21566:      * @access private
                   21567:      */
                   21568:     function _processMultipleDepsName($deps)
                   21569:     {
                   21570:         $ret = $tests = array();
                   21571:         foreach ($deps as $name => $dep) {
                   21572:             foreach ($dep as $d) {
                   21573:                 $tests[$name][] = $this->_processDep($d);
                   21574:             }
                   21575:         }
                   21576: 
                   21577:         foreach ($tests as $name => $test) {
                   21578:             $max = $min = $php = array();
                   21579:             $php['name'] = $name;
                   21580:             foreach ($test as $dep) {
                   21581:                 if (!$dep) {
                   21582:                     continue;
                   21583:                 }
                   21584:                 if (isset($dep['channel'])) {
                   21585:                     $php['channel'] = 'pear.php.net';
                   21586:                 }
                   21587:                 if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
                   21588:                     $php['conflicts'] = 'yes';
                   21589:                 }
                   21590:                 if (isset($dep['min'])) {
                   21591:                     $min[$dep['min']] = count($min);
                   21592:                 }
                   21593:                 if (isset($dep['max'])) {
                   21594:                     $max[$dep['max']] = count($max);
                   21595:                 }
                   21596:             }
                   21597:             if (count($min) > 0) {
                   21598:                 uksort($min, 'version_compare');
                   21599:             }
                   21600:             if (count($max) > 0) {
                   21601:                 uksort($max, 'version_compare');
                   21602:             }
                   21603:             if (count($min)) {
                   21604:                 // get the highest minimum
                   21605:                 $min = array_pop($a = array_flip($min));
                   21606:             } else {
                   21607:                 $min = false;
                   21608:             }
                   21609:             if (count($max)) {
                   21610:                 // get the lowest maximum
                   21611:                 $max = array_shift($a = array_flip($max));
                   21612:             } else {
                   21613:                 $max = false;
                   21614:             }
                   21615:             if ($min) {
                   21616:                 $php['min'] = $min;
                   21617:             }
                   21618:             if ($max) {
                   21619:                 $php['max'] = $max;
                   21620:             }
                   21621:             $exclude = array();
                   21622:             foreach ($test as $dep) {
                   21623:                 if (!isset($dep['exclude'])) {
                   21624:                     continue;
                   21625:                 }
                   21626:                 $exclude[] = $dep['exclude'];
                   21627:             }
                   21628:             if (count($exclude)) {
                   21629:                 $php['exclude'] = $exclude;
                   21630:             }
                   21631:             $ret[] = $php;
                   21632:         }
                   21633:         return $ret;
                   21634:     }
                   21635: }
                   21636: ?>PEAR-1.9.4/PEAR/PackageFile/Generator/v2.php0000644000076500000240000010136011605156760017107 0ustar  helgistaff<?php
                   21637: /**
                   21638:  * package.xml generation class, package.xml version 2.0
                   21639:  *
                   21640:  * PHP versions 4 and 5
                   21641:  *
                   21642:  * @category   pear
                   21643:  * @package    PEAR
                   21644:  * @author     Greg Beaver <cellog@php.net>
                   21645:  * @author     Stephan Schmidt (original XML_Serializer code)
                   21646:  * @copyright  1997-2009 The Authors
                   21647:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   21648:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   21649:  * @link       http://pear.php.net/package/PEAR
                   21650:  * @since      File available since Release 1.4.0a1
                   21651:  */
                   21652: /**
                   21653:  * file/dir manipulation routines
                   21654:  */
                   21655: require_once 'System.php';
                   21656: require_once 'XML/Util.php';
                   21657: 
                   21658: /**
                   21659:  * This class converts a PEAR_PackageFile_v2 object into any output format.
                   21660:  *
                   21661:  * Supported output formats include array, XML string (using S. Schmidt's
                   21662:  * XML_Serializer, slightly customized)
                   21663:  * @category   pear
                   21664:  * @package    PEAR
                   21665:  * @author     Greg Beaver <cellog@php.net>
                   21666:  * @author     Stephan Schmidt (original XML_Serializer code)
                   21667:  * @copyright  1997-2009 The Authors
                   21668:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   21669:  * @version    Release: 1.9.4
                   21670:  * @link       http://pear.php.net/package/PEAR
                   21671:  * @since      Class available since Release 1.4.0a1
                   21672:  */
                   21673: class PEAR_PackageFile_Generator_v2
                   21674: {
                   21675:    /**
                   21676:     * default options for the serialization
                   21677:     * @access private
                   21678:     * @var array $_defaultOptions
                   21679:     */
                   21680:     var $_defaultOptions = array(
                   21681:         'indent'             => ' ',                    // string used for indentation
                   21682:         'linebreak'          => "\n",                  // string used for newlines
                   21683:         'typeHints'          => false,                 // automatically add type hin attributes
                   21684:         'addDecl'            => true,                 // add an XML declaration
                   21685:         'defaultTagName'     => 'XML_Serializer_Tag',  // tag used for indexed arrays or invalid names
                   21686:         'classAsTagName'     => false,                 // use classname for objects in indexed arrays
                   21687:         'keyAttribute'       => '_originalKey',        // attribute where original key is stored
                   21688:         'typeAttribute'      => '_type',               // attribute for type (only if typeHints => true)
                   21689:         'classAttribute'     => '_class',              // attribute for class of objects (only if typeHints => true)
                   21690:         'scalarAsAttributes' => false,                 // scalar values (strings, ints,..) will be serialized as attribute
                   21691:         'prependAttributes'  => '',                    // prepend string for attributes
                   21692:         'indentAttributes'   => false,                 // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
                   21693:         'mode'               => 'simplexml',             // use 'simplexml' to use parent name as tagname if transforming an indexed array
                   21694:         'addDoctype'         => false,                 // add a doctype declaration
                   21695:         'doctype'            => null,                  // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
                   21696:         'rootName'           => 'package',                  // name of the root tag
                   21697:         'rootAttributes'     => array(
                   21698:             'version' => '2.0',
                   21699:             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   21700:             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   21701:             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   21702:             'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   21703: http://pear.php.net/dtd/tasks-1.0.xsd
                   21704: http://pear.php.net/dtd/package-2.0
                   21705: http://pear.php.net/dtd/package-2.0.xsd',
                   21706:         ),               // attributes of the root tag
                   21707:         'attributesArray'    => 'attribs',                  // all values in this key will be treated as attributes
                   21708:         'contentName'        => '_content',                   // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
                   21709:         'beautifyFilelist'   => false,
                   21710:         'encoding' => 'UTF-8',
                   21711:     );
                   21712: 
                   21713:    /**
                   21714:     * options for the serialization
                   21715:     * @access private
                   21716:     * @var array $options
                   21717:     */
                   21718:     var $options = array();
                   21719: 
                   21720:    /**
                   21721:     * current tag depth
                   21722:     * @var integer $_tagDepth
                   21723:     */
                   21724:     var $_tagDepth = 0;
                   21725: 
                   21726:    /**
                   21727:     * serilialized representation of the data
                   21728:     * @var string $_serializedData
                   21729:     */
                   21730:     var $_serializedData = null;
                   21731:     /**
                   21732:      * @var PEAR_PackageFile_v2
                   21733:      */
                   21734:     var $_packagefile;
                   21735:     /**
                   21736:      * @param PEAR_PackageFile_v2
                   21737:      */
                   21738:     function PEAR_PackageFile_Generator_v2(&$packagefile)
                   21739:     {
                   21740:         $this->_packagefile = &$packagefile;
                   21741:         if (isset($this->_packagefile->encoding)) {
                   21742:             $this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
                   21743:         }
                   21744:     }
                   21745: 
                   21746:     /**
                   21747:      * @return string
                   21748:      */
                   21749:     function getPackagerVersion()
                   21750:     {
                   21751:         return '1.9.4';
                   21752:     }
                   21753: 
                   21754:     /**
                   21755:      * @param PEAR_Packager
                   21756:      * @param bool generate a .tgz or a .tar
                   21757:      * @param string|null temporary directory to package in
                   21758:      */
                   21759:     function toTgz(&$packager, $compress = true, $where = null)
                   21760:     {
                   21761:         $a = null;
                   21762:         return $this->toTgz2($packager, $a, $compress, $where);
                   21763:     }
                   21764: 
                   21765:     /**
                   21766:      * Package up both a package.xml and package2.xml for the same release
                   21767:      * @param PEAR_Packager
                   21768:      * @param PEAR_PackageFile_v1
                   21769:      * @param bool generate a .tgz or a .tar
                   21770:      * @param string|null temporary directory to package in
                   21771:      */
                   21772:     function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
                   21773:     {
                   21774:         require_once 'Archive/Tar.php';
                   21775:         if (!$this->_packagefile->isEquivalent($pf1)) {
                   21776:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
                   21777:                 basename($pf1->getPackageFile()) .
                   21778:                 '" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
                   21779:                 . '"');
                   21780:         }
                   21781: 
                   21782:         if ($where === null) {
                   21783:             if (!($where = System::mktemp(array('-d')))) {
                   21784:                 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
                   21785:             }
                   21786:         } elseif (!@System::mkDir(array('-p', $where))) {
                   21787:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
                   21788:                 ' not be created');
                   21789:         }
                   21790: 
                   21791:         $file = $where . DIRECTORY_SEPARATOR . 'package.xml';
                   21792:         if (file_exists($file) && !is_file($file)) {
                   21793:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
                   21794:                 ' "' . $file  .'"');
                   21795:         }
                   21796: 
                   21797:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   21798:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
                   21799:         }
                   21800: 
                   21801:         $ext = $compress ? '.tgz' : '.tar';
                   21802:         $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
                   21803:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   21804:         if (file_exists($dest_package) && !is_file($dest_package)) {
                   21805:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
                   21806:                 $dest_package . '"');
                   21807:         }
                   21808: 
                   21809:         $pkgfile = $this->_packagefile->getPackageFile();
                   21810:         if (!$pkgfile) {
                   21811:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
                   21812:                 'be created from a real file');
                   21813:         }
                   21814: 
                   21815:         $pkgdir  = dirname(realpath($pkgfile));
                   21816:         $pkgfile = basename($pkgfile);
                   21817: 
                   21818:         // {{{ Create the package file list
                   21819:         $filelist = array();
                   21820:         $i = 0;
                   21821:         $this->_packagefile->flattenFilelist();
                   21822:         $contents = $this->_packagefile->getContents();
                   21823:         if (isset($contents['bundledpackage'])) { // bundles of packages
                   21824:             $contents = $contents['bundledpackage'];
                   21825:             if (!isset($contents[0])) {
                   21826:                 $contents = array($contents);
                   21827:             }
                   21828: 
                   21829:             $packageDir = $where;
                   21830:             foreach ($contents as $i => $package) {
                   21831:                 $fname = $package;
                   21832:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   21833:                 if (!file_exists($file)) {
                   21834:                     return $packager->raiseError("File does not exist: $fname");
                   21835:                 }
                   21836: 
                   21837:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   21838:                 System::mkdir(array('-p', dirname($tfile)));
                   21839:                 copy($file, $tfile);
                   21840:                 $filelist[$i++] = $tfile;
                   21841:                 $packager->log(2, "Adding package $fname");
                   21842:             }
                   21843:         } else { // normal packages
                   21844:             $contents = $contents['dir']['file'];
                   21845:             if (!isset($contents[0])) {
                   21846:                 $contents = array($contents);
                   21847:             }
                   21848: 
                   21849:             $packageDir = $where;
                   21850:             foreach ($contents as $i => $file) {
                   21851:                 $fname = $file['attribs']['name'];
                   21852:                 $atts = $file['attribs'];
                   21853:                 $orig = $file;
                   21854:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   21855:                 if (!file_exists($file)) {
                   21856:                     return $packager->raiseError("File does not exist: $fname");
                   21857:                 }
                   21858: 
                   21859:                 $origperms = fileperms($file);
                   21860:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   21861:                 unset($orig['attribs']);
                   21862:                 if (count($orig)) { // file with tasks
                   21863:                     // run any package-time tasks
                   21864:                     $contents = file_get_contents($file);
                   21865:                     foreach ($orig as $tag => $raw) {
                   21866:                         $tag = str_replace(
                   21867:                             array($this->_packagefile->getTasksNs() . ':', '-'),
                   21868:                             array('', '_'), $tag);
                   21869:                         $task = "PEAR_Task_$tag";
                   21870:                         $task = &new $task($this->_packagefile->_config,
                   21871:                             $this->_packagefile->_logger,
                   21872:                             PEAR_TASK_PACKAGE);
                   21873:                         $task->init($raw, $atts, null);
                   21874:                         $res = $task->startSession($this->_packagefile, $contents, $tfile);
                   21875:                         if (!$res) {
                   21876:                             continue; // skip this task
                   21877:                         }
                   21878: 
                   21879:                         if (PEAR::isError($res)) {
                   21880:                             return $res;
                   21881:                         }
                   21882: 
                   21883:                         $contents = $res; // save changes
                   21884:                         System::mkdir(array('-p', dirname($tfile)));
                   21885:                         $wp = fopen($tfile, "wb");
                   21886:                         fwrite($wp, $contents);
                   21887:                         fclose($wp);
                   21888:                     }
                   21889:                 }
                   21890: 
                   21891:                 if (!file_exists($tfile)) {
                   21892:                     System::mkdir(array('-p', dirname($tfile)));
                   21893:                     copy($file, $tfile);
                   21894:                 }
                   21895: 
                   21896:                 chmod($tfile, $origperms);
                   21897:                 $filelist[$i++] = $tfile;
                   21898:                 $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
                   21899:                 $packager->log(2, "Adding file $fname");
                   21900:             }
                   21901:         }
                   21902:             // }}}
                   21903: 
                   21904:         $name       = $pf1 !== null ? 'package2.xml' : 'package.xml';
                   21905:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
                   21906:         if ($packagexml) {
                   21907:             $tar =& new Archive_Tar($dest_package, $compress);
                   21908:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   21909:             // ----- Creates with the package.xml file
                   21910:             $ok = $tar->createModify(array($packagexml), '', $where);
                   21911:             if (PEAR::isError($ok)) {
                   21912:                 return $packager->raiseError($ok);
                   21913:             } elseif (!$ok) {
                   21914:                 return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
                   21915:                     ' failed');
                   21916:             }
                   21917: 
                   21918:             // ----- Add the content of the package
                   21919:             if (!$tar->addModify($filelist, $pkgver, $where)) {
                   21920:                 return $packager->raiseError(
                   21921:                     'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
                   21922:             }
                   21923: 
                   21924:             // add the package.xml version 1.0
                   21925:             if ($pf1 !== null) {
                   21926:                 $pfgen = &$pf1->getDefaultGenerator();
                   21927:                 $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   21928:                 if (!$tar->addModify(array($packagexml1), '', $where)) {
                   21929:                     return $packager->raiseError(
                   21930:                         'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
                   21931:                 }
                   21932:             }
                   21933: 
                   21934:             return $dest_package;
                   21935:         }
                   21936:     }
                   21937: 
                   21938:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
                   21939:     {
                   21940:         if (!$this->_packagefile->validate($state)) {
                   21941:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
                   21942:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   21943:         }
                   21944: 
                   21945:         if ($where === null) {
                   21946:             if (!($where = System::mktemp(array('-d')))) {
                   21947:                 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
                   21948:             }
                   21949:         } elseif (!@System::mkDir(array('-p', $where))) {
                   21950:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
                   21951:                 ' not be created');
                   21952:         }
                   21953: 
                   21954:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   21955:         $np = @fopen($newpkgfile, 'wb');
                   21956:         if (!$np) {
                   21957:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
                   21958:                "$name as $newpkgfile");
                   21959:         }
                   21960:         fwrite($np, $this->toXml($state));
                   21961:         fclose($np);
                   21962:         return $newpkgfile;
                   21963:     }
                   21964: 
                   21965:     function &toV2()
                   21966:     {
                   21967:         return $this->_packagefile;
                   21968:     }
                   21969: 
                   21970:     /**
                   21971:      * Return an XML document based on the package info (as returned
                   21972:      * by the PEAR_Common::infoFrom* methods).
                   21973:      *
                   21974:      * @return string XML data
                   21975:      */
                   21976:     function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
                   21977:     {
                   21978:         $this->_packagefile->setDate(date('Y-m-d'));
                   21979:         $this->_packagefile->setTime(date('H:i:s'));
                   21980:         if (!$this->_packagefile->validate($state)) {
                   21981:             return false;
                   21982:         }
                   21983: 
                   21984:         if (is_array($options)) {
                   21985:             $this->options = array_merge($this->_defaultOptions, $options);
                   21986:         } else {
                   21987:             $this->options = $this->_defaultOptions;
                   21988:         }
                   21989: 
                   21990:         $arr = $this->_packagefile->getArray();
                   21991:         if (isset($arr['filelist'])) {
                   21992:             unset($arr['filelist']);
                   21993:         }
                   21994: 
                   21995:         if (isset($arr['_lastversion'])) {
                   21996:             unset($arr['_lastversion']);
                   21997:         }
                   21998: 
                   21999:         // Fix the notes a little bit
                   22000:         if (isset($arr['notes'])) {
                   22001:             // This trims out the indenting, needs fixing
                   22002:             $arr['notes'] = "\n" . trim($arr['notes']) . "\n";
                   22003:         }
                   22004: 
                   22005:         if (isset($arr['changelog']) && !empty($arr['changelog'])) {
                   22006:             // Fix for inconsistency how the array is filled depending on the changelog release amount
                   22007:             if (!isset($arr['changelog']['release'][0])) {
                   22008:                 $release = $arr['changelog']['release'];
                   22009:                 unset($arr['changelog']['release']);
                   22010: 
                   22011:                 $arr['changelog']['release']    = array();
                   22012:                 $arr['changelog']['release'][0] = $release;
                   22013:             }
                   22014: 
                   22015:             foreach (array_keys($arr['changelog']['release']) as $key) {
                   22016:                 $c =& $arr['changelog']['release'][$key];
                   22017:                 if (isset($c['notes'])) {
                   22018:                     // This trims out the indenting, needs fixing
                   22019:                     $c['notes'] = "\n" . trim($c['notes']) . "\n";
                   22020:                 }
                   22021:             }
                   22022:         }
                   22023: 
                   22024:         if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
                   22025:             $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
                   22026:             unset($arr['contents']['dir']['file']);
                   22027:             if (isset($use['dir'])) {
                   22028:                 $arr['contents']['dir']['dir'] = $use['dir'];
                   22029:             }
                   22030:             if (isset($use['file'])) {
                   22031:                 $arr['contents']['dir']['file'] = $use['file'];
                   22032:             }
                   22033:             $this->options['beautifyFilelist'] = true;
                   22034:         }
                   22035: 
                   22036:         $arr['attribs']['packagerversion'] = '1.9.4';
                   22037:         if ($this->serialize($arr, $options)) {
                   22038:             return $this->_serializedData . "\n";
                   22039:         }
                   22040: 
                   22041:         return false;
                   22042:     }
                   22043: 
                   22044: 
                   22045:     function _recursiveXmlFilelist($list)
                   22046:     {
                   22047:         $dirs = array();
                   22048:         if (isset($list['attribs'])) {
                   22049:             $file = $list['attribs']['name'];
                   22050:             unset($list['attribs']['name']);
                   22051:             $attributes = $list['attribs'];
                   22052:             $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
                   22053:         } else {
                   22054:             foreach ($list as $a) {
                   22055:                 $file = $a['attribs']['name'];
                   22056:                 $attributes = $a['attribs'];
                   22057:                 unset($a['attribs']);
                   22058:                 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
                   22059:             }
                   22060:         }
                   22061:         $this->_formatDir($dirs);
                   22062:         $this->_deFormat($dirs);
                   22063:         return $dirs;
                   22064:     }
                   22065: 
                   22066:     function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
                   22067:     {
                   22068:         if (!$tasks) {
                   22069:             $tasks = array();
                   22070:         }
                   22071:         if ($dir == array() || $dir == array('.')) {
                   22072:             $dirs['file'][basename($file)] = $tasks;
                   22073:             $attributes['name'] = basename($file);
                   22074:             $dirs['file'][basename($file)]['attribs'] = $attributes;
                   22075:             return;
                   22076:         }
                   22077:         $curdir = array_shift($dir);
                   22078:         if (!isset($dirs['dir'][$curdir])) {
                   22079:             $dirs['dir'][$curdir] = array();
                   22080:         }
                   22081:         $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
                   22082:     }
                   22083: 
                   22084:     function _formatDir(&$dirs)
                   22085:     {
                   22086:         if (!count($dirs)) {
                   22087:             return array();
                   22088:         }
                   22089:         $newdirs = array();
                   22090:         if (isset($dirs['dir'])) {
                   22091:             $newdirs['dir'] = $dirs['dir'];
                   22092:         }
                   22093:         if (isset($dirs['file'])) {
                   22094:             $newdirs['file'] = $dirs['file'];
                   22095:         }
                   22096:         $dirs = $newdirs;
                   22097:         if (isset($dirs['dir'])) {
                   22098:             uksort($dirs['dir'], 'strnatcasecmp');
                   22099:             foreach ($dirs['dir'] as $dir => $contents) {
                   22100:                 $this->_formatDir($dirs['dir'][$dir]);
                   22101:             }
                   22102:         }
                   22103:         if (isset($dirs['file'])) {
                   22104:             uksort($dirs['file'], 'strnatcasecmp');
                   22105:         };
                   22106:     }
                   22107: 
                   22108:     function _deFormat(&$dirs)
                   22109:     {
                   22110:         if (!count($dirs)) {
                   22111:             return array();
                   22112:         }
                   22113:         $newdirs = array();
                   22114:         if (isset($dirs['dir'])) {
                   22115:             foreach ($dirs['dir'] as $dir => $contents) {
                   22116:                 $newdir = array();
                   22117:                 $newdir['attribs']['name'] = $dir;
                   22118:                 $this->_deFormat($contents);
                   22119:                 foreach ($contents as $tag => $val) {
                   22120:                     $newdir[$tag] = $val;
                   22121:                 }
                   22122:                 $newdirs['dir'][] = $newdir;
                   22123:             }
                   22124:             if (count($newdirs['dir']) == 1) {
                   22125:                 $newdirs['dir'] = $newdirs['dir'][0];
                   22126:             }
                   22127:         }
                   22128:         if (isset($dirs['file'])) {
                   22129:             foreach ($dirs['file'] as $name => $file) {
                   22130:                 $newdirs['file'][] = $file;
                   22131:             }
                   22132:             if (count($newdirs['file']) == 1) {
                   22133:                 $newdirs['file'] = $newdirs['file'][0];
                   22134:             }
                   22135:         }
                   22136:         $dirs = $newdirs;
                   22137:     }
                   22138: 
                   22139:     /**
                   22140:     * reset all options to default options
                   22141:     *
                   22142:     * @access   public
                   22143:     * @see      setOption(), XML_Unserializer()
                   22144:     */
                   22145:     function resetOptions()
                   22146:     {
                   22147:         $this->options = $this->_defaultOptions;
                   22148:     }
                   22149: 
                   22150:    /**
                   22151:     * set an option
                   22152:     *
                   22153:     * You can use this method if you do not want to set all options in the constructor
                   22154:     *
                   22155:     * @access   public
                   22156:     * @see      resetOption(), XML_Serializer()
                   22157:     */
                   22158:     function setOption($name, $value)
                   22159:     {
                   22160:         $this->options[$name] = $value;
                   22161:     }
                   22162: 
                   22163:    /**
                   22164:     * sets several options at once
                   22165:     *
                   22166:     * You can use this method if you do not want to set all options in the constructor
                   22167:     *
                   22168:     * @access   public
                   22169:     * @see      resetOption(), XML_Unserializer(), setOption()
                   22170:     */
                   22171:     function setOptions($options)
                   22172:     {
                   22173:         $this->options = array_merge($this->options, $options);
                   22174:     }
                   22175: 
                   22176:    /**
                   22177:     * serialize data
                   22178:     *
                   22179:     * @access   public
                   22180:     * @param    mixed    $data data to serialize
                   22181:     * @return   boolean  true on success, pear error on failure
                   22182:     */
                   22183:     function serialize($data, $options = null)
                   22184:     {
                   22185:         // if options have been specified, use them instead
                   22186:         // of the previously defined ones
                   22187:         if (is_array($options)) {
                   22188:             $optionsBak = $this->options;
                   22189:             if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
                   22190:                 $this->options = array_merge($this->_defaultOptions, $options);
                   22191:             } else {
                   22192:                 $this->options = array_merge($this->options, $options);
                   22193:             }
                   22194:         } else {
                   22195:             $optionsBak = null;
                   22196:         }
                   22197: 
                   22198:         //  start depth is zero
                   22199:         $this->_tagDepth = 0;
                   22200:         $this->_serializedData = '';
                   22201:         // serialize an array
                   22202:         if (is_array($data)) {
                   22203:             $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
                   22204:             $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
                   22205:         }
                   22206: 
                   22207:         // add doctype declaration
                   22208:         if ($this->options['addDoctype'] === true) {
                   22209:             $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
                   22210:                                    . $this->options['linebreak']
                   22211:                                    . $this->_serializedData;
                   22212:         }
                   22213: 
                   22214:         //  build xml declaration
                   22215:         if ($this->options['addDecl']) {
                   22216:             $atts = array();
                   22217:             $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
                   22218:             $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
                   22219:                                    . $this->options['linebreak']
                   22220:                                    . $this->_serializedData;
                   22221:         }
                   22222: 
                   22223: 
                   22224:         if ($optionsBak !== null) {
                   22225:             $this->options = $optionsBak;
                   22226:         }
                   22227: 
                   22228:         return  true;
                   22229:     }
                   22230: 
                   22231:    /**
                   22232:     * get the result of the serialization
                   22233:     *
                   22234:     * @access public
                   22235:     * @return string serialized XML
                   22236:     */
                   22237:     function getSerializedData()
                   22238:     {
                   22239:         if ($this->_serializedData === null) {
                   22240:             return  $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
                   22241:         }
                   22242:         return $this->_serializedData;
                   22243:     }
                   22244: 
                   22245:    /**
                   22246:     * serialize any value
                   22247:     *
                   22248:     * This method checks for the type of the value and calls the appropriate method
                   22249:     *
                   22250:     * @access private
                   22251:     * @param  mixed     $value
                   22252:     * @param  string    $tagName
                   22253:     * @param  array     $attributes
                   22254:     * @return string
                   22255:     */
                   22256:     function _serializeValue($value, $tagName = null, $attributes = array())
                   22257:     {
                   22258:         if (is_array($value)) {
                   22259:             $xml = $this->_serializeArray($value, $tagName, $attributes);
                   22260:         } elseif (is_object($value)) {
                   22261:             $xml = $this->_serializeObject($value, $tagName);
                   22262:         } else {
                   22263:             $tag = array(
                   22264:                           'qname'      => $tagName,
                   22265:                           'attributes' => $attributes,
                   22266:                           'content'    => $value
                   22267:                         );
                   22268:             $xml = $this->_createXMLTag($tag);
                   22269:         }
                   22270:         return $xml;
                   22271:     }
                   22272: 
                   22273:    /**
                   22274:     * serialize an array
                   22275:     *
                   22276:     * @access   private
                   22277:     * @param    array   $array       array to serialize
                   22278:     * @param    string  $tagName     name of the root tag
                   22279:     * @param    array   $attributes  attributes for the root tag
                   22280:     * @return   string  $string      serialized data
                   22281:     * @uses     XML_Util::isValidName() to check, whether key has to be substituted
                   22282:     */
                   22283:     function _serializeArray(&$array, $tagName = null, $attributes = array())
                   22284:     {
                   22285:         $_content = null;
                   22286: 
                   22287:         /**
                   22288:          * check for special attributes
                   22289:          */
                   22290:         if ($this->options['attributesArray'] !== null) {
                   22291:             if (isset($array[$this->options['attributesArray']])) {
                   22292:                 $attributes = $array[$this->options['attributesArray']];
                   22293:                 unset($array[$this->options['attributesArray']]);
                   22294:             }
                   22295:             /**
                   22296:              * check for special content
                   22297:              */
                   22298:             if ($this->options['contentName'] !== null) {
                   22299:                 if (isset($array[$this->options['contentName']])) {
                   22300:                     $_content = $array[$this->options['contentName']];
                   22301:                     unset($array[$this->options['contentName']]);
                   22302:                 }
                   22303:             }
                   22304:         }
                   22305: 
                   22306:         /*
                   22307:         * if mode is set to simpleXML, check whether
                   22308:         * the array is associative or indexed
                   22309:         */
                   22310:         if (is_array($array) && $this->options['mode'] == 'simplexml') {
                   22311:             $indexed = true;
                   22312:             if (!count($array)) {
                   22313:                 $indexed = false;
                   22314:             }
                   22315:             foreach ($array as $key => $val) {
                   22316:                 if (!is_int($key)) {
                   22317:                     $indexed = false;
                   22318:                     break;
                   22319:                 }
                   22320:             }
                   22321: 
                   22322:             if ($indexed && $this->options['mode'] == 'simplexml') {
                   22323:                 $string = '';
                   22324:                 foreach ($array as $key => $val) {
                   22325:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   22326:                         if (!isset($this->_curdir)) {
                   22327:                             $this->_curdir = '';
                   22328:                         }
                   22329:                         $savedir = $this->_curdir;
                   22330:                         if (isset($val['attribs'])) {
                   22331:                             if ($val['attribs']['name'] == '/') {
                   22332:                                 $this->_curdir = '/';
                   22333:                             } else {
                   22334:                                 if ($this->_curdir == '/') {
                   22335:                                     $this->_curdir = '';
                   22336:                                 }
                   22337:                                 $this->_curdir .= '/' . $val['attribs']['name'];
                   22338:                             }
                   22339:                         }
                   22340:                     }
                   22341:                     $string .= $this->_serializeValue( $val, $tagName, $attributes);
                   22342:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   22343:                         $string .= ' <!-- ' . $this->_curdir . ' -->';
                   22344:                         if (empty($savedir)) {
                   22345:                             unset($this->_curdir);
                   22346:                         } else {
                   22347:                             $this->_curdir = $savedir;
                   22348:                         }
                   22349:                     }
                   22350: 
                   22351:                     $string .= $this->options['linebreak'];
                   22352:                     // do indentation
                   22353:                     if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   22354:                         $string .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22355:                     }
                   22356:                 }
                   22357:                 return rtrim($string);
                   22358:             }
                   22359:         }
                   22360: 
                   22361:         if ($this->options['scalarAsAttributes'] === true) {
                   22362:             foreach ($array as $key => $value) {
                   22363:                 if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
                   22364:                     unset($array[$key]);
                   22365:                     $attributes[$this->options['prependAttributes'].$key] = $value;
                   22366:                 }
                   22367:             }
                   22368:         }
                   22369: 
                   22370:         // check for empty array => create empty tag
                   22371:         if (empty($array)) {
                   22372:             $tag = array(
                   22373:                             'qname'      => $tagName,
                   22374:                             'content'    => $_content,
                   22375:                             'attributes' => $attributes
                   22376:                         );
                   22377: 
                   22378:         } else {
                   22379:             $this->_tagDepth++;
                   22380:             $tmp = $this->options['linebreak'];
                   22381:             foreach ($array as $key => $value) {
                   22382:                 // do indentation
                   22383:                 if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   22384:                     $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22385:                 }
                   22386: 
                   22387:                 // copy key
                   22388:                 $origKey = $key;
                   22389:                 // key cannot be used as tagname => use default tag
                   22390:                 $valid = XML_Util::isValidName($key);
                   22391:                 if (PEAR::isError($valid)) {
                   22392:                     if ($this->options['classAsTagName'] && is_object($value)) {
                   22393:                         $key = get_class($value);
                   22394:                     } else {
                   22395:                         $key = $this->options['defaultTagName'];
                   22396:                     }
                   22397:                 }
                   22398:                 $atts = array();
                   22399:                 if ($this->options['typeHints'] === true) {
                   22400:                     $atts[$this->options['typeAttribute']] = gettype($value);
                   22401:                     if ($key !== $origKey) {
                   22402:                         $atts[$this->options['keyAttribute']] = (string)$origKey;
                   22403:                     }
                   22404: 
                   22405:                 }
                   22406:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   22407:                     if (!isset($this->_curdir)) {
                   22408:                         $this->_curdir = '';
                   22409:                     }
                   22410:                     $savedir = $this->_curdir;
                   22411:                     if (isset($value['attribs'])) {
                   22412:                         if ($value['attribs']['name'] == '/') {
                   22413:                             $this->_curdir = '/';
                   22414:                         } else {
                   22415:                             $this->_curdir .= '/' . $value['attribs']['name'];
                   22416:                         }
                   22417:                     }
                   22418:                 }
                   22419: 
                   22420:                 if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
                   22421:                     $value .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22422:                 }
                   22423:                 $tmp .= $this->_createXMLTag(array(
                   22424:                                                     'qname'      => $key,
                   22425:                                                     'attributes' => $atts,
                   22426:                                                     'content'    => $value )
                   22427:                                             );
                   22428:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   22429:                     if (isset($value['attribs'])) {
                   22430:                         $tmp .= ' <!-- ' . $this->_curdir . ' -->';
                   22431:                         if (empty($savedir)) {
                   22432:                             unset($this->_curdir);
                   22433:                         } else {
                   22434:                             $this->_curdir = $savedir;
                   22435:                         }
                   22436:                     }
                   22437:                 }
                   22438:                 $tmp .= $this->options['linebreak'];
                   22439:             }
                   22440: 
                   22441:             $this->_tagDepth--;
                   22442:             if ($this->options['indent']!==null && $this->_tagDepth>0) {
                   22443:                 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22444:             }
                   22445: 
                   22446:             if (trim($tmp) === '') {
                   22447:                 $tmp = null;
                   22448:             }
                   22449: 
                   22450:             $tag = array(
                   22451:                 'qname'      => $tagName,
                   22452:                 'content'    => $tmp,
                   22453:                 'attributes' => $attributes
                   22454:             );
                   22455:         }
                   22456:         if ($this->options['typeHints'] === true) {
                   22457:             if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
                   22458:                 $tag['attributes'][$this->options['typeAttribute']] = 'array';
                   22459:             }
                   22460:         }
                   22461: 
                   22462:         $string = $this->_createXMLTag($tag, false);
                   22463:         return $string;
                   22464:     }
                   22465: 
                   22466:    /**
                   22467:     * create a tag from an array
                   22468:     * this method awaits an array in the following format
                   22469:     * array(
                   22470:     *       'qname'        => $tagName,
                   22471:     *       'attributes'   => array(),
                   22472:     *       'content'      => $content,      // optional
                   22473:     *       'namespace'    => $namespace     // optional
                   22474:     *       'namespaceUri' => $namespaceUri  // optional
                   22475:     *   )
                   22476:     *
                   22477:     * @access   private
                   22478:     * @param    array   $tag tag definition
                   22479:     * @param    boolean $replaceEntities whether to replace XML entities in content or not
                   22480:     * @return   string  $string XML tag
                   22481:     */
                   22482:     function _createXMLTag($tag, $replaceEntities = true)
                   22483:     {
                   22484:         if ($this->options['indentAttributes'] !== false) {
                   22485:             $multiline = true;
                   22486:             $indent    = str_repeat($this->options['indent'], $this->_tagDepth);
                   22487: 
                   22488:             if ($this->options['indentAttributes'] == '_auto') {
                   22489:                 $indent .= str_repeat(' ', (strlen($tag['qname'])+2));
                   22490: 
                   22491:             } else {
                   22492:                 $indent .= $this->options['indentAttributes'];
                   22493:             }
                   22494:         } else {
                   22495:             $indent = $multiline = false;
                   22496:         }
                   22497: 
                   22498:         if (is_array($tag['content'])) {
                   22499:             if (empty($tag['content'])) {
                   22500:                 $tag['content'] = '';
                   22501:             }
                   22502:         } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
                   22503:             $tag['content'] = '';
                   22504:         }
                   22505: 
                   22506:         if (is_scalar($tag['content']) || is_null($tag['content'])) {
                   22507:             if ($this->options['encoding'] == 'UTF-8' &&
                   22508:                   version_compare(phpversion(), '5.0.0', 'lt')
                   22509:             ) {
                   22510:                 $tag['content'] = utf8_encode($tag['content']);
                   22511:             }
                   22512: 
                   22513:             if ($replaceEntities === true) {
                   22514:                 $replaceEntities = XML_UTIL_ENTITIES_XML;
                   22515:             }
                   22516: 
                   22517:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
                   22518:         } elseif (is_array($tag['content'])) {
                   22519:             $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
                   22520:         } elseif (is_object($tag['content'])) {
                   22521:             $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
                   22522:         } elseif (is_resource($tag['content'])) {
                   22523:             settype($tag['content'], 'string');
                   22524:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities);
                   22525:         }
                   22526:         return  $tag;
                   22527:     }
                   22528: }PEAR-1.9.4/PEAR/PackageFile/Parser/v1.php0000644000076500000240000004031411605156760016415 0ustar  helgistaff<?php
                   22529: /**
                   22530:  * package.xml parsing class, package.xml version 1.0
                   22531:  *
                   22532:  * PHP versions 4 and 5
                   22533:  *
                   22534:  * @category   pear
                   22535:  * @package    PEAR
                   22536:  * @author     Greg Beaver <cellog@php.net>
                   22537:  * @copyright  1997-2009 The Authors
                   22538:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   22539:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   22540:  * @link       http://pear.php.net/package/PEAR
                   22541:  * @since      File available since Release 1.4.0a1
                   22542:  */
                   22543: /**
                   22544:  * package.xml abstraction class
                   22545:  */
                   22546: require_once 'PEAR/PackageFile/v1.php';
                   22547: /**
                   22548:  * Parser for package.xml version 1.0
                   22549:  * @category   pear
                   22550:  * @package    PEAR
                   22551:  * @author     Greg Beaver <cellog@php.net>
                   22552:  * @copyright  1997-2009 The Authors
                   22553:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   22554:  * @version    Release: @PEAR-VER@
                   22555:  * @link       http://pear.php.net/package/PEAR
                   22556:  * @since      Class available since Release 1.4.0a1
                   22557:  */
                   22558: class PEAR_PackageFile_Parser_v1
                   22559: {
                   22560:     var $_registry;
                   22561:     var $_config;
                   22562:     var $_logger;
                   22563:     /**
                   22564:      * BC hack to allow PEAR_Common::infoFromString() to sort of
                   22565:      * work with the version 2.0 format - there's no filelist though
                   22566:      * @param PEAR_PackageFile_v2
                   22567:      */
                   22568:     function fromV2($packagefile)
                   22569:     {
                   22570:         $info = $packagefile->getArray(true);
                   22571:         $ret = new PEAR_PackageFile_v1;
                   22572:         $ret->fromArray($info['old']);
                   22573:     }
                   22574: 
                   22575:     function setConfig(&$c)
                   22576:     {
                   22577:         $this->_config = &$c;
                   22578:         $this->_registry = &$c->getRegistry();
                   22579:     }
                   22580: 
                   22581:     function setLogger(&$l)
                   22582:     {
                   22583:         $this->_logger = &$l;
                   22584:     }
                   22585: 
                   22586:     /**
                   22587:      * @param string contents of package.xml file, version 1.0
                   22588:      * @return bool success of parsing
                   22589:      */
                   22590:     function &parse($data, $file, $archive = false)
                   22591:     {
                   22592:         if (!extension_loaded('xml')) {
                   22593:             return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
                   22594:         }
                   22595:         $xp = xml_parser_create();
                   22596:         if (!$xp) {
                   22597:             $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
                   22598:             return $a;
                   22599:         }
                   22600:         xml_set_object($xp, $this);
                   22601:         xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
                   22602:         xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
                   22603:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
                   22604: 
                   22605:         $this->element_stack = array();
                   22606:         $this->_packageInfo = array('provides' => array());
                   22607:         $this->current_element = false;
                   22608:         unset($this->dir_install);
                   22609:         $this->_packageInfo['filelist'] = array();
                   22610:         $this->filelist =& $this->_packageInfo['filelist'];
                   22611:         $this->dir_names = array();
                   22612:         $this->in_changelog = false;
                   22613:         $this->d_i = 0;
                   22614:         $this->cdata = '';
                   22615:         $this->_isValid = true;
                   22616: 
                   22617:         if (!xml_parse($xp, $data, 1)) {
                   22618:             $code = xml_get_error_code($xp);
                   22619:             $line = xml_get_current_line_number($xp);
                   22620:             xml_parser_free($xp);
                   22621:             $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
                   22622:                            $str = xml_error_string($code), $line), 2);
                   22623:             return $a;
                   22624:         }
                   22625: 
                   22626:         xml_parser_free($xp);
                   22627: 
                   22628:         $pf = new PEAR_PackageFile_v1;
                   22629:         $pf->setConfig($this->_config);
                   22630:         if (isset($this->_logger)) {
                   22631:             $pf->setLogger($this->_logger);
                   22632:         }
                   22633:         $pf->setPackagefile($file, $archive);
                   22634:         $pf->fromArray($this->_packageInfo);
                   22635:         return $pf;
                   22636:     }
                   22637:     // {{{ _unIndent()
                   22638: 
                   22639:     /**
                   22640:      * Unindent given string
                   22641:      *
                   22642:      * @param string $str The string that has to be unindented.
                   22643:      * @return string
                   22644:      * @access private
                   22645:      */
                   22646:     function _unIndent($str)
                   22647:     {
                   22648:         // remove leading newlines
                   22649:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   22650:         // find whitespace at the beginning of the first line
                   22651:         $indent_len = strspn($str, " \t");
                   22652:         $indent = substr($str, 0, $indent_len);
                   22653:         $data = '';
                   22654:         // remove the same amount of whitespace from following lines
                   22655:         foreach (explode("\n", $str) as $line) {
                   22656:             if (substr($line, 0, $indent_len) == $indent) {
                   22657:                 $data .= substr($line, $indent_len) . "\n";
                   22658:             } elseif (trim(substr($line, 0, $indent_len))) {
                   22659:                 $data .= ltrim($line);
                   22660:             }
                   22661:         }
                   22662:         return $data;
                   22663:     }
                   22664: 
                   22665:     // Support for package DTD v1.0:
                   22666:     // {{{ _element_start_1_0()
                   22667: 
                   22668:     /**
                   22669:      * XML parser callback for ending elements.  Used for version 1.0
                   22670:      * packages.
                   22671:      *
                   22672:      * @param resource  $xp    XML parser resource
                   22673:      * @param string    $name  name of ending element
                   22674:      *
                   22675:      * @return void
                   22676:      *
                   22677:      * @access private
                   22678:      */
                   22679:     function _element_start_1_0($xp, $name, $attribs)
                   22680:     {
                   22681:         array_push($this->element_stack, $name);
                   22682:         $this->current_element = $name;
                   22683:         $spos = sizeof($this->element_stack) - 2;
                   22684:         $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
                   22685:         $this->current_attributes = $attribs;
                   22686:         $this->cdata = '';
                   22687:         switch ($name) {
                   22688:             case 'dir':
                   22689:                 if ($this->in_changelog) {
                   22690:                     break;
                   22691:                 }
                   22692:                 if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
                   22693:                     $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   22694:                         $attribs['name']);
                   22695:                     if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
                   22696:                         $attribs['name'] = substr($attribs['name'], 0,
                   22697:                             strlen($attribs['name']) - 1);
                   22698:                     }
                   22699:                     if (strpos($attribs['name'], '/') === 0) {
                   22700:                         $attribs['name'] = substr($attribs['name'], 1);
                   22701:                     }
                   22702:                     $this->dir_names[] = $attribs['name'];
                   22703:                 }
                   22704:                 if (isset($attribs['baseinstalldir'])) {
                   22705:                     $this->dir_install = $attribs['baseinstalldir'];
                   22706:                 }
                   22707:                 if (isset($attribs['role'])) {
                   22708:                     $this->dir_role = $attribs['role'];
                   22709:                 }
                   22710:                 break;
                   22711:             case 'file':
                   22712:                 if ($this->in_changelog) {
                   22713:                     break;
                   22714:                 }
                   22715:                 if (isset($attribs['name'])) {
                   22716:                     $path = '';
                   22717:                     if (count($this->dir_names)) {
                   22718:                         foreach ($this->dir_names as $dir) {
                   22719:                             $path .= $dir . '/';
                   22720:                         }
                   22721:                     }
                   22722:                     $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   22723:                         $attribs['name']);
                   22724:                     unset($attribs['name']);
                   22725:                     $this->current_path = $path;
                   22726:                     $this->filelist[$path] = $attribs;
                   22727:                     // Set the baseinstalldir only if the file don't have this attrib
                   22728:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   22729:                         isset($this->dir_install))
                   22730:                     {
                   22731:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   22732:                     }
                   22733:                     // Set the Role
                   22734:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   22735:                         $this->filelist[$path]['role'] = $this->dir_role;
                   22736:                     }
                   22737:                 }
                   22738:                 break;
                   22739:             case 'replace':
                   22740:                 if (!$this->in_changelog) {
                   22741:                     $this->filelist[$this->current_path]['replacements'][] = $attribs;
                   22742:                 }
                   22743:                 break;
                   22744:             case 'maintainers':
                   22745:                 $this->_packageInfo['maintainers'] = array();
                   22746:                 $this->m_i = 0; // maintainers array index
                   22747:                 break;
                   22748:             case 'maintainer':
                   22749:                 // compatibility check
                   22750:                 if (!isset($this->_packageInfo['maintainers'])) {
                   22751:                     $this->_packageInfo['maintainers'] = array();
                   22752:                     $this->m_i = 0;
                   22753:                 }
                   22754:                 $this->_packageInfo['maintainers'][$this->m_i] = array();
                   22755:                 $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
                   22756:                 break;
                   22757:             case 'changelog':
                   22758:                 $this->_packageInfo['changelog'] = array();
                   22759:                 $this->c_i = 0; // changelog array index
                   22760:                 $this->in_changelog = true;
                   22761:                 break;
                   22762:             case 'release':
                   22763:                 if ($this->in_changelog) {
                   22764:                     $this->_packageInfo['changelog'][$this->c_i] = array();
                   22765:                     $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
                   22766:                 } else {
                   22767:                     $this->current_release = &$this->_packageInfo;
                   22768:                 }
                   22769:                 break;
                   22770:             case 'deps':
                   22771:                 if (!$this->in_changelog) {
                   22772:                     $this->_packageInfo['release_deps'] = array();
                   22773:                 }
                   22774:                 break;
                   22775:             case 'dep':
                   22776:                 // dependencies array index
                   22777:                 if (!$this->in_changelog) {
                   22778:                     $this->d_i++;
                   22779:                     isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
                   22780:                     $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
                   22781:                 }
                   22782:                 break;
                   22783:             case 'configureoptions':
                   22784:                 if (!$this->in_changelog) {
                   22785:                     $this->_packageInfo['configure_options'] = array();
                   22786:                 }
                   22787:                 break;
                   22788:             case 'configureoption':
                   22789:                 if (!$this->in_changelog) {
                   22790:                     $this->_packageInfo['configure_options'][] = $attribs;
                   22791:                 }
                   22792:                 break;
                   22793:             case 'provides':
                   22794:                 if (empty($attribs['type']) || empty($attribs['name'])) {
                   22795:                     break;
                   22796:                 }
                   22797:                 $attribs['explicit'] = true;
                   22798:                 $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
                   22799:                 break;
                   22800:             case 'package' :
                   22801:                 if (isset($attribs['version'])) {
                   22802:                     $this->_packageInfo['xsdversion'] = trim($attribs['version']);
                   22803:                 } else {
                   22804:                     $this->_packageInfo['xsdversion'] = '1.0';
                   22805:                 }
                   22806:                 if (isset($attribs['packagerversion'])) {
                   22807:                     $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
                   22808:                 }
                   22809:                 break;
                   22810:         }
                   22811:     }
                   22812: 
                   22813:     // }}}
                   22814:     // {{{ _element_end_1_0()
                   22815: 
                   22816:     /**
                   22817:      * XML parser callback for ending elements.  Used for version 1.0
                   22818:      * packages.
                   22819:      *
                   22820:      * @param resource  $xp    XML parser resource
                   22821:      * @param string    $name  name of ending element
                   22822:      *
                   22823:      * @return void
                   22824:      *
                   22825:      * @access private
                   22826:      */
                   22827:     function _element_end_1_0($xp, $name)
                   22828:     {
                   22829:         $data = trim($this->cdata);
                   22830:         switch ($name) {
                   22831:             case 'name':
                   22832:                 switch ($this->prev_element) {
                   22833:                     case 'package':
                   22834:                         $this->_packageInfo['package'] = $data;
                   22835:                         break;
                   22836:                     case 'maintainer':
                   22837:                         $this->current_maintainer['name'] = $data;
                   22838:                         break;
                   22839:                 }
                   22840:                 break;
                   22841:             case 'extends' :
                   22842:                 $this->_packageInfo['extends'] = $data;
                   22843:                 break;
                   22844:             case 'summary':
                   22845:                 $this->_packageInfo['summary'] = $data;
                   22846:                 break;
                   22847:             case 'description':
                   22848:                 $data = $this->_unIndent($this->cdata);
                   22849:                 $this->_packageInfo['description'] = $data;
                   22850:                 break;
                   22851:             case 'user':
                   22852:                 $this->current_maintainer['handle'] = $data;
                   22853:                 break;
                   22854:             case 'email':
                   22855:                 $this->current_maintainer['email'] = $data;
                   22856:                 break;
                   22857:             case 'role':
                   22858:                 $this->current_maintainer['role'] = $data;
                   22859:                 break;
                   22860:             case 'version':
                   22861:                 if ($this->in_changelog) {
                   22862:                     $this->current_release['version'] = $data;
                   22863:                 } else {
                   22864:                     $this->_packageInfo['version'] = $data;
                   22865:                 }
                   22866:                 break;
                   22867:             case 'date':
                   22868:                 if ($this->in_changelog) {
                   22869:                     $this->current_release['release_date'] = $data;
                   22870:                 } else {
                   22871:                     $this->_packageInfo['release_date'] = $data;
                   22872:                 }
                   22873:                 break;
                   22874:             case 'notes':
                   22875:                 // try to "de-indent" release notes in case someone
                   22876:                 // has been over-indenting their xml ;-)
                   22877:                 // Trim only on the right side
                   22878:                 $data = rtrim($this->_unIndent($this->cdata));
                   22879:                 if ($this->in_changelog) {
                   22880:                     $this->current_release['release_notes'] = $data;
                   22881:                 } else {
                   22882:                     $this->_packageInfo['release_notes'] = $data;
                   22883:                 }
                   22884:                 break;
                   22885:             case 'warnings':
                   22886:                 if ($this->in_changelog) {
                   22887:                     $this->current_release['release_warnings'] = $data;
                   22888:                 } else {
                   22889:                     $this->_packageInfo['release_warnings'] = $data;
                   22890:                 }
                   22891:                 break;
                   22892:             case 'state':
                   22893:                 if ($this->in_changelog) {
                   22894:                     $this->current_release['release_state'] = $data;
                   22895:                 } else {
                   22896:                     $this->_packageInfo['release_state'] = $data;
                   22897:                 }
                   22898:                 break;
                   22899:             case 'license':
                   22900:                 if ($this->in_changelog) {
                   22901:                     $this->current_release['release_license'] = $data;
                   22902:                 } else {
                   22903:                     $this->_packageInfo['release_license'] = $data;
                   22904:                 }
                   22905:                 break;
                   22906:             case 'dep':
                   22907:                 if ($data && !$this->in_changelog) {
                   22908:                     $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
                   22909:                 }
                   22910:                 break;
                   22911:             case 'dir':
                   22912:                 if ($this->in_changelog) {
                   22913:                     break;
                   22914:                 }
                   22915:                 array_pop($this->dir_names);
                   22916:                 break;
                   22917:             case 'file':
                   22918:                 if ($this->in_changelog) {
                   22919:                     break;
                   22920:                 }
                   22921:                 if ($data) {
                   22922:                     $path = '';
                   22923:                     if (count($this->dir_names)) {
                   22924:                         foreach ($this->dir_names as $dir) {
                   22925:                             $path .= $dir . '/';
                   22926:                         }
                   22927:                     }
                   22928:                     $path .= $data;
                   22929:                     $this->filelist[$path] = $this->current_attributes;
                   22930:                     // Set the baseinstalldir only if the file don't have this attrib
                   22931:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   22932:                         isset($this->dir_install))
                   22933:                     {
                   22934:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   22935:                     }
                   22936:                     // Set the Role
                   22937:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   22938:                         $this->filelist[$path]['role'] = $this->dir_role;
                   22939:                     }
                   22940:                 }
                   22941:                 break;
                   22942:             case 'maintainer':
                   22943:                 if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
                   22944:                     $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
                   22945:                 }
                   22946:                 $this->m_i++;
                   22947:                 break;
                   22948:             case 'release':
                   22949:                 if ($this->in_changelog) {
                   22950:                     $this->c_i++;
                   22951:                 }
                   22952:                 break;
                   22953:             case 'changelog':
                   22954:                 $this->in_changelog = false;
                   22955:                 break;
                   22956:         }
                   22957:         array_pop($this->element_stack);
                   22958:         $spos = sizeof($this->element_stack) - 1;
                   22959:         $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
                   22960:         $this->cdata = '';
                   22961:     }
                   22962: 
                   22963:     // }}}
                   22964:     // {{{ _pkginfo_cdata_1_0()
                   22965: 
                   22966:     /**
                   22967:      * XML parser callback for character data.  Used for version 1.0
                   22968:      * packages.
                   22969:      *
                   22970:      * @param resource  $xp    XML parser resource
                   22971:      * @param string    $name  character data
                   22972:      *
                   22973:      * @return void
                   22974:      *
                   22975:      * @access private
                   22976:      */
                   22977:     function _pkginfo_cdata_1_0($xp, $data)
                   22978:     {
                   22979:         if (isset($this->cdata)) {
                   22980:             $this->cdata .= $data;
                   22981:         }
                   22982:     }
                   22983: 
                   22984:     // }}}
                   22985: }
                   22986: ?>PEAR-1.9.4/PEAR/PackageFile/Parser/v2.php0000644000076500000240000000621511605156760016420 0ustar  helgistaff<?php
                   22987: /**
                   22988:  * package.xml parsing class, package.xml version 2.0
                   22989:  *
                   22990:  * PHP versions 4 and 5
                   22991:  *
                   22992:  * @category   pear
                   22993:  * @package    PEAR
                   22994:  * @author     Greg Beaver <cellog@php.net>
                   22995:  * @copyright  1997-2009 The Authors
                   22996:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   22997:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   22998:  * @link       http://pear.php.net/package/PEAR
                   22999:  * @since      File available since Release 1.4.0a1
                   23000:  */
                   23001: /**
                   23002:  * base xml parser class
                   23003:  */
                   23004: require_once 'PEAR/XMLParser.php';
                   23005: require_once 'PEAR/PackageFile/v2.php';
                   23006: /**
                   23007:  * Parser for package.xml version 2.0
                   23008:  * @category   pear
                   23009:  * @package    PEAR
                   23010:  * @author     Greg Beaver <cellog@php.net>
                   23011:  * @copyright  1997-2009 The Authors
                   23012:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23013:  * @version    Release: @PEAR-VER@
                   23014:  * @link       http://pear.php.net/package/PEAR
                   23015:  * @since      Class available since Release 1.4.0a1
                   23016:  */
                   23017: class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
                   23018: {
                   23019:     var $_config;
                   23020:     var $_logger;
                   23021:     var $_registry;
                   23022: 
                   23023:     function setConfig(&$c)
                   23024:     {
                   23025:         $this->_config = &$c;
                   23026:         $this->_registry = &$c->getRegistry();
                   23027:     }
                   23028: 
                   23029:     function setLogger(&$l)
                   23030:     {
                   23031:         $this->_logger = &$l;
                   23032:     }
                   23033:     /**
                   23034:      * Unindent given string
                   23035:      *
                   23036:      * @param string $str The string that has to be unindented.
                   23037:      * @return string
                   23038:      * @access private
                   23039:      */
                   23040:     function _unIndent($str)
                   23041:     {
                   23042:         // remove leading newlines
                   23043:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   23044:         // find whitespace at the beginning of the first line
                   23045:         $indent_len = strspn($str, " \t");
                   23046:         $indent = substr($str, 0, $indent_len);
                   23047:         $data = '';
                   23048:         // remove the same amount of whitespace from following lines
                   23049:         foreach (explode("\n", $str) as $line) {
                   23050:             if (substr($line, 0, $indent_len) == $indent) {
                   23051:                 $data .= substr($line, $indent_len) . "\n";
                   23052:             } else {
                   23053:                 $data .= $line . "\n";
                   23054:             }
                   23055:         }
                   23056:         return $data;
                   23057:     }
                   23058: 
                   23059:     /**
                   23060:      * post-process data
                   23061:      *
                   23062:      * @param string $data
                   23063:      * @param string $element element name
                   23064:      */
                   23065:     function postProcess($data, $element)
                   23066:     {
                   23067:         if ($element == 'notes') {
                   23068:             return trim($this->_unIndent($data));
                   23069:         }
                   23070:         return trim($data);
                   23071:     }
                   23072: 
                   23073:     /**
                   23074:      * @param string
                   23075:      * @param string file name of the package.xml
                   23076:      * @param string|false name of the archive this package.xml came from, if any
                   23077:      * @param string class name to instantiate and return.  This must be PEAR_PackageFile_v2 or
                   23078:      *               a subclass
                   23079:      * @return PEAR_PackageFile_v2
                   23080:      */
                   23081:     function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
                   23082:     {
                   23083:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   23084:             return $err;
                   23085:         }
                   23086: 
                   23087:         $ret = new $class;
                   23088:         $ret->encoding = $this->encoding;
                   23089:         $ret->setConfig($this->_config);
                   23090:         if (isset($this->_logger)) {
                   23091:             $ret->setLogger($this->_logger);
                   23092:         }
                   23093: 
                   23094:         $ret->fromArray($this->_unserializedData);
                   23095:         $ret->setPackagefile($file, $archive);
                   23096:         return $ret;
                   23097:     }
                   23098: }PEAR-1.9.4/PEAR/PackageFile/v2/rw.php0000644000076500000240000017321011605156760015614 0ustar  helgistaff<?php
                   23099: /**
                   23100:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
                   23101:  *
                   23102:  * PHP versions 4 and 5
                   23103:  *
                   23104:  * @category   pear
                   23105:  * @package    PEAR
                   23106:  * @author     Greg Beaver <cellog@php.net>
                   23107:  * @copyright  1997-2009 The Authors
                   23108:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23109:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   23110:  * @link       http://pear.php.net/package/PEAR
                   23111:  * @since      File available since Release 1.4.0a8
                   23112:  */
                   23113: /**
                   23114:  * For base class
                   23115:  */
                   23116: require_once 'PEAR/PackageFile/v2.php';
                   23117: /**
                   23118:  * @category   pear
                   23119:  * @package    PEAR
                   23120:  * @author     Greg Beaver <cellog@php.net>
                   23121:  * @copyright  1997-2009 The Authors
                   23122:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23123:  * @version    Release: 1.9.4
                   23124:  * @link       http://pear.php.net/package/PEAR
                   23125:  * @since      Class available since Release 1.4.0a8
                   23126:  */
                   23127: class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                   23128: {
                   23129:     /**
                   23130:      * @param string Extension name
                   23131:      * @return bool success of operation
                   23132:      */
                   23133:     function setProvidesExtension($extension)
                   23134:     {
                   23135:         if (in_array($this->getPackageType(),
                   23136:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   23137:             if (!isset($this->_packageInfo['providesextension'])) {
                   23138:                 // ensure that the channel tag is set up in the right location
                   23139:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23140:                     array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                   23141:                     'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23142:                     'bundle', 'changelog'),
                   23143:                     $extension, 'providesextension');
                   23144:             }
                   23145:             $this->_packageInfo['providesextension'] = $extension;
                   23146:             return true;
                   23147:         }
                   23148:         return false;
                   23149:     }
                   23150: 
                   23151:     function setPackage($package)
                   23152:     {
                   23153:         $this->_isValid = 0;
                   23154:         if (!isset($this->_packageInfo['attribs'])) {
                   23155:             $this->_packageInfo = array_merge(array('attribs' => array(
                   23156:                                  'version' => '2.0',
                   23157:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   23158:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   23159:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   23160:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   23161:     http://pear.php.net/dtd/tasks-1.0.xsd
                   23162:     http://pear.php.net/dtd/package-2.0
                   23163:     http://pear.php.net/dtd/package-2.0.xsd',
                   23164:                              )), $this->_packageInfo);
                   23165:         }
                   23166:         if (!isset($this->_packageInfo['name'])) {
                   23167:             return $this->_packageInfo = array_merge(array('name' => $package),
                   23168:                 $this->_packageInfo);
                   23169:         }
                   23170:         $this->_packageInfo['name'] = $package;
                   23171:     }
                   23172: 
                   23173:     /**
                   23174:      * set this as a package.xml version 2.1
                   23175:      * @access private
                   23176:      */
                   23177:     function _setPackageVersion2_1()
                   23178:     {
                   23179:         $info = array(
                   23180:                                  'version' => '2.1',
                   23181:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.1',
                   23182:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   23183:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   23184:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   23185:     http://pear.php.net/dtd/tasks-1.0.xsd
                   23186:     http://pear.php.net/dtd/package-2.1
                   23187:     http://pear.php.net/dtd/package-2.1.xsd',
                   23188:                              );
                   23189:         if (!isset($this->_packageInfo['attribs'])) {
                   23190:             $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
                   23191:         } else {
                   23192:             $this->_packageInfo['attribs'] = $info;
                   23193:         }
                   23194:     }
                   23195: 
                   23196:     function setUri($uri)
                   23197:     {
                   23198:         unset($this->_packageInfo['channel']);
                   23199:         $this->_isValid = 0;
                   23200:         if (!isset($this->_packageInfo['uri'])) {
                   23201:             // ensure that the uri tag is set up in the right location
                   23202:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23203:                 array('extends', 'summary', 'description', 'lead',
                   23204:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23205:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23206:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23207:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23208:                 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
                   23209:         }
                   23210:         $this->_packageInfo['uri'] = $uri;
                   23211:     }
                   23212: 
                   23213:     function setChannel($channel)
                   23214:     {
                   23215:         unset($this->_packageInfo['uri']);
                   23216:         $this->_isValid = 0;
                   23217:         if (!isset($this->_packageInfo['channel'])) {
                   23218:             // ensure that the channel tag is set up in the right location
                   23219:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23220:                 array('extends', 'summary', 'description', 'lead',
                   23221:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23222:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23223:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23224:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23225:                 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
                   23226:         }
                   23227:         $this->_packageInfo['channel'] = $channel;
                   23228:     }
                   23229: 
                   23230:     function setExtends($extends)
                   23231:     {
                   23232:         $this->_isValid = 0;
                   23233:         if (!isset($this->_packageInfo['extends'])) {
                   23234:             // ensure that the extends tag is set up in the right location
                   23235:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23236:                 array('summary', 'description', 'lead',
                   23237:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23238:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23239:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23240:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23241:                 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
                   23242:         }
                   23243:         $this->_packageInfo['extends'] = $extends;
                   23244:     }
                   23245: 
                   23246:     function setSummary($summary)
                   23247:     {
                   23248:         $this->_isValid = 0;
                   23249:         if (!isset($this->_packageInfo['summary'])) {
                   23250:             // ensure that the summary tag is set up in the right location
                   23251:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23252:                 array('description', 'lead',
                   23253:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23254:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23255:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23256:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23257:                 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
                   23258:         }
                   23259:         $this->_packageInfo['summary'] = $summary;
                   23260:     }
                   23261: 
                   23262:     function setDescription($desc)
                   23263:     {
                   23264:         $this->_isValid = 0;
                   23265:         if (!isset($this->_packageInfo['description'])) {
                   23266:             // ensure that the description tag is set up in the right location
                   23267:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23268:                 array('lead',
                   23269:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23270:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23271:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23272:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23273:                 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
                   23274:         }
                   23275:         $this->_packageInfo['description'] = $desc;
                   23276:     }
                   23277: 
                   23278:     /**
                   23279:      * Adds a new maintainer - no checking of duplicates is performed, use
                   23280:      * updatemaintainer for that purpose.
                   23281:      */
                   23282:     function addMaintainer($role, $handle, $name, $email, $active = 'yes')
                   23283:     {
                   23284:         if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
                   23285:             return false;
                   23286:         }
                   23287:         if (isset($this->_packageInfo[$role])) {
                   23288:             if (!isset($this->_packageInfo[$role][0])) {
                   23289:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
                   23290:             }
                   23291:             $this->_packageInfo[$role][] =
                   23292:                 array(
                   23293:                     'name' => $name,
                   23294:                     'user' => $handle,
                   23295:                     'email' => $email,
                   23296:                     'active' => $active,
                   23297:                 );
                   23298:         } else {
                   23299:             $testarr = array('lead',
                   23300:                     'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23301:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   23302:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23303:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23304:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
                   23305:             foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
                   23306:                 array_shift($testarr);
                   23307:                 if ($role == $testrole) {
                   23308:                     break;
                   23309:                 }
                   23310:             }
                   23311:             if (!isset($this->_packageInfo[$role])) {
                   23312:                 // ensure that the extends tag is set up in the right location
                   23313:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
                   23314:                     array(), $role);
                   23315:             }
                   23316:             $this->_packageInfo[$role] =
                   23317:                 array(
                   23318:                     'name' => $name,
                   23319:                     'user' => $handle,
                   23320:                     'email' => $email,
                   23321:                     'active' => $active,
                   23322:                 );
                   23323:         }
                   23324:         $this->_isValid = 0;
                   23325:     }
                   23326: 
                   23327:     function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
                   23328:     {
                   23329:         $found = false;
                   23330:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   23331:             if (!isset($this->_packageInfo[$role])) {
                   23332:                 continue;
                   23333:             }
                   23334:             $info = $this->_packageInfo[$role];
                   23335:             if (!isset($info[0])) {
                   23336:                 if ($info['user'] == $handle) {
                   23337:                     $found = true;
                   23338:                     break;
                   23339:                 }
                   23340:             }
                   23341:             foreach ($info as $i => $maintainer) {
                   23342:                 if ($maintainer['user'] == $handle) {
                   23343:                     $found = $i;
                   23344:                     break 2;
                   23345:                 }
                   23346:             }
                   23347:         }
                   23348:         if ($found === false) {
                   23349:             return $this->addMaintainer($newrole, $handle, $name, $email, $active);
                   23350:         }
                   23351:         if ($found !== false) {
                   23352:             if ($found === true) {
                   23353:                 unset($this->_packageInfo[$role]);
                   23354:             } else {
                   23355:                 unset($this->_packageInfo[$role][$found]);
                   23356:                 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
                   23357:             }
                   23358:         }
                   23359:         $this->addMaintainer($newrole, $handle, $name, $email, $active);
                   23360:         $this->_isValid = 0;
                   23361:     }
                   23362: 
                   23363:     function deleteMaintainer($handle)
                   23364:     {
                   23365:         $found = false;
                   23366:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   23367:             if (!isset($this->_packageInfo[$role])) {
                   23368:                 continue;
                   23369:             }
                   23370:             if (!isset($this->_packageInfo[$role][0])) {
                   23371:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
                   23372:             }
                   23373:             foreach ($this->_packageInfo[$role] as $i => $maintainer) {
                   23374:                 if ($maintainer['user'] == $handle) {
                   23375:                     $found = $i;
                   23376:                     break;
                   23377:                 }
                   23378:             }
                   23379:             if ($found !== false) {
                   23380:                 unset($this->_packageInfo[$role][$found]);
                   23381:                 if (!count($this->_packageInfo[$role]) && $role == 'lead') {
                   23382:                     $this->_isValid = 0;
                   23383:                 }
                   23384:                 if (!count($this->_packageInfo[$role])) {
                   23385:                     unset($this->_packageInfo[$role]);
                   23386:                     return true;
                   23387:                 }
                   23388:                 $this->_packageInfo[$role] =
                   23389:                     array_values($this->_packageInfo[$role]);
                   23390:                 if (count($this->_packageInfo[$role]) == 1) {
                   23391:                     $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
                   23392:                 }
                   23393:                 return true;
                   23394:             }
                   23395:             if (count($this->_packageInfo[$role]) == 1) {
                   23396:                 $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
                   23397:             }
                   23398:         }
                   23399:         return false;
                   23400:     }
                   23401: 
                   23402:     function setReleaseVersion($version)
                   23403:     {
                   23404:         if (isset($this->_packageInfo['version']) &&
                   23405:               isset($this->_packageInfo['version']['release'])) {
                   23406:             unset($this->_packageInfo['version']['release']);
                   23407:         }
                   23408:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
                   23409:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                   23410:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23411:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23412:                 'extbinrelease', 'bundle', 'changelog'),
                   23413:             'release' => array('api')));
                   23414:         $this->_isValid = 0;
                   23415:     }
                   23416: 
                   23417:     function setAPIVersion($version)
                   23418:     {
                   23419:         if (isset($this->_packageInfo['version']) &&
                   23420:               isset($this->_packageInfo['version']['api'])) {
                   23421:             unset($this->_packageInfo['version']['api']);
                   23422:         }
                   23423:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
                   23424:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                   23425:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23426:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23427:                 'extbinrelease', 'bundle', 'changelog'),
                   23428:             'api' => array()));
                   23429:         $this->_isValid = 0;
                   23430:     }
                   23431: 
                   23432:     /**
                   23433:      * snapshot|devel|alpha|beta|stable
                   23434:      */
                   23435:     function setReleaseStability($state)
                   23436:     {
                   23437:         if (isset($this->_packageInfo['stability']) &&
                   23438:               isset($this->_packageInfo['stability']['release'])) {
                   23439:             unset($this->_packageInfo['stability']['release']);
                   23440:         }
                   23441:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
                   23442:             'stability' => array('license', 'notes', 'contents', 'compatible',
                   23443:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23444:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23445:                 'extbinrelease', 'bundle', 'changelog'),
                   23446:             'release' => array('api')));
                   23447:         $this->_isValid = 0;
                   23448:     }
                   23449: 
                   23450:     /**
                   23451:      * @param devel|alpha|beta|stable
                   23452:      */
                   23453:     function setAPIStability($state)
                   23454:     {
                   23455:         if (isset($this->_packageInfo['stability']) &&
                   23456:               isset($this->_packageInfo['stability']['api'])) {
                   23457:             unset($this->_packageInfo['stability']['api']);
                   23458:         }
                   23459:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
                   23460:             'stability' => array('license', 'notes', 'contents', 'compatible',
                   23461:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23462:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23463:                 'extbinrelease', 'bundle', 'changelog'),
                   23464:             'api' => array()));
                   23465:         $this->_isValid = 0;
                   23466:     }
                   23467: 
                   23468:     function setLicense($license, $uri = false, $filesource = false)
                   23469:     {
                   23470:         if (!isset($this->_packageInfo['license'])) {
                   23471:             // ensure that the license tag is set up in the right location
                   23472:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23473:                 array('notes', 'contents', 'compatible',
                   23474:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23475:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23476:                 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
                   23477:         }
                   23478:         if ($uri || $filesource) {
                   23479:             $attribs = array();
                   23480:             if ($uri) {
                   23481:                 $attribs['uri'] = $uri;
                   23482:             }
                   23483:             $uri = true; // for test below
                   23484:             if ($filesource) {
                   23485:                 $attribs['filesource'] = $filesource;
                   23486:             }
                   23487:         }
                   23488:         $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
                   23489:         $this->_packageInfo['license'] = $license;
                   23490:         $this->_isValid = 0;
                   23491:     }
                   23492: 
                   23493:     function setNotes($notes)
                   23494:     {
                   23495:         $this->_isValid = 0;
                   23496:         if (!isset($this->_packageInfo['notes'])) {
                   23497:             // ensure that the notes tag is set up in the right location
                   23498:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23499:                 array('contents', 'compatible',
                   23500:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23501:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23502:                 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
                   23503:         }
                   23504:         $this->_packageInfo['notes'] = $notes;
                   23505:     }
                   23506: 
                   23507:     /**
                   23508:      * This is only used at install-time, after all serialization
                   23509:      * is over.
                   23510:      * @param string file name
                   23511:      * @param string installed path
                   23512:      */
                   23513:     function setInstalledAs($file, $path)
                   23514:     {
                   23515:         if ($path) {
                   23516:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   23517:         }
                   23518:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   23519:     }
                   23520: 
                   23521:     /**
                   23522:      * This is only used at install-time, after all serialization
                   23523:      * is over.
                   23524:      */
                   23525:     function installedFile($file, $atts)
                   23526:     {
                   23527:         if (isset($this->_packageInfo['filelist'][$file])) {
                   23528:             $this->_packageInfo['filelist'][$file] =
                   23529:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
                   23530:         } else {
                   23531:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
                   23532:         }
                   23533:     }
                   23534: 
                   23535:     /**
                   23536:      * Reset the listing of package contents
                   23537:      * @param string base installation dir for the whole package, if any
                   23538:      */
                   23539:     function clearContents($baseinstall = false)
                   23540:     {
                   23541:         $this->_filesValid = false;
                   23542:         $this->_isValid = 0;
                   23543:         if (!isset($this->_packageInfo['contents'])) {
                   23544:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23545:                 array('compatible',
                   23546:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23547:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23548:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23549:                     'bundle', 'changelog'), array(), 'contents');
                   23550:         }
                   23551:         if ($this->getPackageType() != 'bundle') {
                   23552:             $this->_packageInfo['contents'] =
                   23553:                 array('dir' => array('attribs' => array('name' => '/')));
                   23554:             if ($baseinstall) {
                   23555:                 $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
                   23556:             }
                   23557:         } else {
                   23558:             $this->_packageInfo['contents'] = array('bundledpackage' => array());
                   23559:         }
                   23560:     }
                   23561: 
                   23562:     /**
                   23563:      * @param string relative path of the bundled package.
                   23564:      */
                   23565:     function addBundledPackage($path)
                   23566:     {
                   23567:         if ($this->getPackageType() != 'bundle') {
                   23568:             return false;
                   23569:         }
                   23570:         $this->_filesValid = false;
                   23571:         $this->_isValid = 0;
                   23572:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
                   23573:                 'contents' => array('compatible', 'dependencies', 'providesextension',
                   23574:                 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                   23575:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23576:                 'bundle', 'changelog'),
                   23577:                 'bundledpackage' => array()));
                   23578:     }
                   23579: 
                   23580:     /**
                   23581:      * @param string file name
                   23582:      * @param PEAR_Task_Common a read/write task
                   23583:      */
                   23584:     function addTaskToFile($filename, $task)
                   23585:     {
                   23586:         if (!method_exists($task, 'getXml')) {
                   23587:             return false;
                   23588:         }
                   23589:         if (!method_exists($task, 'getName')) {
                   23590:             return false;
                   23591:         }
                   23592:         if (!method_exists($task, 'validate')) {
                   23593:             return false;
                   23594:         }
                   23595:         if (!$task->validate()) {
                   23596:             return false;
                   23597:         }
                   23598:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
                   23599:             return false;
                   23600:         }
                   23601:         $this->getTasksNs(); // discover the tasks namespace if not done already
                   23602:         $files = $this->_packageInfo['contents']['dir']['file'];
                   23603:         if (!isset($files[0])) {
                   23604:             $files = array($files);
                   23605:             $ind = false;
                   23606:         } else {
                   23607:             $ind = true;
                   23608:         }
                   23609:         foreach ($files as $i => $file) {
                   23610:             if (isset($file['attribs'])) {
                   23611:                 if ($file['attribs']['name'] == $filename) {
                   23612:                     if ($ind) {
                   23613:                         $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
                   23614:                               ['attribs'][$this->_tasksNs .
                   23615:                               ':' . $task->getName()]) ?
                   23616:                               $this->_packageInfo['contents']['dir']['file'][$i]
                   23617:                               ['attribs'][$this->_tasksNs .
                   23618:                               ':' . $task->getName()] : false;
                   23619:                         if ($t && !isset($t[0])) {
                   23620:                             $this->_packageInfo['contents']['dir']['file'][$i]
                   23621:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
                   23622:                         }
                   23623:                         $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
                   23624:                             ':' . $task->getName()][] = $task->getXml();
                   23625:                     } else {
                   23626:                         $t = isset($this->_packageInfo['contents']['dir']['file']
                   23627:                               ['attribs'][$this->_tasksNs .
                   23628:                               ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
                   23629:                               ['attribs'][$this->_tasksNs .
                   23630:                               ':' . $task->getName()] : false;
                   23631:                         if ($t && !isset($t[0])) {
                   23632:                             $this->_packageInfo['contents']['dir']['file']
                   23633:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
                   23634:                         }
                   23635:                         $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
                   23636:                             ':' . $task->getName()][] = $task->getXml();
                   23637:                     }
                   23638:                     return true;
                   23639:                 }
                   23640:             }
                   23641:         }
                   23642:         return false;
                   23643:     }
                   23644: 
                   23645:     /**
                   23646:      * @param string path to the file
                   23647:      * @param string filename
                   23648:      * @param array extra attributes
                   23649:      */
                   23650:     function addFile($dir, $file, $attrs)
                   23651:     {
                   23652:         if ($this->getPackageType() == 'bundle') {
                   23653:             return false;
                   23654:         }
                   23655:         $this->_filesValid = false;
                   23656:         $this->_isValid = 0;
                   23657:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
                   23658:         if ($dir == '/' || $dir == '') {
                   23659:             $dir = '';
                   23660:         } else {
                   23661:             $dir .= '/';
                   23662:         }
                   23663:         $attrs['name'] = $dir . $file;
                   23664:         if (!isset($this->_packageInfo['contents'])) {
                   23665:             // ensure that the contents tag is set up
                   23666:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23667:                 array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23668:                 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23669:                 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23670:                 'bundle', 'changelog'), array(), 'contents');
                   23671:         }
                   23672:         if (isset($this->_packageInfo['contents']['dir']['file'])) {
                   23673:             if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
                   23674:                 $this->_packageInfo['contents']['dir']['file'] =
                   23675:                     array($this->_packageInfo['contents']['dir']['file']);
                   23676:             }
                   23677:             $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
                   23678:         } else {
                   23679:             $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
                   23680:         }
                   23681:     }
                   23682: 
                   23683:     /**
                   23684:      * @param string Dependent package name
                   23685:      * @param string Dependent package's channel name
                   23686:      * @param string minimum version of specified package that this release is guaranteed to be
                   23687:      *               compatible with
                   23688:      * @param string maximum version of specified package that this release is guaranteed to be
                   23689:      *               compatible with
                   23690:      * @param string versions of specified package that this release is not compatible with
                   23691:      */
                   23692:     function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
                   23693:     {
                   23694:         $this->_isValid = 0;
                   23695:         $set = array(
                   23696:             'name' => $name,
                   23697:             'channel' => $channel,
                   23698:             'min' => $min,
                   23699:             'max' => $max,
                   23700:         );
                   23701:         if ($exclude) {
                   23702:             $set['exclude'] = $exclude;
                   23703:         }
                   23704:         $this->_isValid = 0;
                   23705:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   23706:                 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
                   23707:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23708:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   23709:             ));
                   23710:     }
                   23711: 
                   23712:     /**
                   23713:      * Removes the <usesrole> tag entirely
                   23714:      */
                   23715:     function resetUsesrole()
                   23716:     {
                   23717:         if (isset($this->_packageInfo['usesrole'])) {
                   23718:             unset($this->_packageInfo['usesrole']);
                   23719:         }
                   23720:     }
                   23721: 
                   23722:     /**
                   23723:      * @param string
                   23724:      * @param string package name or uri
                   23725:      * @param string channel name if non-uri
                   23726:      */
                   23727:     function addUsesrole($role, $packageOrUri, $channel = false) {
                   23728:         $set = array('role' => $role);
                   23729:         if ($channel) {
                   23730:             $set['package'] = $packageOrUri;
                   23731:             $set['channel'] = $channel;
                   23732:         } else {
                   23733:             $set['uri'] = $packageOrUri;
                   23734:         }
                   23735:         $this->_isValid = 0;
                   23736:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   23737:                 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
                   23738:                     'phprelease', 'extsrcrelease', 'extbinrelease',
                   23739:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   23740:             ));
                   23741:     }
                   23742: 
                   23743:     /**
                   23744:      * Removes the <usestask> tag entirely
                   23745:      */
                   23746:     function resetUsestask()
                   23747:     {
                   23748:         if (isset($this->_packageInfo['usestask'])) {
                   23749:             unset($this->_packageInfo['usestask']);
                   23750:         }
                   23751:     }
                   23752: 
                   23753: 
                   23754:     /**
                   23755:      * @param string
                   23756:      * @param string package name or uri
                   23757:      * @param string channel name if non-uri
                   23758:      */
                   23759:     function addUsestask($task, $packageOrUri, $channel = false) {
                   23760:         $set = array('task' => $task);
                   23761:         if ($channel) {
                   23762:             $set['package'] = $packageOrUri;
                   23763:             $set['channel'] = $channel;
                   23764:         } else {
                   23765:             $set['uri'] = $packageOrUri;
                   23766:         }
                   23767:         $this->_isValid = 0;
                   23768:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   23769:                 'usestask' => array('srcpackage', 'srcuri',
                   23770:                     'phprelease', 'extsrcrelease', 'extbinrelease',
                   23771:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   23772:             ));
                   23773:     }
                   23774: 
                   23775:     /**
                   23776:      * Remove all compatible tags
                   23777:      */
                   23778:     function clearCompatible()
                   23779:     {
                   23780:         unset($this->_packageInfo['compatible']);
                   23781:     }
                   23782: 
                   23783:     /**
                   23784:      * Reset dependencies prior to adding new ones
                   23785:      */
                   23786:     function clearDeps()
                   23787:     {
                   23788:         if (!isset($this->_packageInfo['dependencies'])) {
                   23789:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                   23790:                 array(
                   23791:                     'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23792:                         'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23793:                         'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
                   23794:         }
                   23795:         $this->_packageInfo['dependencies'] = array();
                   23796:     }
                   23797: 
                   23798:     /**
                   23799:      * @param string minimum PHP version allowed
                   23800:      * @param string maximum PHP version allowed
                   23801:      * @param array $exclude incompatible PHP versions
                   23802:      */
                   23803:     function setPhpDep($min, $max = false, $exclude = false)
                   23804:     {
                   23805:         $this->_isValid = 0;
                   23806:         $dep =
                   23807:             array(
                   23808:                 'min' => $min,
                   23809:             );
                   23810:         if ($max) {
                   23811:             $dep['max'] = $max;
                   23812:         }
                   23813:         if ($exclude) {
                   23814:             if (count($exclude) == 1) {
                   23815:                 $exclude = $exclude[0];
                   23816:             }
                   23817:             $dep['exclude'] = $exclude;
                   23818:         }
                   23819:         if (isset($this->_packageInfo['dependencies']['required']['php'])) {
                   23820:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
                   23821:             $this->_packageInfo['dependencies']['required']['php']),
                   23822:                 'warning: PHP dependency already exists, overwriting');
                   23823:             unset($this->_packageInfo['dependencies']['required']['php']);
                   23824:         }
                   23825:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   23826:             array(
                   23827:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23828:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23829:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   23830:                 'required' => array('optional', 'group'),
                   23831:                 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
                   23832:             ));
                   23833:         return true;
                   23834:     }
                   23835: 
                   23836:     /**
                   23837:      * @param string minimum allowed PEAR installer version
                   23838:      * @param string maximum allowed PEAR installer version
                   23839:      * @param string recommended PEAR installer version
                   23840:      * @param array incompatible version of the PEAR installer
                   23841:      */
                   23842:     function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
                   23843:     {
                   23844:         $this->_isValid = 0;
                   23845:         $dep =
                   23846:             array(
                   23847:                 'min' => $min,
                   23848:             );
                   23849:         if ($max) {
                   23850:             $dep['max'] = $max;
                   23851:         }
                   23852:         if ($recommended) {
                   23853:             $dep['recommended'] = $recommended;
                   23854:         }
                   23855:         if ($exclude) {
                   23856:             if (count($exclude) == 1) {
                   23857:                 $exclude = $exclude[0];
                   23858:             }
                   23859:             $dep['exclude'] = $exclude;
                   23860:         }
                   23861:         if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
                   23862:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
                   23863:             $this->_packageInfo['dependencies']['required']['pearinstaller']),
                   23864:                 'warning: PEAR Installer dependency already exists, overwriting');
                   23865:             unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
                   23866:         }
                   23867:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   23868:             array(
                   23869:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23870:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23871:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   23872:                 'required' => array('optional', 'group'),
                   23873:                 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
                   23874:             ));
                   23875:     }
                   23876: 
                   23877:     /**
                   23878:      * Mark a package as conflicting with this package
                   23879:      * @param string package name
                   23880:      * @param string package channel
                   23881:      * @param string extension this package provides, if any
                   23882:      * @param string|false minimum version required
                   23883:      * @param string|false maximum version allowed
                   23884:      * @param array|false versions to exclude from installation
                   23885:      */
                   23886:     function addConflictingPackageDepWithChannel($name, $channel,
                   23887:                 $providesextension = false, $min = false, $max = false, $exclude = false)
                   23888:     {
                   23889:         $this->_isValid = 0;
                   23890:         $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
                   23891:             $exclude, $providesextension, false, true);
                   23892:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   23893:             array(
                   23894:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23895:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23896:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   23897:                 'required' => array('optional', 'group'),
                   23898:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   23899:             ));
                   23900:     }
                   23901: 
                   23902:     /**
                   23903:      * Mark a package as conflicting with this package
                   23904:      * @param string package name
                   23905:      * @param string package channel
                   23906:      * @param string extension this package provides, if any
                   23907:      */
                   23908:     function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
                   23909:     {
                   23910:         $this->_isValid = 0;
                   23911:         $dep =
                   23912:             array(
                   23913:                 'name' => $name,
                   23914:                 'uri' => $uri,
                   23915:                 'conflicts' => '',
                   23916:             );
                   23917:         if ($providesextension) {
                   23918:             $dep['providesextension'] = $providesextension;
                   23919:         }
                   23920:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   23921:             array(
                   23922:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23923:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23924:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   23925:                 'required' => array('optional', 'group'),
                   23926:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   23927:             ));
                   23928:     }
                   23929: 
                   23930:     function addDependencyGroup($name, $hint)
                   23931:     {
                   23932:         $this->_isValid = 0;
                   23933:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
                   23934:             array('attribs' => array('name' => $name, 'hint' => $hint)),
                   23935:             array(
                   23936:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   23937:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23938:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   23939:                 'group' => array(),
                   23940:             ));
                   23941:     }
                   23942: 
                   23943:     /**
                   23944:      * @param string package name
                   23945:      * @param string|false channel name, false if this is a uri
                   23946:      * @param string|false uri name, false if this is a channel
                   23947:      * @param string|false minimum version required
                   23948:      * @param string|false maximum version allowed
                   23949:      * @param string|false recommended installation version
                   23950:      * @param array|false versions to exclude from installation
                   23951:      * @param string extension this package provides, if any
                   23952:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   23953:      *             when installing this package
                   23954:      * @param bool if true, tells the installer to negate this dependency (conflicts)
                   23955:      * @return array
                   23956:      * @access private
                   23957:      */
                   23958:     function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
                   23959:                            $providesextension = false, $nodefault = false,
                   23960:                            $conflicts = false)
                   23961:     {
                   23962:         $dep =
                   23963:             array(
                   23964:                 'name' => $name,
                   23965:             );
                   23966:         if ($channel) {
                   23967:             $dep['channel'] = $channel;
                   23968:         } elseif ($uri) {
                   23969:             $dep['uri'] = $uri;
                   23970:         }
                   23971:         if ($min) {
                   23972:             $dep['min'] = $min;
                   23973:         }
                   23974:         if ($max) {
                   23975:             $dep['max'] = $max;
                   23976:         }
                   23977:         if ($recommended) {
                   23978:             $dep['recommended'] = $recommended;
                   23979:         }
                   23980:         if ($exclude) {
                   23981:             if (is_array($exclude) && count($exclude) == 1) {
                   23982:                 $exclude = $exclude[0];
                   23983:             }
                   23984:             $dep['exclude'] = $exclude;
                   23985:         }
                   23986:         if ($conflicts) {
                   23987:             $dep['conflicts'] = '';
                   23988:         }
                   23989:         if ($nodefault) {
                   23990:             $dep['nodefault'] = '';
                   23991:         }
                   23992:         if ($providesextension) {
                   23993:             $dep['providesextension'] = $providesextension;
                   23994:         }
                   23995:         return $dep;
                   23996:     }
                   23997: 
                   23998:     /**
                   23999:      * @param package|subpackage
                   24000:      * @param string group name
                   24001:      * @param string package name
                   24002:      * @param string package channel
                   24003:      * @param string minimum version
                   24004:      * @param string maximum version
                   24005:      * @param string recommended version
                   24006:      * @param array|false optional excluded versions
                   24007:      * @param string extension this package provides, if any
                   24008:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24009:      *             when installing this package
                   24010:      * @return bool false if the dependency group has not been initialized with
                   24011:      *              {@link addDependencyGroup()}, or a subpackage is added with
                   24012:      *              a providesextension
                   24013:      */
                   24014:     function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
                   24015:                                       $max = false, $recommended = false, $exclude = false,
                   24016:                                       $providesextension = false, $nodefault = false)
                   24017:     {
                   24018:         if ($type == 'subpackage' && $providesextension) {
                   24019:             return false; // subpackages must be php packages
                   24020:         }
                   24021:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24022:             $providesextension, $nodefault);
                   24023:         return $this->_addGroupDependency($type, $dep, $groupname);
                   24024:     }
                   24025: 
                   24026:     /**
                   24027:      * @param package|subpackage
                   24028:      * @param string group name
                   24029:      * @param string package name
                   24030:      * @param string package uri
                   24031:      * @param string extension this package provides, if any
                   24032:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24033:      *             when installing this package
                   24034:      * @return bool false if the dependency group has not been initialized with
                   24035:      *              {@link addDependencyGroup()}
                   24036:      */
                   24037:     function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
                   24038:                                        $nodefault = false)
                   24039:     {
                   24040:         if ($type == 'subpackage' && $providesextension) {
                   24041:             return false; // subpackages must be php packages
                   24042:         }
                   24043:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
                   24044:             $providesextension, $nodefault);
                   24045:         return $this->_addGroupDependency($type, $dep, $groupname);
                   24046:     }
                   24047: 
                   24048:     /**
                   24049:      * @param string group name (must be pre-existing)
                   24050:      * @param string extension name
                   24051:      * @param string minimum version allowed
                   24052:      * @param string maximum version allowed
                   24053:      * @param string recommended version
                   24054:      * @param array incompatible versions
                   24055:      */
                   24056:     function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
                   24057:                                          $recommended = false, $exclude = false)
                   24058:     {
                   24059:         $this->_isValid = 0;
                   24060:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24061:         return $this->_addGroupDependency('extension', $dep, $groupname);
                   24062:     }
                   24063: 
                   24064:     /**
                   24065:      * @param package|subpackage|extension
                   24066:      * @param array dependency contents
                   24067:      * @param string name of the dependency group to add this to
                   24068:      * @return boolean
                   24069:      * @access private
                   24070:      */
                   24071:     function _addGroupDependency($type, $dep, $groupname)
                   24072:     {
                   24073:         $arr = array('subpackage', 'extension');
                   24074:         if ($type != 'package') {
                   24075:             array_shift($arr);
                   24076:         }
                   24077:         if ($type == 'extension') {
                   24078:             array_shift($arr);
                   24079:         }
                   24080:         if (!isset($this->_packageInfo['dependencies']['group'])) {
                   24081:             return false;
                   24082:         } else {
                   24083:             if (!isset($this->_packageInfo['dependencies']['group'][0])) {
                   24084:                 if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
                   24085:                     $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
                   24086:                         $this->_packageInfo['dependencies']['group'], $dep,
                   24087:                         array(
                   24088:                             $type => $arr
                   24089:                         ));
                   24090:                     $this->_isValid = 0;
                   24091:                     return true;
                   24092:                 } else {
                   24093:                     return false;
                   24094:                 }
                   24095:             } else {
                   24096:                 foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
                   24097:                     if ($group['attribs']['name'] == $groupname) {
                   24098:                     $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
                   24099:                         $this->_packageInfo['dependencies']['group'][$i], $dep,
                   24100:                         array(
                   24101:                             $type => $arr
                   24102:                         ));
                   24103:                         $this->_isValid = 0;
                   24104:                         return true;
                   24105:                     }
                   24106:                 }
                   24107:                 return false;
                   24108:             }
                   24109:         }
                   24110:     }
                   24111: 
                   24112:     /**
                   24113:      * @param optional|required
                   24114:      * @param string package name
                   24115:      * @param string package channel
                   24116:      * @param string minimum version
                   24117:      * @param string maximum version
                   24118:      * @param string recommended version
                   24119:      * @param string extension this package provides, if any
                   24120:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24121:      *             when installing this package
                   24122:      * @param array|false optional excluded versions
                   24123:      */
                   24124:     function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                   24125:                                       $recommended = false, $exclude = false,
                   24126:                                       $providesextension = false, $nodefault = false)
                   24127:     {
                   24128:         if (!in_array($type, array('optional', 'required'), true)) {
                   24129:             $type = 'required';
                   24130:         }
                   24131:         $this->_isValid = 0;
                   24132:         $arr = array('optional', 'group');
                   24133:         if ($type != 'required') {
                   24134:             array_shift($arr);
                   24135:         }
                   24136:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24137:             $providesextension, $nodefault);
                   24138:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24139:             array(
                   24140:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24141:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24142:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24143:                 $type => $arr,
                   24144:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24145:             ));
                   24146:     }
                   24147: 
                   24148:     /**
                   24149:      * @param optional|required
                   24150:      * @param string name of the package
                   24151:      * @param string uri of the package
                   24152:      * @param string extension this package provides, if any
                   24153:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24154:      *             when installing this package
                   24155:      */
                   24156:     function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
                   24157:                                   $nodefault = false)
                   24158:     {
                   24159:         $this->_isValid = 0;
                   24160:         $arr = array('optional', 'group');
                   24161:         if ($type != 'required') {
                   24162:             array_shift($arr);
                   24163:         }
                   24164:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
                   24165:             $providesextension, $nodefault);
                   24166:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24167:             array(
                   24168:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24169:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24170:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24171:                 $type => $arr,
                   24172:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24173:             ));
                   24174:     }
                   24175: 
                   24176:     /**
                   24177:      * @param optional|required optional, required
                   24178:      * @param string package name
                   24179:      * @param string package channel
                   24180:      * @param string minimum version
                   24181:      * @param string maximum version
                   24182:      * @param string recommended version
                   24183:      * @param array incompatible versions
                   24184:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24185:      *             when installing this package
                   24186:      */
                   24187:     function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                   24188:                                          $recommended = false, $exclude = false,
                   24189:                                          $nodefault = false)
                   24190:     {
                   24191:         $this->_isValid = 0;
                   24192:         $arr = array('optional', 'group');
                   24193:         if ($type != 'required') {
                   24194:             array_shift($arr);
                   24195:         }
                   24196:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24197:             $nodefault);
                   24198:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24199:             array(
                   24200:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24201:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24202:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24203:                 $type => $arr,
                   24204:                 'subpackage' => array('extension', 'os', 'arch')
                   24205:             ));
                   24206:     }
                   24207: 
                   24208:     /**
                   24209:      * @param optional|required optional, required
                   24210:      * @param string package name
                   24211:      * @param string package uri for download
                   24212:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24213:      *             when installing this package
                   24214:      */
                   24215:     function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
                   24216:     {
                   24217:         $this->_isValid = 0;
                   24218:         $arr = array('optional', 'group');
                   24219:         if ($type != 'required') {
                   24220:             array_shift($arr);
                   24221:         }
                   24222:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
                   24223:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24224:             array(
                   24225:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24226:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24227:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24228:                 $type => $arr,
                   24229:                 'subpackage' => array('extension', 'os', 'arch')
                   24230:             ));
                   24231:     }
                   24232: 
                   24233:     /**
                   24234:      * @param optional|required optional, required
                   24235:      * @param string extension name
                   24236:      * @param string minimum version
                   24237:      * @param string maximum version
                   24238:      * @param string recommended version
                   24239:      * @param array incompatible versions
                   24240:      */
                   24241:     function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
                   24242:                              $exclude = false)
                   24243:     {
                   24244:         $this->_isValid = 0;
                   24245:         $arr = array('optional', 'group');
                   24246:         if ($type != 'required') {
                   24247:             array_shift($arr);
                   24248:         }
                   24249:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24250:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24251:             array(
                   24252:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24253:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24254:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24255:                 $type => $arr,
                   24256:                 'extension' => array('os', 'arch')
                   24257:             ));
                   24258:     }
                   24259: 
                   24260:     /**
                   24261:      * @param string Operating system name
                   24262:      * @param boolean true if this package cannot be installed on this OS
                   24263:      */
                   24264:     function addOsDep($name, $conflicts = false)
                   24265:     {
                   24266:         $this->_isValid = 0;
                   24267:         $dep = array('name' => $name);
                   24268:         if ($conflicts) {
                   24269:             $dep['conflicts'] = '';
                   24270:         }
                   24271:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24272:             array(
                   24273:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24274:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24275:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24276:                 'required' => array('optional', 'group'),
                   24277:                 'os' => array('arch')
                   24278:             ));
                   24279:     }
                   24280: 
                   24281:     /**
                   24282:      * @param string Architecture matching pattern
                   24283:      * @param boolean true if this package cannot be installed on this architecture
                   24284:      */
                   24285:     function addArchDep($pattern, $conflicts = false)
                   24286:     {
                   24287:         $this->_isValid = 0;
                   24288:         $dep = array('pattern' => $pattern);
                   24289:         if ($conflicts) {
                   24290:             $dep['conflicts'] = '';
                   24291:         }
                   24292:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24293:             array(
                   24294:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24295:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24296:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24297:                 'required' => array('optional', 'group'),
                   24298:                 'arch' => array()
                   24299:             ));
                   24300:     }
                   24301: 
                   24302:     /**
                   24303:      * Set the kind of package, and erase all release tags
                   24304:      *
                   24305:      * - a php package is a PEAR-style package
                   24306:      * - an extbin package is a PECL-style extension binary
                   24307:      * - an extsrc package is a PECL-style source for a binary
                   24308:      * - an zendextbin package is a PECL-style zend extension binary
                   24309:      * - an zendextsrc package is a PECL-style source for a zend extension binary
                   24310:      * - a bundle package is a collection of other pre-packaged packages
                   24311:      * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
                   24312:      * @return bool success
                   24313:      */
                   24314:     function setPackageType($type)
                   24315:     {
                   24316:         $this->_isValid = 0;
                   24317:         if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
                   24318:                                    'zendextbin', 'bundle'))) {
                   24319:             return false;
                   24320:         }
                   24321: 
                   24322:         if (in_array($type, array('zendextsrc', 'zendextbin'))) {
                   24323:             $this->_setPackageVersion2_1();
                   24324:         }
                   24325: 
                   24326:         if ($type != 'bundle') {
                   24327:             $type .= 'release';
                   24328:         }
                   24329: 
                   24330:         foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
                   24331:                        'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
                   24332:             unset($this->_packageInfo[$test]);
                   24333:         }
                   24334: 
                   24335:         if (!isset($this->_packageInfo[$type])) {
                   24336:             // ensure that the release tag is set up
                   24337:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
                   24338:                 array(), $type);
                   24339:         }
                   24340: 
                   24341:         $this->_packageInfo[$type] = array();
                   24342:         return true;
                   24343:     }
                   24344: 
                   24345:     /**
                   24346:      * @return bool true if package type is set up
                   24347:      */
                   24348:     function addRelease()
                   24349:     {
                   24350:         if ($type = $this->getPackageType()) {
                   24351:             if ($type != 'bundle') {
                   24352:                 $type .= 'release';
                   24353:             }
                   24354:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                   24355:                 array($type => array('changelog')));
                   24356:             return true;
                   24357:         }
                   24358:         return false;
                   24359:     }
                   24360: 
                   24361:     /**
                   24362:      * Get the current release tag in order to add to it
                   24363:      * @param bool returns only releases that have installcondition if true
                   24364:      * @return array|null
                   24365:      */
                   24366:     function &_getCurrentRelease($strict = true)
                   24367:     {
                   24368:         if ($p = $this->getPackageType()) {
                   24369:             if ($strict) {
                   24370:                 if ($p == 'extsrc' || $p == 'zendextsrc') {
                   24371:                     $a = null;
                   24372:                     return $a;
                   24373:                 }
                   24374:             }
                   24375:             if ($p != 'bundle') {
                   24376:                 $p .= 'release';
                   24377:             }
                   24378:             if (isset($this->_packageInfo[$p][0])) {
                   24379:                 return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
                   24380:             } else {
                   24381:                 return $this->_packageInfo[$p];
                   24382:             }
                   24383:         } else {
                   24384:             $a = null;
                   24385:             return $a;
                   24386:         }
                   24387:     }
                   24388: 
                   24389:     /**
                   24390:      * Add a file to the current release that should be installed under a different name
                   24391:      * @param string <contents> path to file
                   24392:      * @param string name the file should be installed as
                   24393:      */
                   24394:     function addInstallAs($path, $as)
                   24395:     {
                   24396:         $r = &$this->_getCurrentRelease();
                   24397:         if ($r === null) {
                   24398:             return false;
                   24399:         }
                   24400:         $this->_isValid = 0;
                   24401:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
                   24402:             array(
                   24403:                 'filelist' => array(),
                   24404:                 'install' => array('ignore')
                   24405:             ));
                   24406:     }
                   24407: 
                   24408:     /**
                   24409:      * Add a file to the current release that should be ignored
                   24410:      * @param string <contents> path to file
                   24411:      * @return bool success of operation
                   24412:      */
                   24413:     function addIgnore($path)
                   24414:     {
                   24415:         $r = &$this->_getCurrentRelease();
                   24416:         if ($r === null) {
                   24417:             return false;
                   24418:         }
                   24419:         $this->_isValid = 0;
                   24420:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
                   24421:             array(
                   24422:                 'filelist' => array(),
                   24423:                 'ignore' => array()
                   24424:             ));
                   24425:     }
                   24426: 
                   24427:     /**
                   24428:      * Add an extension binary package for this extension source code release
                   24429:      *
                   24430:      * Note that the package must be from the same channel as the extension source package
                   24431:      * @param string
                   24432:      */
                   24433:     function addBinarypackage($package)
                   24434:     {
                   24435:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   24436:             return false;
                   24437:         }
                   24438:         $r = &$this->_getCurrentRelease(false);
                   24439:         if ($r === null) {
                   24440:             return false;
                   24441:         }
                   24442:         $this->_isValid = 0;
                   24443:         $r = $this->_mergeTag($r, $package,
                   24444:             array(
                   24445:                 'binarypackage' => array('filelist'),
                   24446:             ));
                   24447:     }
                   24448: 
                   24449:     /**
                   24450:      * Add a configureoption to an extension source package
                   24451:      * @param string
                   24452:      * @param string
                   24453:      * @param string
                   24454:      */
                   24455:     function addConfigureOption($name, $prompt, $default = null)
                   24456:     {
                   24457:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   24458:             return false;
                   24459:         }
                   24460: 
                   24461:         $r = &$this->_getCurrentRelease(false);
                   24462:         if ($r === null) {
                   24463:             return false;
                   24464:         }
                   24465: 
                   24466:         $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
                   24467:         if ($default !== null) {
                   24468:             $opt['attribs']['default'] = $default;
                   24469:         }
                   24470: 
                   24471:         $this->_isValid = 0;
                   24472:         $r = $this->_mergeTag($r, $opt,
                   24473:             array(
                   24474:                 'configureoption' => array('binarypackage', 'filelist'),
                   24475:             ));
                   24476:     }
                   24477: 
                   24478:     /**
                   24479:      * Set an installation condition based on php version for the current release set
                   24480:      * @param string minimum version
                   24481:      * @param string maximum version
                   24482:      * @param false|array incompatible versions of PHP
                   24483:      */
                   24484:     function setPhpInstallCondition($min, $max, $exclude = false)
                   24485:     {
                   24486:         $r = &$this->_getCurrentRelease();
                   24487:         if ($r === null) {
                   24488:             return false;
                   24489:         }
                   24490:         $this->_isValid = 0;
                   24491:         if (isset($r['installconditions']['php'])) {
                   24492:             unset($r['installconditions']['php']);
                   24493:         }
                   24494:         $dep = array('min' => $min, 'max' => $max);
                   24495:         if ($exclude) {
                   24496:             if (is_array($exclude) && count($exclude) == 1) {
                   24497:                 $exclude = $exclude[0];
                   24498:             }
                   24499:             $dep['exclude'] = $exclude;
                   24500:         }
                   24501:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24502:             $r = $this->_mergeTag($r, $dep,
                   24503:                 array(
                   24504:                     'installconditions' => array('configureoption', 'binarypackage',
                   24505:                         'filelist'),
                   24506:                     'php' => array('extension', 'os', 'arch')
                   24507:                 ));
                   24508:         } else {
                   24509:             $r = $this->_mergeTag($r, $dep,
                   24510:                 array(
                   24511:                     'installconditions' => array('filelist'),
                   24512:                     'php' => array('extension', 'os', 'arch')
                   24513:                 ));
                   24514:         }
                   24515:     }
                   24516: 
                   24517:     /**
                   24518:      * @param optional|required optional, required
                   24519:      * @param string extension name
                   24520:      * @param string minimum version
                   24521:      * @param string maximum version
                   24522:      * @param string recommended version
                   24523:      * @param array incompatible versions
                   24524:      */
                   24525:     function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
                   24526:                                           $exclude = false)
                   24527:     {
                   24528:         $r = &$this->_getCurrentRelease();
                   24529:         if ($r === null) {
                   24530:             return false;
                   24531:         }
                   24532:         $this->_isValid = 0;
                   24533:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24534:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24535:             $r = $this->_mergeTag($r, $dep,
                   24536:                 array(
                   24537:                     'installconditions' => array('configureoption', 'binarypackage',
                   24538:                         'filelist'),
                   24539:                     'extension' => array('os', 'arch')
                   24540:                 ));
                   24541:         } else {
                   24542:             $r = $this->_mergeTag($r, $dep,
                   24543:                 array(
                   24544:                     'installconditions' => array('filelist'),
                   24545:                     'extension' => array('os', 'arch')
                   24546:                 ));
                   24547:         }
                   24548:     }
                   24549: 
                   24550:     /**
                   24551:      * Set an installation condition based on operating system for the current release set
                   24552:      * @param string OS name
                   24553:      * @param bool whether this OS is incompatible with the current release
                   24554:      */
                   24555:     function setOsInstallCondition($name, $conflicts = false)
                   24556:     {
                   24557:         $r = &$this->_getCurrentRelease();
                   24558:         if ($r === null) {
                   24559:             return false;
                   24560:         }
                   24561:         $this->_isValid = 0;
                   24562:         if (isset($r['installconditions']['os'])) {
                   24563:             unset($r['installconditions']['os']);
                   24564:         }
                   24565:         $dep = array('name' => $name);
                   24566:         if ($conflicts) {
                   24567:             $dep['conflicts'] = '';
                   24568:         }
                   24569:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24570:             $r = $this->_mergeTag($r, $dep,
                   24571:                 array(
                   24572:                     'installconditions' => array('configureoption', 'binarypackage',
                   24573:                         'filelist'),
                   24574:                     'os' => array('arch')
                   24575:                 ));
                   24576:         } else {
                   24577:             $r = $this->_mergeTag($r, $dep,
                   24578:                 array(
                   24579:                     'installconditions' => array('filelist'),
                   24580:                     'os' => array('arch')
                   24581:                 ));
                   24582:         }
                   24583:     }
                   24584: 
                   24585:     /**
                   24586:      * Set an installation condition based on architecture for the current release set
                   24587:      * @param string architecture pattern
                   24588:      * @param bool whether this arch is incompatible with the current release
                   24589:      */
                   24590:     function setArchInstallCondition($pattern, $conflicts = false)
                   24591:     {
                   24592:         $r = &$this->_getCurrentRelease();
                   24593:         if ($r === null) {
                   24594:             return false;
                   24595:         }
                   24596:         $this->_isValid = 0;
                   24597:         if (isset($r['installconditions']['arch'])) {
                   24598:             unset($r['installconditions']['arch']);
                   24599:         }
                   24600:         $dep = array('pattern' => $pattern);
                   24601:         if ($conflicts) {
                   24602:             $dep['conflicts'] = '';
                   24603:         }
                   24604:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24605:             $r = $this->_mergeTag($r, $dep,
                   24606:                 array(
                   24607:                     'installconditions' => array('configureoption', 'binarypackage',
                   24608:                         'filelist'),
                   24609:                     'arch' => array()
                   24610:                 ));
                   24611:         } else {
                   24612:             $r = $this->_mergeTag($r, $dep,
                   24613:                 array(
                   24614:                     'installconditions' => array('filelist'),
                   24615:                     'arch' => array()
                   24616:                 ));
                   24617:         }
                   24618:     }
                   24619: 
                   24620:     /**
                   24621:      * For extension binary releases, this is used to specify either the
                   24622:      * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
                   24623:      * package it is based on.
                   24624:      * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
                   24625:      */
                   24626:     function setSourcePackage($packageOrUri)
                   24627:     {
                   24628:         $this->_isValid = 0;
                   24629:         if (isset($this->_packageInfo['channel'])) {
                   24630:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                   24631:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   24632:                 'bundle', 'changelog'),
                   24633:                 $packageOrUri, 'srcpackage');
                   24634:         } else {
                   24635:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                   24636:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   24637:                 'bundle', 'changelog'), $packageOrUri, 'srcuri');
                   24638:         }
                   24639:     }
                   24640: 
                   24641:     /**
                   24642:      * Generate a valid change log entry from the current package.xml
                   24643:      * @param string|false
                   24644:      */
                   24645:     function generateChangeLogEntry($notes = false)
                   24646:     {
                   24647:         return array(
                   24648:             'version' =>
                   24649:                 array(
                   24650:                     'release' => $this->getVersion('release'),
                   24651:                     'api' => $this->getVersion('api'),
                   24652:                     ),
                   24653:             'stability' =>
                   24654:                 $this->getStability(),
                   24655:             'date' => $this->getDate(),
                   24656:             'license' => $this->getLicense(true),
                   24657:             'notes' => $notes ? $notes : $this->getNotes()
                   24658:             );
                   24659:     }
                   24660: 
                   24661:     /**
                   24662:      * @param string release version to set change log notes for
                   24663:      * @param array output of {@link generateChangeLogEntry()}
                   24664:      */
                   24665:     function setChangelogEntry($releaseversion, $contents)
                   24666:     {
                   24667:         if (!isset($this->_packageInfo['changelog'])) {
                   24668:             $this->_packageInfo['changelog']['release'] = $contents;
                   24669:             return;
                   24670:         }
                   24671:         if (!isset($this->_packageInfo['changelog']['release'][0])) {
                   24672:             if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
                   24673:                 $this->_packageInfo['changelog']['release'] = array(
                   24674:                     $this->_packageInfo['changelog']['release']);
                   24675:             } else {
                   24676:                 $this->_packageInfo['changelog']['release'] = array(
                   24677:                     $this->_packageInfo['changelog']['release']);
                   24678:                 return $this->_packageInfo['changelog']['release'][] = $contents;
                   24679:             }
                   24680:         }
                   24681:         foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
                   24682:             if (isset($changelog['version']) &&
                   24683:                   strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
                   24684:                 $curlog = $index;
                   24685:             }
                   24686:         }
                   24687:         if (isset($curlog)) {
                   24688:             $this->_packageInfo['changelog']['release'][$curlog] = $contents;
                   24689:         } else {
                   24690:             $this->_packageInfo['changelog']['release'][] = $contents;
                   24691:         }
                   24692:     }
                   24693: 
                   24694:     /**
                   24695:      * Remove the changelog entirely
                   24696:      */
                   24697:     function clearChangeLog()
                   24698:     {
                   24699:         unset($this->_packageInfo['changelog']);
                   24700:     }
                   24701: }PEAR-1.9.4/PEAR/PackageFile/v2/Validator.php0000644000076500000240000025015111605156760017111 0ustar  helgistaff<?php
                   24702: /**
                   24703:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
                   24704:  *
                   24705:  * PHP versions 4 and 5
                   24706:  *
                   24707:  * @category   pear
                   24708:  * @package    PEAR
                   24709:  * @author     Greg Beaver <cellog@php.net>
                   24710:  * @copyright  1997-2009 The Authors
                   24711:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   24712:  * @version    CVS: $Id: Validator.php 313023 2011-07-06 19:17:11Z dufuz $
                   24713:  * @link       http://pear.php.net/package/PEAR
                   24714:  * @since      File available since Release 1.4.0a8
                   24715:  */
                   24716: /**
                   24717:  * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
                   24718:  * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
                   24719:  * @category   pear
                   24720:  * @package    PEAR
                   24721:  * @author     Greg Beaver <cellog@php.net>
                   24722:  * @copyright  1997-2009 The Authors
                   24723:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   24724:  * @version    Release: 1.9.4
                   24725:  * @link       http://pear.php.net/package/PEAR
                   24726:  * @since      Class available since Release 1.4.0a8
                   24727:  * @access private
                   24728:  */
                   24729: class PEAR_PackageFile_v2_Validator
                   24730: {
                   24731:     /**
                   24732:      * @var array
                   24733:      */
                   24734:     var $_packageInfo;
                   24735:     /**
                   24736:      * @var PEAR_PackageFile_v2
                   24737:      */
                   24738:     var $_pf;
                   24739:     /**
                   24740:      * @var PEAR_ErrorStack
                   24741:      */
                   24742:     var $_stack;
                   24743:     /**
                   24744:      * @var int
                   24745:      */
                   24746:     var $_isValid = 0;
                   24747:     /**
                   24748:      * @var int
                   24749:      */
                   24750:     var $_filesValid = 0;
                   24751:     /**
                   24752:      * @var int
                   24753:      */
                   24754:     var $_curState = 0;
                   24755:     /**
                   24756:      * @param PEAR_PackageFile_v2
                   24757:      * @param int
                   24758:      */
                   24759:     function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
                   24760:     {
                   24761:         $this->_pf = &$pf;
                   24762:         $this->_curState = $state;
                   24763:         $this->_packageInfo = $this->_pf->getArray();
                   24764:         $this->_isValid = $this->_pf->_isValid;
                   24765:         $this->_filesValid = $this->_pf->_filesValid;
                   24766:         $this->_stack = &$pf->_stack;
                   24767:         $this->_stack->getErrors(true);
                   24768:         if (($this->_isValid & $state) == $state) {
                   24769:             return true;
                   24770:         }
                   24771:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   24772:             return false;
                   24773:         }
                   24774:         if (!isset($this->_packageInfo['attribs']['version']) ||
                   24775:               ($this->_packageInfo['attribs']['version'] != '2.0' &&
                   24776:                $this->_packageInfo['attribs']['version'] != '2.1')
                   24777:         ) {
                   24778:             $this->_noPackageVersion();
                   24779:         }
                   24780:         $structure =
                   24781:         array(
                   24782:             'name',
                   24783:             'channel|uri',
                   24784:             '*extends', // can't be multiple, but this works fine
                   24785:             'summary',
                   24786:             'description',
                   24787:             '+lead', // these all need content checks
                   24788:             '*developer',
                   24789:             '*contributor',
                   24790:             '*helper',
                   24791:             'date',
                   24792:             '*time',
                   24793:             'version',
                   24794:             'stability',
                   24795:             'license->?uri->?filesource',
                   24796:             'notes',
                   24797:             'contents', //special validation needed
                   24798:             '*compatible',
                   24799:             'dependencies', //special validation needed
                   24800:             '*usesrole',
                   24801:             '*usestask', // reserve these for 1.4.0a1 to implement
                   24802:                          // this will allow a package.xml to gracefully say it
                   24803:                          // needs a certain package installed in order to implement a role or task
                   24804:             '*providesextension',
                   24805:             '*srcpackage|*srcuri',
                   24806:             '+phprelease|+extsrcrelease|+extbinrelease|' .
                   24807:                 '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
                   24808:             '*changelog',
                   24809:         );
                   24810:         $test = $this->_packageInfo;
                   24811:         if (isset($test['dependencies']) &&
                   24812:               isset($test['dependencies']['required']) &&
                   24813:               isset($test['dependencies']['required']['pearinstaller']) &&
                   24814:               isset($test['dependencies']['required']['pearinstaller']['min']) &&
                   24815:               version_compare('1.9.4',
                   24816:                 $test['dependencies']['required']['pearinstaller']['min'], '<')
                   24817:         ) {
                   24818:             $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
                   24819:             return false;
                   24820:         }
                   24821:         // ignore post-installation array fields
                   24822:         if (array_key_exists('filelist', $test)) {
                   24823:             unset($test['filelist']);
                   24824:         }
                   24825:         if (array_key_exists('_lastmodified', $test)) {
                   24826:             unset($test['_lastmodified']);
                   24827:         }
                   24828:         if (array_key_exists('#binarypackage', $test)) {
                   24829:             unset($test['#binarypackage']);
                   24830:         }
                   24831:         if (array_key_exists('old', $test)) {
                   24832:             unset($test['old']);
                   24833:         }
                   24834:         if (array_key_exists('_lastversion', $test)) {
                   24835:             unset($test['_lastversion']);
                   24836:         }
                   24837:         if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
                   24838:             return false;
                   24839:         }
                   24840:         if (empty($this->_packageInfo['name'])) {
                   24841:             $this->_tagCannotBeEmpty('name');
                   24842:         }
                   24843:         $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
                   24844:         if (empty($this->_packageInfo[$test])) {
                   24845:             $this->_tagCannotBeEmpty($test);
                   24846:         }
                   24847:         if (is_array($this->_packageInfo['license']) &&
                   24848:               (!isset($this->_packageInfo['license']['_content']) ||
                   24849:               empty($this->_packageInfo['license']['_content']))) {
                   24850:             $this->_tagCannotBeEmpty('license');
                   24851:         } elseif (empty($this->_packageInfo['license'])) {
                   24852:             $this->_tagCannotBeEmpty('license');
                   24853:         }
                   24854:         if (empty($this->_packageInfo['summary'])) {
                   24855:             $this->_tagCannotBeEmpty('summary');
                   24856:         }
                   24857:         if (empty($this->_packageInfo['description'])) {
                   24858:             $this->_tagCannotBeEmpty('description');
                   24859:         }
                   24860:         if (empty($this->_packageInfo['date'])) {
                   24861:             $this->_tagCannotBeEmpty('date');
                   24862:         }
                   24863:         if (empty($this->_packageInfo['notes'])) {
                   24864:             $this->_tagCannotBeEmpty('notes');
                   24865:         }
                   24866:         if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
                   24867:             $this->_tagCannotBeEmpty('time');
                   24868:         }
                   24869:         if (isset($this->_packageInfo['dependencies'])) {
                   24870:             $this->_validateDependencies();
                   24871:         }
                   24872:         if (isset($this->_packageInfo['compatible'])) {
                   24873:             $this->_validateCompatible();
                   24874:         }
                   24875:         if (!isset($this->_packageInfo['bundle'])) {
                   24876:             if (empty($this->_packageInfo['contents'])) {
                   24877:                 $this->_tagCannotBeEmpty('contents');
                   24878:             }
                   24879:             if (!isset($this->_packageInfo['contents']['dir'])) {
                   24880:                 $this->_filelistMustContainDir('contents');
                   24881:                 return false;
                   24882:             }
                   24883:             if (isset($this->_packageInfo['contents']['file'])) {
                   24884:                 $this->_filelistCannotContainFile('contents');
                   24885:                 return false;
                   24886:             }
                   24887:         }
                   24888:         $this->_validateMaintainers();
                   24889:         $this->_validateStabilityVersion();
                   24890:         $fail = false;
                   24891:         if (array_key_exists('usesrole', $this->_packageInfo)) {
                   24892:             $roles = $this->_packageInfo['usesrole'];
                   24893:             if (!is_array($roles) || !isset($roles[0])) {
                   24894:                 $roles = array($roles);
                   24895:             }
                   24896:             foreach ($roles as $role) {
                   24897:                 if (!isset($role['role'])) {
                   24898:                     $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
                   24899:                     $fail = true;
                   24900:                 } else {
                   24901:                     if (!isset($role['channel'])) {
                   24902:                         if (!isset($role['uri'])) {
                   24903:                             $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
                   24904:                             $fail = true;
                   24905:                         }
                   24906:                     } elseif (!isset($role['package'])) {
                   24907:                         $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
                   24908:                         $fail = true;
                   24909:                     }
                   24910:                 }
                   24911:             }
                   24912:         }
                   24913:         if (array_key_exists('usestask', $this->_packageInfo)) {
                   24914:             $roles = $this->_packageInfo['usestask'];
                   24915:             if (!is_array($roles) || !isset($roles[0])) {
                   24916:                 $roles = array($roles);
                   24917:             }
                   24918:             foreach ($roles as $role) {
                   24919:                 if (!isset($role['task'])) {
                   24920:                     $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
                   24921:                     $fail = true;
                   24922:                 } else {
                   24923:                     if (!isset($role['channel'])) {
                   24924:                         if (!isset($role['uri'])) {
                   24925:                             $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
                   24926:                             $fail = true;
                   24927:                         }
                   24928:                     } elseif (!isset($role['package'])) {
                   24929:                         $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
                   24930:                         $fail = true;
                   24931:                     }
                   24932:                 }
                   24933:             }
                   24934:         }
                   24935: 
                   24936:         if ($fail) {
                   24937:             return false;
                   24938:         }
                   24939: 
                   24940:         $list = $this->_packageInfo['contents'];
                   24941:         if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
                   24942:             $this->_multipleToplevelDirNotAllowed();
                   24943:             return $this->_isValid = 0;
                   24944:         }
                   24945: 
                   24946:         $this->_validateFilelist();
                   24947:         $this->_validateRelease();
                   24948:         if (!$this->_stack->hasErrors()) {
                   24949:             $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
                   24950:             if (PEAR::isError($chan)) {
                   24951:                 $this->_unknownChannel($this->_pf->getChannel());
                   24952:             } else {
                   24953:                 $valpack = $chan->getValidationPackage();
                   24954:                 // for channel validator packages, always use the default PEAR validator.
                   24955:                 // otherwise, they can't be installed or packaged
                   24956:                 $validator = $chan->getValidationObject($this->_pf->getPackage());
                   24957:                 if (!$validator) {
                   24958:                     $this->_stack->push(__FUNCTION__, 'error',
                   24959:                         array('channel' => $chan->getName(),
                   24960:                               'package' => $this->_pf->getPackage(),
                   24961:                               'name'    => $valpack['_content'],
                   24962:                               'version' => $valpack['attribs']['version']),
                   24963:                         'package "%channel%/%package%" cannot be properly validated without ' .
                   24964:                         'validation package "%channel%/%name%-%version%"');
                   24965:                     return $this->_isValid = 0;
                   24966:                 }
                   24967:                 $validator->setPackageFile($this->_pf);
                   24968:                 $validator->validate($state);
                   24969:                 $failures = $validator->getFailures();
                   24970:                 foreach ($failures['errors'] as $error) {
                   24971:                     $this->_stack->push(__FUNCTION__, 'error', $error,
                   24972:                         'Channel validator error: field "%field%" - %reason%');
                   24973:                 }
                   24974:                 foreach ($failures['warnings'] as $warning) {
                   24975:                     $this->_stack->push(__FUNCTION__, 'warning', $warning,
                   24976:                         'Channel validator warning: field "%field%" - %reason%');
                   24977:                 }
                   24978:             }
                   24979:         }
                   24980: 
                   24981:         $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
                   24982:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
                   24983:             if ($this->_pf->getPackageType() == 'bundle') {
                   24984:                 if ($this->_analyzeBundledPackages()) {
                   24985:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   24986:                 } else {
                   24987:                     $this->_pf->_isValid = $this->_isValid = 0;
                   24988:                 }
                   24989:             } else {
                   24990:                 if (!$this->_analyzePhpFiles()) {
                   24991:                     $this->_pf->_isValid = $this->_isValid = 0;
                   24992:                 } else {
                   24993:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   24994:                 }
                   24995:             }
                   24996:         }
                   24997: 
                   24998:         if ($this->_isValid) {
                   24999:             return $this->_pf->_isValid = $this->_isValid = $state;
                   25000:         }
                   25001: 
                   25002:         return $this->_pf->_isValid = $this->_isValid = 0;
                   25003:     }
                   25004: 
                   25005:     function _stupidSchemaValidate($structure, $xml, $root)
                   25006:     {
                   25007:         if (!is_array($xml)) {
                   25008:             $xml = array();
                   25009:         }
                   25010:         $keys = array_keys($xml);
                   25011:         reset($keys);
                   25012:         $key = current($keys);
                   25013:         while ($key == 'attribs' || $key == '_contents') {
                   25014:             $key = next($keys);
                   25015:         }
                   25016:         $unfoundtags = $optionaltags = array();
                   25017:         $ret = true;
                   25018:         $mismatch = false;
                   25019:         foreach ($structure as $struc) {
                   25020:             if ($key) {
                   25021:                 $tag = $xml[$key];
                   25022:             }
                   25023:             $test = $this->_processStructure($struc);
                   25024:             if (isset($test['choices'])) {
                   25025:                 $loose = true;
                   25026:                 foreach ($test['choices'] as $choice) {
                   25027:                     if ($key == $choice['tag']) {
                   25028:                         $key = next($keys);
                   25029:                         while ($key == 'attribs' || $key == '_contents') {
                   25030:                             $key = next($keys);
                   25031:                         }
                   25032:                         $unfoundtags = $optionaltags = array();
                   25033:                         $mismatch = false;
                   25034:                         if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
                   25035:                             $unfoundtags[] = $choice['tag'];
                   25036:                             $optionaltags[] = $choice['tag'];
                   25037:                             if ($key) {
                   25038:                                 $mismatch = true;
                   25039:                             }
                   25040:                         }
                   25041:                         $ret &= $this->_processAttribs($choice, $tag, $root);
                   25042:                         continue 2;
                   25043:                     } else {
                   25044:                         $unfoundtags[] = $choice['tag'];
                   25045:                         $mismatch = true;
                   25046:                     }
                   25047:                     if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
                   25048:                         $loose = false;
                   25049:                     } else {
                   25050:                         $optionaltags[] = $choice['tag'];
                   25051:                     }
                   25052:                 }
                   25053:                 if (!$loose) {
                   25054:                     $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25055:                     return false;
                   25056:                 }
                   25057:             } else {
                   25058:                 if ($key != $test['tag']) {
                   25059:                     if (isset($test['multiple']) && $test['multiple'] != '*') {
                   25060:                         $unfoundtags[] = $test['tag'];
                   25061:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25062:                         return false;
                   25063:                     } else {
                   25064:                         if ($key) {
                   25065:                             $mismatch = true;
                   25066:                         }
                   25067:                         $unfoundtags[] = $test['tag'];
                   25068:                         $optionaltags[] = $test['tag'];
                   25069:                     }
                   25070:                     if (!isset($test['multiple'])) {
                   25071:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25072:                         return false;
                   25073:                     }
                   25074:                     continue;
                   25075:                 } else {
                   25076:                     $unfoundtags = $optionaltags = array();
                   25077:                     $mismatch = false;
                   25078:                 }
                   25079:                 $key = next($keys);
                   25080:                 while ($key == 'attribs' || $key == '_contents') {
                   25081:                     $key = next($keys);
                   25082:                 }
                   25083:                 if ($key && $key != $test['tag'] && isset($test['multiple'])) {
                   25084:                     $unfoundtags[] = $test['tag'];
                   25085:                     $optionaltags[] = $test['tag'];
                   25086:                     $mismatch = true;
                   25087:                 }
                   25088:                 $ret &= $this->_processAttribs($test, $tag, $root);
                   25089:                 continue;
                   25090:             }
                   25091:         }
                   25092:         if (!$mismatch && count($optionaltags)) {
                   25093:             // don't error out on any optional tags
                   25094:             $unfoundtags = array_diff($unfoundtags, $optionaltags);
                   25095:         }
                   25096:         if (count($unfoundtags)) {
                   25097:             $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25098:         } elseif ($key) {
                   25099:             // unknown tags
                   25100:             $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   25101:             while ($key = next($keys)) {
                   25102:                 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   25103:             }
                   25104:         }
                   25105:         return $ret;
                   25106:     }
                   25107: 
                   25108:     function _processAttribs($choice, $tag, $context)
                   25109:     {
                   25110:         if (isset($choice['attribs'])) {
                   25111:             if (!is_array($tag)) {
                   25112:                 $tag = array($tag);
                   25113:             }
                   25114:             $tags = $tag;
                   25115:             if (!isset($tags[0])) {
                   25116:                 $tags = array($tags);
                   25117:             }
                   25118:             $ret = true;
                   25119:             foreach ($tags as $i => $tag) {
                   25120:                 if (!is_array($tag) || !isset($tag['attribs'])) {
                   25121:                     foreach ($choice['attribs'] as $attrib) {
                   25122:                         if ($attrib{0} != '?') {
                   25123:                             $ret &= $this->_tagHasNoAttribs($choice['tag'],
                   25124:                                 $context);
                   25125:                             continue 2;
                   25126:                         }
                   25127:                     }
                   25128:                 }
                   25129:                 foreach ($choice['attribs'] as $attrib) {
                   25130:                     if ($attrib{0} != '?') {
                   25131:                         if (!isset($tag['attribs'][$attrib])) {
                   25132:                             $ret &= $this->_tagMissingAttribute($choice['tag'],
                   25133:                                 $attrib, $context);
                   25134:                         }
                   25135:                     }
                   25136:                 }
                   25137:             }
                   25138:             return $ret;
                   25139:         }
                   25140:         return true;
                   25141:     }
                   25142: 
                   25143:     function _processStructure($key)
                   25144:     {
                   25145:         $ret = array();
                   25146:         if (count($pieces = explode('|', $key)) > 1) {
                   25147:             $ret['choices'] = array();
                   25148:             foreach ($pieces as $piece) {
                   25149:                 $ret['choices'][] = $this->_processStructure($piece);
                   25150:             }
                   25151:             return $ret;
                   25152:         }
                   25153:         $multi = $key{0};
                   25154:         if ($multi == '+' || $multi == '*') {
                   25155:             $ret['multiple'] = $key{0};
                   25156:             $key = substr($key, 1);
                   25157:         }
                   25158:         if (count($attrs = explode('->', $key)) > 1) {
                   25159:             $ret['tag'] = array_shift($attrs);
                   25160:             $ret['attribs'] = $attrs;
                   25161:         } else {
                   25162:             $ret['tag'] = $key;
                   25163:         }
                   25164:         return $ret;
                   25165:     }
                   25166: 
                   25167:     function _validateStabilityVersion()
                   25168:     {
                   25169:         $structure = array('release', 'api');
                   25170:         $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
                   25171:         $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
                   25172:         if ($a) {
                   25173:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25174:                   $this->_packageInfo['version']['release'])) {
                   25175:                 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
                   25176:             }
                   25177:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25178:                   $this->_packageInfo['version']['api'])) {
                   25179:                 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
                   25180:             }
                   25181:             if (!in_array($this->_packageInfo['stability']['release'],
                   25182:                   array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
                   25183:                 $this->_invalidState('release', $this->_packageInfo['stability']['release']);
                   25184:             }
                   25185:             if (!in_array($this->_packageInfo['stability']['api'],
                   25186:                   array('devel', 'alpha', 'beta', 'stable'))) {
                   25187:                 $this->_invalidState('api', $this->_packageInfo['stability']['api']);
                   25188:             }
                   25189:         }
                   25190:     }
                   25191: 
                   25192:     function _validateMaintainers()
                   25193:     {
                   25194:         $structure =
                   25195:             array(
                   25196:                 'name',
                   25197:                 'user',
                   25198:                 'email',
                   25199:                 'active',
                   25200:             );
                   25201:         foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
                   25202:             if (!isset($this->_packageInfo[$type])) {
                   25203:                 continue;
                   25204:             }
                   25205:             if (isset($this->_packageInfo[$type][0])) {
                   25206:                 foreach ($this->_packageInfo[$type] as $lead) {
                   25207:                     $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
                   25208:                 }
                   25209:             } else {
                   25210:                 $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
                   25211:                     '<' . $type . '>');
                   25212:             }
                   25213:         }
                   25214:     }
                   25215: 
                   25216:     function _validatePhpDep($dep, $installcondition = false)
                   25217:     {
                   25218:         $structure = array(
                   25219:             'min',
                   25220:             '*max',
                   25221:             '*exclude',
                   25222:         );
                   25223:         $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
                   25224:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25225:         if (isset($dep['min'])) {
                   25226:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25227:                   $dep['min'])) {
                   25228:                 $this->_invalidVersion($type . '<min>', $dep['min']);
                   25229:             }
                   25230:         }
                   25231:         if (isset($dep['max'])) {
                   25232:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25233:                   $dep['max'])) {
                   25234:                 $this->_invalidVersion($type . '<max>', $dep['max']);
                   25235:             }
                   25236:         }
                   25237:         if (isset($dep['exclude'])) {
                   25238:             if (!is_array($dep['exclude'])) {
                   25239:                 $dep['exclude'] = array($dep['exclude']);
                   25240:             }
                   25241:             foreach ($dep['exclude'] as $exclude) {
                   25242:                 if (!preg_match(
                   25243:                      '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25244:                      $exclude)) {
                   25245:                     $this->_invalidVersion($type . '<exclude>', $exclude);
                   25246:                 }
                   25247:             }
                   25248:         }
                   25249:     }
                   25250: 
                   25251:     function _validatePearinstallerDep($dep)
                   25252:     {
                   25253:         $structure = array(
                   25254:             'min',
                   25255:             '*max',
                   25256:             '*recommended',
                   25257:             '*exclude',
                   25258:         );
                   25259:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
                   25260:         if (isset($dep['min'])) {
                   25261:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25262:                   $dep['min'])) {
                   25263:                 $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
                   25264:                     $dep['min']);
                   25265:             }
                   25266:         }
                   25267:         if (isset($dep['max'])) {
                   25268:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25269:                   $dep['max'])) {
                   25270:                 $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
                   25271:                     $dep['max']);
                   25272:             }
                   25273:         }
                   25274:         if (isset($dep['recommended'])) {
                   25275:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25276:                   $dep['recommended'])) {
                   25277:                 $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
                   25278:                     $dep['recommended']);
                   25279:             }
                   25280:         }
                   25281:         if (isset($dep['exclude'])) {
                   25282:             if (!is_array($dep['exclude'])) {
                   25283:                 $dep['exclude'] = array($dep['exclude']);
                   25284:             }
                   25285:             foreach ($dep['exclude'] as $exclude) {
                   25286:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25287:                       $exclude)) {
                   25288:                     $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
                   25289:                         $exclude);
                   25290:                 }
                   25291:             }
                   25292:         }
                   25293:     }
                   25294: 
                   25295:     function _validatePackageDep($dep, $group, $type = '<package>')
                   25296:     {
                   25297:         if (isset($dep['uri'])) {
                   25298:             if (isset($dep['conflicts'])) {
                   25299:                 $structure = array(
                   25300:                     'name',
                   25301:                     'uri',
                   25302:                     'conflicts',
                   25303:                     '*providesextension',
                   25304:                 );
                   25305:             } else {
                   25306:                 $structure = array(
                   25307:                     'name',
                   25308:                     'uri',
                   25309:                     '*providesextension',
                   25310:                 );
                   25311:             }
                   25312:         } else {
                   25313:             if (isset($dep['conflicts'])) {
                   25314:                 $structure = array(
                   25315:                     'name',
                   25316:                     'channel',
                   25317:                     '*min',
                   25318:                     '*max',
                   25319:                     '*exclude',
                   25320:                     'conflicts',
                   25321:                     '*providesextension',
                   25322:                 );
                   25323:             } else {
                   25324:                 $structure = array(
                   25325:                     'name',
                   25326:                     'channel',
                   25327:                     '*min',
                   25328:                     '*max',
                   25329:                     '*recommended',
                   25330:                     '*exclude',
                   25331:                     '*nodefault',
                   25332:                     '*providesextension',
                   25333:                 );
                   25334:             }
                   25335:         }
                   25336:         if (isset($dep['name'])) {
                   25337:             $type .= '<name>' . $dep['name'] . '</name>';
                   25338:         }
                   25339:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
                   25340:         if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
                   25341:               isset($dep['recommended']) || isset($dep['exclude']))) {
                   25342:             $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
                   25343:         }
                   25344:         if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
                   25345:             $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
                   25346:         }
                   25347:         if (isset($dep['min'])) {
                   25348:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25349:                   $dep['min'])) {
                   25350:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
                   25351:             }
                   25352:         }
                   25353:         if (isset($dep['max'])) {
                   25354:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25355:                   $dep['max'])) {
                   25356:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
                   25357:             }
                   25358:         }
                   25359:         if (isset($dep['recommended'])) {
                   25360:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25361:                   $dep['recommended'])) {
                   25362:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
                   25363:                     $dep['recommended']);
                   25364:             }
                   25365:         }
                   25366:         if (isset($dep['exclude'])) {
                   25367:             if (!is_array($dep['exclude'])) {
                   25368:                 $dep['exclude'] = array($dep['exclude']);
                   25369:             }
                   25370:             foreach ($dep['exclude'] as $exclude) {
                   25371:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25372:                       $exclude)) {
                   25373:                     $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
                   25374:                         $exclude);
                   25375:                 }
                   25376:             }
                   25377:         }
                   25378:     }
                   25379: 
                   25380:     function _validateSubpackageDep($dep, $group)
                   25381:     {
                   25382:         $this->_validatePackageDep($dep, $group, '<subpackage>');
                   25383:         if (isset($dep['providesextension'])) {
                   25384:             $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
                   25385:         }
                   25386:         if (isset($dep['conflicts'])) {
                   25387:             $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
                   25388:         }
                   25389:     }
                   25390: 
                   25391:     function _validateExtensionDep($dep, $group = false, $installcondition = false)
                   25392:     {
                   25393:         if (isset($dep['conflicts'])) {
                   25394:             $structure = array(
                   25395:                 'name',
                   25396:                 '*min',
                   25397:                 '*max',
                   25398:                 '*exclude',
                   25399:                 'conflicts',
                   25400:             );
                   25401:         } else {
                   25402:             $structure = array(
                   25403:                 'name',
                   25404:                 '*min',
                   25405:                 '*max',
                   25406:                 '*recommended',
                   25407:                 '*exclude',
                   25408:             );
                   25409:         }
                   25410:         if ($installcondition) {
                   25411:             $type = '<installcondition><extension>';
                   25412:         } else {
                   25413:             $type = '<dependencies>' . $group . '<extension>';
                   25414:         }
                   25415:         if (isset($dep['name'])) {
                   25416:             $type .= '<name>' . $dep['name'] . '</name>';
                   25417:         }
                   25418:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25419:         if (isset($dep['min'])) {
                   25420:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25421:                   $dep['min'])) {
                   25422:                 $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
                   25423:             }
                   25424:         }
                   25425:         if (isset($dep['max'])) {
                   25426:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25427:                   $dep['max'])) {
                   25428:                 $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
                   25429:             }
                   25430:         }
                   25431:         if (isset($dep['recommended'])) {
                   25432:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25433:                   $dep['recommended'])) {
                   25434:                 $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
                   25435:             }
                   25436:         }
                   25437:         if (isset($dep['exclude'])) {
                   25438:             if (!is_array($dep['exclude'])) {
                   25439:                 $dep['exclude'] = array($dep['exclude']);
                   25440:             }
                   25441:             foreach ($dep['exclude'] as $exclude) {
                   25442:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25443:                       $exclude)) {
                   25444:                     $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   25445:                 }
                   25446:             }
                   25447:         }
                   25448:     }
                   25449: 
                   25450:     function _validateOsDep($dep, $installcondition = false)
                   25451:     {
                   25452:         $structure = array(
                   25453:             'name',
                   25454:             '*conflicts',
                   25455:         );
                   25456:         $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
                   25457:         if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
                   25458:             if ($dep['name'] == '*') {
                   25459:                 if (array_key_exists('conflicts', $dep)) {
                   25460:                     $this->_cannotConflictWithAllOs($type);
                   25461:                 }
                   25462:             }
                   25463:         }
                   25464:     }
                   25465: 
                   25466:     function _validateArchDep($dep, $installcondition = false)
                   25467:     {
                   25468:         $structure = array(
                   25469:             'pattern',
                   25470:             '*conflicts',
                   25471:         );
                   25472:         $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
                   25473:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25474:     }
                   25475: 
                   25476:     function _validateInstallConditions($cond, $release)
                   25477:     {
                   25478:         $structure = array(
                   25479:             '*php',
                   25480:             '*extension',
                   25481:             '*os',
                   25482:             '*arch',
                   25483:         );
                   25484:         if (!$this->_stupidSchemaValidate($structure,
                   25485:               $cond, $release)) {
                   25486:             return false;
                   25487:         }
                   25488:         foreach (array('php', 'extension', 'os', 'arch') as $type) {
                   25489:             if (isset($cond[$type])) {
                   25490:                 $iter = $cond[$type];
                   25491:                 if (!is_array($iter) || !isset($iter[0])) {
                   25492:                     $iter = array($iter);
                   25493:                 }
                   25494:                 foreach ($iter as $package) {
                   25495:                     if ($type == 'extension') {
                   25496:                         $this->{"_validate{$type}Dep"}($package, false, true);
                   25497:                     } else {
                   25498:                         $this->{"_validate{$type}Dep"}($package, true);
                   25499:                     }
                   25500:                 }
                   25501:             }
                   25502:         }
                   25503:     }
                   25504: 
                   25505:     function _validateDependencies()
                   25506:     {
                   25507:         $structure = array(
                   25508:             'required',
                   25509:             '*optional',
                   25510:             '*group->name->hint'
                   25511:         );
                   25512:         if (!$this->_stupidSchemaValidate($structure,
                   25513:               $this->_packageInfo['dependencies'], '<dependencies>')) {
                   25514:             return false;
                   25515:         }
                   25516:         foreach (array('required', 'optional') as $simpledep) {
                   25517:             if (isset($this->_packageInfo['dependencies'][$simpledep])) {
                   25518:                 if ($simpledep == 'optional') {
                   25519:                     $structure = array(
                   25520:                         '*package',
                   25521:                         '*subpackage',
                   25522:                         '*extension',
                   25523:                     );
                   25524:                 } else {
                   25525:                     $structure = array(
                   25526:                         'php',
                   25527:                         'pearinstaller',
                   25528:                         '*package',
                   25529:                         '*subpackage',
                   25530:                         '*extension',
                   25531:                         '*os',
                   25532:                         '*arch',
                   25533:                     );
                   25534:                 }
                   25535:                 if ($this->_stupidSchemaValidate($structure,
                   25536:                       $this->_packageInfo['dependencies'][$simpledep],
                   25537:                       "<dependencies><$simpledep>")) {
                   25538:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   25539:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   25540:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   25541:                             if (!isset($iter[0])) {
                   25542:                                 $iter = array($iter);
                   25543:                             }
                   25544:                             foreach ($iter as $package) {
                   25545:                                 if ($type != 'extension') {
                   25546:                                     if (isset($package['uri'])) {
                   25547:                                         if (isset($package['channel'])) {
                   25548:                                             $this->_UrlOrChannel($type,
                   25549:                                                 $package['name']);
                   25550:                                         }
                   25551:                                     } else {
                   25552:                                         if (!isset($package['channel'])) {
                   25553:                                             $this->_NoChannel($type, $package['name']);
                   25554:                                         }
                   25555:                                     }
                   25556:                                 }
                   25557:                                 $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
                   25558:                             }
                   25559:                         }
                   25560:                     }
                   25561:                     if ($simpledep == 'optional') {
                   25562:                         continue;
                   25563:                     }
                   25564:                     foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
                   25565:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   25566:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   25567:                             if (!isset($iter[0])) {
                   25568:                                 $iter = array($iter);
                   25569:                             }
                   25570:                             foreach ($iter as $package) {
                   25571:                                 $this->{"_validate{$type}Dep"}($package);
                   25572:                             }
                   25573:                         }
                   25574:                     }
                   25575:                 }
                   25576:             }
                   25577:         }
                   25578:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   25579:             $groups = $this->_packageInfo['dependencies']['group'];
                   25580:             if (!isset($groups[0])) {
                   25581:                 $groups = array($groups);
                   25582:             }
                   25583:             $structure = array(
                   25584:                 '*package',
                   25585:                 '*subpackage',
                   25586:                 '*extension',
                   25587:             );
                   25588:             foreach ($groups as $group) {
                   25589:                 if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
                   25590:                     if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
                   25591:                         $this->_invalidDepGroupName($group['attribs']['name']);
                   25592:                     }
                   25593:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   25594:                         if (isset($group[$type])) {
                   25595:                             $iter = $group[$type];
                   25596:                             if (!isset($iter[0])) {
                   25597:                                 $iter = array($iter);
                   25598:                             }
                   25599:                             foreach ($iter as $package) {
                   25600:                                 if ($type != 'extension') {
                   25601:                                     if (isset($package['uri'])) {
                   25602:                                         if (isset($package['channel'])) {
                   25603:                                             $this->_UrlOrChannelGroup($type,
                   25604:                                                 $package['name'],
                   25605:                                                 $group['name']);
                   25606:                                         }
                   25607:                                     } else {
                   25608:                                         if (!isset($package['channel'])) {
                   25609:                                             $this->_NoChannelGroup($type,
                   25610:                                                 $package['name'],
                   25611:                                                 $group['name']);
                   25612:                                         }
                   25613:                                     }
                   25614:                                 }
                   25615:                                 $this->{"_validate{$type}Dep"}($package, '<group name="' .
                   25616:                                     $group['attribs']['name'] . '">');
                   25617:                             }
                   25618:                         }
                   25619:                     }
                   25620:                 }
                   25621:             }
                   25622:         }
                   25623:     }
                   25624: 
                   25625:     function _validateCompatible()
                   25626:     {
                   25627:         $compat = $this->_packageInfo['compatible'];
                   25628:         if (!isset($compat[0])) {
                   25629:             $compat = array($compat);
                   25630:         }
                   25631:         $required = array('name', 'channel', 'min', 'max', '*exclude');
                   25632:         foreach ($compat as $package) {
                   25633:             $type = '<compatible>';
                   25634:             if (is_array($package) && array_key_exists('name', $package)) {
                   25635:                 $type .= '<name>' . $package['name'] . '</name>';
                   25636:             }
                   25637:             $this->_stupidSchemaValidate($required, $package, $type);
                   25638:             if (is_array($package) && array_key_exists('min', $package)) {
                   25639:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25640:                       $package['min'])) {
                   25641:                     $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
                   25642:                 }
                   25643:             }
                   25644:             if (is_array($package) && array_key_exists('max', $package)) {
                   25645:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25646:                       $package['max'])) {
                   25647:                     $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
                   25648:                 }
                   25649:             }
                   25650:             if (is_array($package) && array_key_exists('exclude', $package)) {
                   25651:                 if (!is_array($package['exclude'])) {
                   25652:                     $package['exclude'] = array($package['exclude']);
                   25653:                 }
                   25654:                 foreach ($package['exclude'] as $exclude) {
                   25655:                     if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25656:                           $exclude)) {
                   25657:                         $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   25658:                     }
                   25659:                 }
                   25660:             }
                   25661:         }
                   25662:     }
                   25663: 
                   25664:     function _validateBundle($list)
                   25665:     {
                   25666:         if (!is_array($list) || !isset($list['bundledpackage'])) {
                   25667:             return $this->_NoBundledPackages();
                   25668:         }
                   25669:         if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
                   25670:             return $this->_AtLeast2BundledPackages();
                   25671:         }
                   25672:         foreach ($list['bundledpackage'] as $package) {
                   25673:             if (!is_string($package)) {
                   25674:                 $this->_bundledPackagesMustBeFilename();
                   25675:             }
                   25676:         }
                   25677:     }
                   25678: 
                   25679:     function _validateFilelist($list = false, $allowignore = false, $dirs = '')
                   25680:     {
                   25681:         $iscontents = false;
                   25682:         if (!$list) {
                   25683:             $iscontents = true;
                   25684:             $list = $this->_packageInfo['contents'];
                   25685:             if (isset($this->_packageInfo['bundle'])) {
                   25686:                 return $this->_validateBundle($list);
                   25687:             }
                   25688:         }
                   25689:         if ($allowignore) {
                   25690:             $struc = array(
                   25691:                 '*install->name->as',
                   25692:                 '*ignore->name'
                   25693:             );
                   25694:         } else {
                   25695:             $struc = array(
                   25696:                 '*dir->name->?baseinstalldir',
                   25697:                 '*file->name->role->?baseinstalldir->?md5sum'
                   25698:             );
                   25699:             if (isset($list['dir']) && isset($list['file'])) {
                   25700:                 // stave off validation errors without requiring a set order.
                   25701:                 $_old = $list;
                   25702:                 if (isset($list['attribs'])) {
                   25703:                     $list = array('attribs' => $_old['attribs']);
                   25704:                 }
                   25705:                 $list['dir'] = $_old['dir'];
                   25706:                 $list['file'] = $_old['file'];
                   25707:             }
                   25708:         }
                   25709:         if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
                   25710:             $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
                   25711:             $dirname = $iscontents ? '<contents>' : $unknown;
                   25712:         } else {
                   25713:             $dirname = '<dir name="' . $list['attribs']['name'] . '">';
                   25714:             if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   25715:                           str_replace('\\', '/', $list['attribs']['name']))) {
                   25716:                 // file contains .. parent directory or . cur directory
                   25717:                 $this->_invalidDirName($list['attribs']['name']);
                   25718:             }
                   25719:         }
                   25720:         $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
                   25721:         if ($allowignore && $res) {
                   25722:             $ignored_or_installed = array();
                   25723:             $this->_pf->getFilelist();
                   25724:             $fcontents = $this->_pf->getContents();
                   25725:             $filelist = array();
                   25726:             if (!isset($fcontents['dir']['file'][0])) {
                   25727:                 $fcontents['dir']['file'] = array($fcontents['dir']['file']);
                   25728:             }
                   25729:             foreach ($fcontents['dir']['file'] as $file) {
                   25730:                 $filelist[$file['attribs']['name']] = true;
                   25731:             }
                   25732:             if (isset($list['install'])) {
                   25733:                 if (!isset($list['install'][0])) {
                   25734:                     $list['install'] = array($list['install']);
                   25735:                 }
                   25736:                 foreach ($list['install'] as $file) {
                   25737:                     if (!isset($filelist[$file['attribs']['name']])) {
                   25738:                         $this->_notInContents($file['attribs']['name'], 'install');
                   25739:                         continue;
                   25740:                     }
                   25741:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   25742:                         $this->_multipleInstallAs($file['attribs']['name']);
                   25743:                     }
                   25744:                     if (!isset($ignored_or_installed[$file['attribs']['name']])) {
                   25745:                         $ignored_or_installed[$file['attribs']['name']] = array();
                   25746:                     }
                   25747:                     $ignored_or_installed[$file['attribs']['name']][] = 1;
                   25748:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   25749:                                   str_replace('\\', '/', $file['attribs']['as']))) {
                   25750:                         // file contains .. parent directory or . cur directory references
                   25751:                         $this->_invalidFileInstallAs($file['attribs']['name'],
                   25752:                             $file['attribs']['as']);
                   25753:                     }
                   25754:                 }
                   25755:             }
                   25756:             if (isset($list['ignore'])) {
                   25757:                 if (!isset($list['ignore'][0])) {
                   25758:                     $list['ignore'] = array($list['ignore']);
                   25759:                 }
                   25760:                 foreach ($list['ignore'] as $file) {
                   25761:                     if (!isset($filelist[$file['attribs']['name']])) {
                   25762:                         $this->_notInContents($file['attribs']['name'], 'ignore');
                   25763:                         continue;
                   25764:                     }
                   25765:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   25766:                         $this->_ignoreAndInstallAs($file['attribs']['name']);
                   25767:                     }
                   25768:                 }
                   25769:             }
                   25770:         }
                   25771:         if (!$allowignore && isset($list['file'])) {
                   25772:             if (is_string($list['file'])) {
                   25773:                 $this->_oldStyleFileNotAllowed();
                   25774:                 return false;
                   25775:             }
                   25776:             if (!isset($list['file'][0])) {
                   25777:                 // single file
                   25778:                 $list['file'] = array($list['file']);
                   25779:             }
                   25780:             foreach ($list['file'] as $i => $file)
                   25781:             {
                   25782:                 if (isset($file['attribs']) && isset($file['attribs']['name'])) {
                   25783:                     if ($file['attribs']['name']{0} == '.' &&
                   25784:                           $file['attribs']['name']{1} == '/') {
                   25785:                         // name is something like "./doc/whatever.txt"
                   25786:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   25787:                     }
                   25788:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   25789:                                   str_replace('\\', '/', $file['attribs']['name']))) {
                   25790:                         // file contains .. parent directory or . cur directory
                   25791:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   25792:                     }
                   25793:                 }
                   25794:                 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
                   25795:                     if (!$this->_validateRole($file['attribs']['role'])) {
                   25796:                         if (isset($this->_packageInfo['usesrole'])) {
                   25797:                             $roles = $this->_packageInfo['usesrole'];
                   25798:                             if (!isset($roles[0])) {
                   25799:                                 $roles = array($roles);
                   25800:                             }
                   25801:                             foreach ($roles as $role) {
                   25802:                                 if ($role['role'] = $file['attribs']['role']) {
                   25803:                                     $msg = 'This package contains role "%role%" and requires ' .
                   25804:                                         'package "%package%" to be used';
                   25805:                                     if (isset($role['uri'])) {
                   25806:                                         $params = array('role' => $role['role'],
                   25807:                                             'package' => $role['uri']);
                   25808:                                     } else {
                   25809:                                         $params = array('role' => $role['role'],
                   25810:                                             'package' => $this->_pf->_registry->
                   25811:                                             parsedPackageNameToString(array('package' =>
                   25812:                                                 $role['package'], 'channel' => $role['channel']),
                   25813:                                                 true));
                   25814:                                     }
                   25815:                                     $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
                   25816:                                 }
                   25817:                             }
                   25818:                         }
                   25819:                         $this->_invalidFileRole($file['attribs']['name'],
                   25820:                             $dirname, $file['attribs']['role']);
                   25821:                     }
                   25822:                 }
                   25823:                 if (!isset($file['attribs'])) {
                   25824:                     continue;
                   25825:                 }
                   25826:                 $save = $file['attribs'];
                   25827:                 if ($dirs) {
                   25828:                     $save['name'] = $dirs . '/' . $save['name'];
                   25829:                 }
                   25830:                 unset($file['attribs']);
                   25831:                 if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
                   25832:                     foreach ($file as $task => $value) {
                   25833:                         if ($tagClass = $this->_pf->getTask($task)) {
                   25834:                             if (!is_array($value) || !isset($value[0])) {
                   25835:                                 $value = array($value);
                   25836:                             }
                   25837:                             foreach ($value as $v) {
                   25838:                                 $ret = call_user_func(array($tagClass, 'validateXml'),
                   25839:                                     $this->_pf, $v, $this->_pf->_config, $save);
                   25840:                                 if (is_array($ret)) {
                   25841:                                     $this->_invalidTask($task, $ret, isset($save['name']) ?
                   25842:                                         $save['name'] : '');
                   25843:                                 }
                   25844:                             }
                   25845:                         } else {
                   25846:                             if (isset($this->_packageInfo['usestask'])) {
                   25847:                                 $roles = $this->_packageInfo['usestask'];
                   25848:                                 if (!isset($roles[0])) {
                   25849:                                     $roles = array($roles);
                   25850:                                 }
                   25851:                                 foreach ($roles as $role) {
                   25852:                                     if ($role['task'] = $task) {
                   25853:                                         $msg = 'This package contains task "%task%" and requires ' .
                   25854:                                             'package "%package%" to be used';
                   25855:                                         if (isset($role['uri'])) {
                   25856:                                             $params = array('task' => $role['task'],
                   25857:                                                 'package' => $role['uri']);
                   25858:                                         } else {
                   25859:                                             $params = array('task' => $role['task'],
                   25860:                                                 'package' => $this->_pf->_registry->
                   25861:                                                 parsedPackageNameToString(array('package' =>
                   25862:                                                     $role['package'], 'channel' => $role['channel']),
                   25863:                                                     true));
                   25864:                                         }
                   25865:                                         $this->_stack->push('_mustInstallTask', 'error',
                   25866:                                             $params, $msg);
                   25867:                                     }
                   25868:                                 }
                   25869:                             }
                   25870:                             $this->_unknownTask($task, $save['name']);
                   25871:                         }
                   25872:                     }
                   25873:                 }
                   25874:             }
                   25875:         }
                   25876:         if (isset($list['ignore'])) {
                   25877:             if (!$allowignore) {
                   25878:                 $this->_ignoreNotAllowed('ignore');
                   25879:             }
                   25880:         }
                   25881:         if (isset($list['install'])) {
                   25882:             if (!$allowignore) {
                   25883:                 $this->_ignoreNotAllowed('install');
                   25884:             }
                   25885:         }
                   25886:         if (isset($list['file'])) {
                   25887:             if ($allowignore) {
                   25888:                 $this->_fileNotAllowed('file');
                   25889:             }
                   25890:         }
                   25891:         if (isset($list['dir'])) {
                   25892:             if ($allowignore) {
                   25893:                 $this->_fileNotAllowed('dir');
                   25894:             } else {
                   25895:                 if (!isset($list['dir'][0])) {
                   25896:                     $list['dir'] = array($list['dir']);
                   25897:                 }
                   25898:                 foreach ($list['dir'] as $dir) {
                   25899:                     if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
                   25900:                         if ($dir['attribs']['name'] == '/' ||
                   25901:                               !isset($this->_packageInfo['contents']['dir']['dir'])) {
                   25902:                             // always use nothing if the filelist has already been flattened
                   25903:                             $newdirs = '';
                   25904:                         } elseif ($dirs == '') {
                   25905:                             $newdirs = $dir['attribs']['name'];
                   25906:                         } else {
                   25907:                             $newdirs = $dirs . '/' . $dir['attribs']['name'];
                   25908:                         }
                   25909:                     } else {
                   25910:                         $newdirs = $dirs;
                   25911:                     }
                   25912:                     $this->_validateFilelist($dir, $allowignore, $newdirs);
                   25913:                 }
                   25914:             }
                   25915:         }
                   25916:     }
                   25917: 
                   25918:     function _validateRelease()
                   25919:     {
                   25920:         if (isset($this->_packageInfo['phprelease'])) {
                   25921:             $release = 'phprelease';
                   25922:             if (isset($this->_packageInfo['providesextension'])) {
                   25923:                 $this->_cannotProvideExtension($release);
                   25924:             }
                   25925:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   25926:                 $this->_cannotHaveSrcpackage($release);
                   25927:             }
                   25928:             $releases = $this->_packageInfo['phprelease'];
                   25929:             if (!is_array($releases)) {
                   25930:                 return true;
                   25931:             }
                   25932:             if (!isset($releases[0])) {
                   25933:                 $releases = array($releases);
                   25934:             }
                   25935:             foreach ($releases as $rel) {
                   25936:                 $this->_stupidSchemaValidate(array(
                   25937:                     '*installconditions',
                   25938:                     '*filelist',
                   25939:                 ), $rel, '<phprelease>');
                   25940:             }
                   25941:         }
                   25942:         foreach (array('', 'zend') as $prefix) {
                   25943:             $releasetype = $prefix . 'extsrcrelease';
                   25944:             if (isset($this->_packageInfo[$releasetype])) {
                   25945:                 $release = $releasetype;
                   25946:                 if (!isset($this->_packageInfo['providesextension'])) {
                   25947:                     $this->_mustProvideExtension($release);
                   25948:                 }
                   25949:                 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   25950:                     $this->_cannotHaveSrcpackage($release);
                   25951:                 }
                   25952:                 $releases = $this->_packageInfo[$releasetype];
                   25953:                 if (!is_array($releases)) {
                   25954:                     return true;
                   25955:                 }
                   25956:                 if (!isset($releases[0])) {
                   25957:                     $releases = array($releases);
                   25958:                 }
                   25959:                 foreach ($releases as $rel) {
                   25960:                     $this->_stupidSchemaValidate(array(
                   25961:                         '*installconditions',
                   25962:                         '*configureoption->name->prompt->?default',
                   25963:                         '*binarypackage',
                   25964:                         '*filelist',
                   25965:                     ), $rel, '<' . $releasetype . '>');
                   25966:                     if (isset($rel['binarypackage'])) {
                   25967:                         if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
                   25968:                             $rel['binarypackage'] = array($rel['binarypackage']);
                   25969:                         }
                   25970:                         foreach ($rel['binarypackage'] as $bin) {
                   25971:                             if (!is_string($bin)) {
                   25972:                                 $this->_binaryPackageMustBePackagename();
                   25973:                             }
                   25974:                         }
                   25975:                     }
                   25976:                 }
                   25977:             }
                   25978:             $releasetype = 'extbinrelease';
                   25979:             if (isset($this->_packageInfo[$releasetype])) {
                   25980:                 $release = $releasetype;
                   25981:                 if (!isset($this->_packageInfo['providesextension'])) {
                   25982:                     $this->_mustProvideExtension($release);
                   25983:                 }
                   25984:                 if (isset($this->_packageInfo['channel']) &&
                   25985:                       !isset($this->_packageInfo['srcpackage'])) {
                   25986:                     $this->_mustSrcPackage($release);
                   25987:                 }
                   25988:                 if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
                   25989:                     $this->_mustSrcuri($release);
                   25990:                 }
                   25991:                 $releases = $this->_packageInfo[$releasetype];
                   25992:                 if (!is_array($releases)) {
                   25993:                     return true;
                   25994:                 }
                   25995:                 if (!isset($releases[0])) {
                   25996:                     $releases = array($releases);
                   25997:                 }
                   25998:                 foreach ($releases as $rel) {
                   25999:                     $this->_stupidSchemaValidate(array(
                   26000:                         '*installconditions',
                   26001:                         '*filelist',
                   26002:                     ), $rel, '<' . $releasetype . '>');
                   26003:                 }
                   26004:             }
                   26005:         }
                   26006:         if (isset($this->_packageInfo['bundle'])) {
                   26007:             $release = 'bundle';
                   26008:             if (isset($this->_packageInfo['providesextension'])) {
                   26009:                 $this->_cannotProvideExtension($release);
                   26010:             }
                   26011:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   26012:                 $this->_cannotHaveSrcpackage($release);
                   26013:             }
                   26014:             $releases = $this->_packageInfo['bundle'];
                   26015:             if (!is_array($releases) || !isset($releases[0])) {
                   26016:                 $releases = array($releases);
                   26017:             }
                   26018:             foreach ($releases as $rel) {
                   26019:                 $this->_stupidSchemaValidate(array(
                   26020:                     '*installconditions',
                   26021:                     '*filelist',
                   26022:                 ), $rel, '<bundle>');
                   26023:             }
                   26024:         }
                   26025:         foreach ($releases as $rel) {
                   26026:             if (is_array($rel) && array_key_exists('installconditions', $rel)) {
                   26027:                 $this->_validateInstallConditions($rel['installconditions'],
                   26028:                     "<$release><installconditions>");
                   26029:             }
                   26030:             if (is_array($rel) && array_key_exists('filelist', $rel)) {
                   26031:                 if ($rel['filelist']) {
                   26032: 
                   26033:                     $this->_validateFilelist($rel['filelist'], true);
                   26034:                 }
                   26035:             }
                   26036:         }
                   26037:     }
                   26038: 
                   26039:     /**
                   26040:      * This is here to allow role extension through plugins
                   26041:      * @param string
                   26042:      */
                   26043:     function _validateRole($role)
                   26044:     {
                   26045:         return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
                   26046:     }
                   26047: 
                   26048:     function _pearVersionTooLow($version)
                   26049:     {
                   26050:         $this->_stack->push(__FUNCTION__, 'error',
                   26051:             array('version' => $version),
                   26052:             'This package.xml requires PEAR version %version% to parse properly, we are ' .
                   26053:             'version 1.9.4');
                   26054:     }
                   26055: 
                   26056:     function _invalidTagOrder($oktags, $actual, $root)
                   26057:     {
                   26058:         $this->_stack->push(__FUNCTION__, 'error',
                   26059:             array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
                   26060:             'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
                   26061:     }
                   26062: 
                   26063:     function _ignoreNotAllowed($type)
                   26064:     {
                   26065:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26066:             '<%type%> is not allowed inside global <contents>, only inside ' .
                   26067:             '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
                   26068:     }
                   26069: 
                   26070:     function _fileNotAllowed($type)
                   26071:     {
                   26072:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26073:             '<%type%> is not allowed inside release <filelist>, only inside ' .
                   26074:             '<contents>, use <ignore> and <install> only');
                   26075:     }
                   26076: 
                   26077:     function _oldStyleFileNotAllowed()
                   26078:     {
                   26079:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26080:             'Old-style <file>name</file> is not allowed.  Use' .
                   26081:             '<file name="name" role="role"/>');
                   26082:     }
                   26083: 
                   26084:     function _tagMissingAttribute($tag, $attr, $context)
                   26085:     {
                   26086:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   26087:             'attribute' => $attr, 'context' => $context),
                   26088:             'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
                   26089:     }
                   26090: 
                   26091:     function _tagHasNoAttribs($tag, $context)
                   26092:     {
                   26093:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   26094:             'context' => $context),
                   26095:             'tag <%tag%> has no attributes in context "%context%"');
                   26096:     }
                   26097: 
                   26098:     function _invalidInternalStructure()
                   26099:     {
                   26100:         $this->_stack->push(__FUNCTION__, 'exception', array(),
                   26101:             'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
                   26102:     }
                   26103: 
                   26104:     function _invalidFileRole($file, $dir, $role)
                   26105:     {
                   26106:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26107:             'file' => $file, 'dir' => $dir, 'role' => $role,
                   26108:             'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
                   26109:             'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
                   26110:     }
                   26111: 
                   26112:     function _invalidFileName($file, $dir)
                   26113:     {
                   26114:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26115:             'file' => $file),
                   26116:             'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
                   26117:     }
                   26118: 
                   26119:     function _invalidFileInstallAs($file, $as)
                   26120:     {
                   26121:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26122:             'file' => $file, 'as' => $as),
                   26123:             'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
                   26124:     }
                   26125: 
                   26126:     function _invalidDirName($dir)
                   26127:     {
                   26128:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26129:             'dir' => $file),
                   26130:             'Directory "%dir%" cannot begin with "./" or contain ".."');
                   26131:     }
                   26132: 
                   26133:     function _filelistCannotContainFile($filelist)
                   26134:     {
                   26135:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   26136:             '<%tag%> can only contain <dir>, contains <file>.  Use ' .
                   26137:             '<dir name="/"> as the first dir element');
                   26138:     }
                   26139: 
                   26140:     function _filelistMustContainDir($filelist)
                   26141:     {
                   26142:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   26143:             '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
                   26144:             'first dir element');
                   26145:     }
                   26146: 
                   26147:     function _tagCannotBeEmpty($tag)
                   26148:     {
                   26149:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   26150:             '<%tag%> cannot be empty (<%tag%/>)');
                   26151:     }
                   26152: 
                   26153:     function _UrlOrChannel($type, $name)
                   26154:     {
                   26155:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26156:             'name' => $name),
                   26157:             'Required dependency <%type%> "%name%" can have either url OR ' .
                   26158:             'channel attributes, and not both');
                   26159:     }
                   26160: 
                   26161:     function _NoChannel($type, $name)
                   26162:     {
                   26163:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26164:             'name' => $name),
                   26165:             'Required dependency <%type%> "%name%" must have either url OR ' .
                   26166:             'channel attributes');
                   26167:     }
                   26168: 
                   26169:     function _UrlOrChannelGroup($type, $name, $group)
                   26170:     {
                   26171:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26172:             'name' => $name, 'group' => $group),
                   26173:             'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
                   26174:             'channel attributes, and not both');
                   26175:     }
                   26176: 
                   26177:     function _NoChannelGroup($type, $name, $group)
                   26178:     {
                   26179:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26180:             'name' => $name, 'group' => $group),
                   26181:             'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
                   26182:             'channel attributes');
                   26183:     }
                   26184: 
                   26185:     function _unknownChannel($channel)
                   26186:     {
                   26187:         $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
                   26188:             'Unknown channel "%channel%"');
                   26189:     }
                   26190: 
                   26191:     function _noPackageVersion()
                   26192:     {
                   26193:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26194:             'package.xml <package> tag has no version attribute, or version is not 2.0');
                   26195:     }
                   26196: 
                   26197:     function _NoBundledPackages()
                   26198:     {
                   26199:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26200:             'No <bundledpackage> tag was found in <contents>, required for bundle packages');
                   26201:     }
                   26202: 
                   26203:     function _AtLeast2BundledPackages()
                   26204:     {
                   26205:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26206:             'At least 2 packages must be bundled in a bundle package');
                   26207:     }
                   26208: 
                   26209:     function _ChannelOrUri($name)
                   26210:     {
                   26211:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26212:             'Bundled package "%name%" can have either a uri or a channel, not both');
                   26213:     }
                   26214: 
                   26215:     function _noChildTag($child, $tag)
                   26216:     {
                   26217:         $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
                   26218:             'Tag <%tag%> is missing child tag <%child%>');
                   26219:     }
                   26220: 
                   26221:     function _invalidVersion($type, $value)
                   26222:     {
                   26223:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
                   26224:             'Version type <%type%> is not a valid version (%value%)');
                   26225:     }
                   26226: 
                   26227:     function _invalidState($type, $value)
                   26228:     {
                   26229:         $states = array('stable', 'beta', 'alpha', 'devel');
                   26230:         if ($type != 'api') {
                   26231:             $states[] = 'snapshot';
                   26232:         }
                   26233:         if (strtolower($value) == 'rc') {
                   26234:             $this->_stack->push(__FUNCTION__, 'error',
                   26235:                 array('version' => $this->_packageInfo['version']['release']),
                   26236:                 'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
                   26237:         }
                   26238:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
                   26239:             'types' => $states),
                   26240:             'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
                   26241:             '%types%');
                   26242:     }
                   26243: 
                   26244:     function _invalidTask($task, $ret, $file)
                   26245:     {
                   26246:         switch ($ret[0]) {
                   26247:             case PEAR_TASK_ERROR_MISSING_ATTRIB :
                   26248:                 $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
                   26249:                 $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
                   26250:             break;
                   26251:             case PEAR_TASK_ERROR_NOATTRIBS :
                   26252:                 $info = array('task' => $task, 'file' => $file);
                   26253:                 $msg = 'task <%task%> has no attributes in file %file%';
                   26254:             break;
                   26255:             case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
                   26256:                 $info = array('attrib' => $ret[1], 'values' => $ret[3],
                   26257:                     'was' => $ret[2], 'task' => $task, 'file' => $file);
                   26258:                 $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
                   26259:                     'in file %file%, expecting one of "%values%"';
                   26260:             break;
                   26261:             case PEAR_TASK_ERROR_INVALID :
                   26262:                 $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
                   26263:                 $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
                   26264:             break;
                   26265:         }
                   26266:         $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
                   26267:     }
                   26268: 
                   26269:     function _unknownTask($task, $file)
                   26270:     {
                   26271:         $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
                   26272:             'Unknown task "%task%" passed in file <file name="%file%">');
                   26273:     }
                   26274: 
                   26275:     function _subpackageCannotProvideExtension($name)
                   26276:     {
                   26277:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26278:             'Subpackage dependency "%name%" cannot use <providesextension>, ' .
                   26279:             'only package dependencies can use this tag');
                   26280:     }
                   26281: 
                   26282:     function _subpackagesCannotConflict($name)
                   26283:     {
                   26284:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26285:             'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
                   26286:             'only package dependencies can use this tag');
                   26287:     }
                   26288: 
                   26289:     function _cannotProvideExtension($release)
                   26290:     {
                   26291:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26292:             '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
                   26293:     }
                   26294: 
                   26295:     function _mustProvideExtension($release)
                   26296:     {
                   26297:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26298:             '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
                   26299:     }
                   26300: 
                   26301:     function _cannotHaveSrcpackage($release)
                   26302:     {
                   26303:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26304:             '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
                   26305:     }
                   26306: 
                   26307:     function _mustSrcPackage($release)
                   26308:     {
                   26309:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26310:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
                   26311:     }
                   26312: 
                   26313:     function _mustSrcuri($release)
                   26314:     {
                   26315:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26316:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
                   26317:     }
                   26318: 
                   26319:     function _uriDepsCannotHaveVersioning($type)
                   26320:     {
                   26321:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26322:             '%type%: dependencies with a <uri> tag cannot have any versioning information');
                   26323:     }
                   26324: 
                   26325:     function _conflictingDepsCannotHaveVersioning($type)
                   26326:     {
                   26327:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26328:             '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
                   26329:             'exclude specific versions of a dependency');
                   26330:     }
                   26331: 
                   26332:     function _DepchannelCannotBeUri($type)
                   26333:     {
                   26334:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26335:             '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
                   26336:             'dependencies only');
                   26337:     }
                   26338: 
                   26339:     function _bundledPackagesMustBeFilename()
                   26340:     {
                   26341:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26342:             '<bundledpackage> tags must contain only the filename of a package release ' .
                   26343:             'in the bundle');
                   26344:     }
                   26345: 
                   26346:     function _binaryPackageMustBePackagename()
                   26347:     {
                   26348:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26349:             '<binarypackage> tags must contain the name of a package that is ' .
                   26350:             'a compiled version of this extsrc/zendextsrc package');
                   26351:     }
                   26352: 
                   26353:     function _fileNotFound($file)
                   26354:     {
                   26355:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26356:             'File "%file%" in package.xml does not exist');
                   26357:     }
                   26358: 
                   26359:     function _notInContents($file, $tag)
                   26360:     {
                   26361:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
                   26362:             '<%tag% name="%file%"> is invalid, file is not in <contents>');
                   26363:     }
                   26364: 
                   26365:     function _cannotValidateNoPathSet()
                   26366:     {
                   26367:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26368:             'Cannot validate files, no path to package file is set (use setPackageFile())');
                   26369:     }
                   26370: 
                   26371:     function _usesroletaskMustHaveChannelOrUri($role, $tag)
                   26372:     {
                   26373:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   26374:             '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
                   26375:     }
                   26376: 
                   26377:     function _usesroletaskMustHavePackage($role, $tag)
                   26378:     {
                   26379:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   26380:             '<%tag%> for role "%role%" must contain <package>');
                   26381:     }
                   26382: 
                   26383:     function _usesroletaskMustHaveRoleTask($tag, $type)
                   26384:     {
                   26385:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
                   26386:             '<%tag%> must contain <%type%> defining the %type% to be used');
                   26387:     }
                   26388: 
                   26389:     function _cannotConflictWithAllOs($type)
                   26390:     {
                   26391:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   26392:             '%tag% cannot conflict with all OSes');
                   26393:     }
                   26394: 
                   26395:     function _invalidDepGroupName($name)
                   26396:     {
                   26397:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26398:             'Invalid dependency group name "%name%"');
                   26399:     }
                   26400: 
                   26401:     function _multipleToplevelDirNotAllowed()
                   26402:     {
                   26403:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26404:             'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
                   26405:                 'in a <dir name="/">');
                   26406:     }
                   26407: 
                   26408:     function _multipleInstallAs($file)
                   26409:     {
                   26410:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26411:             'Only one <install> tag is allowed for file "%file%"');
                   26412:     }
                   26413: 
                   26414:     function _ignoreAndInstallAs($file)
                   26415:     {
                   26416:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26417:             'Cannot have both <ignore> and <install> tags for file "%file%"');
                   26418:     }
                   26419: 
                   26420:     function _analyzeBundledPackages()
                   26421:     {
                   26422:         if (!$this->_isValid) {
                   26423:             return false;
                   26424:         }
                   26425:         if (!$this->_pf->getPackageType() == 'bundle') {
                   26426:             return false;
                   26427:         }
                   26428:         if (!isset($this->_pf->_packageFile)) {
                   26429:             return false;
                   26430:         }
                   26431:         $dir_prefix = dirname($this->_pf->_packageFile);
                   26432:         $common = new PEAR_Common;
                   26433:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   26434:             array($common, 'log');
                   26435:         $info = $this->_pf->getContents();
                   26436:         $info = $info['bundledpackage'];
                   26437:         if (!is_array($info)) {
                   26438:             $info = array($info);
                   26439:         }
                   26440:         $pkg = &new PEAR_PackageFile($this->_pf->_config);
                   26441:         foreach ($info as $package) {
                   26442:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
                   26443:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
                   26444:                 $this->_isValid = 0;
                   26445:                 continue;
                   26446:             }
                   26447:             call_user_func_array($log, array(1, "Analyzing bundled package $package"));
                   26448:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   26449:             $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
                   26450:                 PEAR_VALIDATE_NORMAL);
                   26451:             PEAR::popErrorHandling();
                   26452:             if (PEAR::isError($ret)) {
                   26453:                 call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
                   26454:                     'package'));
                   26455:                 $inf = $ret->getUserInfo();
                   26456:                 if (is_array($inf)) {
                   26457:                     foreach ($inf as $err) {
                   26458:                         call_user_func_array($log, array(1, $err['message']));
                   26459:                     }
                   26460:                 }
                   26461:                 return false;
                   26462:             }
                   26463:         }
                   26464:         return true;
                   26465:     }
                   26466: 
                   26467:     function _analyzePhpFiles()
                   26468:     {
                   26469:         if (!$this->_isValid) {
                   26470:             return false;
                   26471:         }
                   26472:         if (!isset($this->_pf->_packageFile)) {
                   26473:             $this->_cannotValidateNoPathSet();
                   26474:             return false;
                   26475:         }
                   26476:         $dir_prefix = dirname($this->_pf->_packageFile);
                   26477:         $common = new PEAR_Common;
                   26478:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   26479:             array(&$common, 'log');
                   26480:         $info = $this->_pf->getContents();
                   26481:         if (!$info || !isset($info['dir']['file'])) {
                   26482:             $this->_tagCannotBeEmpty('contents><dir');
                   26483:             return false;
                   26484:         }
                   26485:         $info = $info['dir']['file'];
                   26486:         if (isset($info['attribs'])) {
                   26487:             $info = array($info);
                   26488:         }
                   26489:         $provides = array();
                   26490:         foreach ($info as $fa) {
                   26491:             $fa = $fa['attribs'];
                   26492:             $file = $fa['name'];
                   26493:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   26494:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   26495:                 $this->_isValid = 0;
                   26496:                 continue;
                   26497:             }
                   26498:             if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
                   26499:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   26500:                 $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   26501:                 if ($srcinfo) {
                   26502:                     $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
                   26503:                 }
                   26504:             }
                   26505:         }
                   26506:         $this->_packageName = $pn = $this->_pf->getPackage();
                   26507:         $pnl = strlen($pn);
                   26508:         foreach ($provides as $key => $what) {
                   26509:             if (isset($what['explicit']) || !$what) {
                   26510:                 // skip conformance checks if the provides entry is
                   26511:                 // specified in the package.xml file
                   26512:                 continue;
                   26513:             }
                   26514:             extract($what);
                   26515:             if ($type == 'class') {
                   26516:                 if (!strncasecmp($name, $pn, $pnl)) {
                   26517:                     continue;
                   26518:                 }
                   26519:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26520:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   26521:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   26522:             } elseif ($type == 'function') {
                   26523:                 if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   26524:                     continue;
                   26525:                 }
                   26526:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26527:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   26528:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   26529:             }
                   26530:         }
                   26531:         return $this->_isValid;
                   26532:     }
                   26533: 
                   26534:     /**
                   26535:      * Analyze the source code of the given PHP file
                   26536:      *
                   26537:      * @param  string Filename of the PHP file
                   26538:      * @param  boolean whether to analyze $file as the file contents
                   26539:      * @return mixed
                   26540:      */
                   26541:     function analyzeSourceCode($file, $string = false)
                   26542:     {
                   26543:         if (!function_exists("token_get_all")) {
                   26544:             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26545:                 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
                   26546:             return false;
                   26547:         }
                   26548: 
                   26549:         if (!defined('T_DOC_COMMENT')) {
                   26550:             define('T_DOC_COMMENT', T_COMMENT);
                   26551:         }
                   26552: 
                   26553:         if (!defined('T_INTERFACE')) {
                   26554:             define('T_INTERFACE', -1);
                   26555:         }
                   26556: 
                   26557:         if (!defined('T_IMPLEMENTS')) {
                   26558:             define('T_IMPLEMENTS', -1);
                   26559:         }
                   26560: 
                   26561:         if ($string) {
                   26562:             $contents = $file;
                   26563:         } else {
                   26564:             if (!$fp = @fopen($file, "r")) {
                   26565:                 return false;
                   26566:             }
                   26567:             fclose($fp);
                   26568:             $contents = file_get_contents($file);
                   26569:         }
                   26570: 
                   26571:         // Silence this function so we can catch PHP Warnings and show our own custom message
                   26572:         $tokens = @token_get_all($contents);
                   26573:         if (isset($php_errormsg)) {
                   26574:             if (isset($this->_stack)) {
                   26575:                 $pn = $this->_pf->getPackage();
                   26576:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26577:                         array('file' => $file, 'package' => $pn),
                   26578:                         'in %file%: Could not process file for unkown reasons,' .
                   26579:                         ' possibly a PHP parse error in %file% from %package%');
                   26580:             }
                   26581:         }
                   26582: /*
                   26583:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   26584:             @list($token, $data) = $tokens[$i];
                   26585:             if (is_string($token)) {
                   26586:                 var_dump($token);
                   26587:             } else {
                   26588:                 print token_name($token) . ' ';
                   26589:                 var_dump(rtrim($data));
                   26590:             }
                   26591:         }
                   26592: */
                   26593:         $look_for = 0;
                   26594:         $paren_level = 0;
                   26595:         $bracket_level = 0;
                   26596:         $brace_level = 0;
                   26597:         $lastphpdoc = '';
                   26598:         $current_class = '';
                   26599:         $current_interface = '';
                   26600:         $current_class_level = -1;
                   26601:         $current_function = '';
                   26602:         $current_function_level = -1;
                   26603:         $declared_classes = array();
                   26604:         $declared_interfaces = array();
                   26605:         $declared_functions = array();
                   26606:         $declared_methods = array();
                   26607:         $used_classes = array();
                   26608:         $used_functions = array();
                   26609:         $extends = array();
                   26610:         $implements = array();
                   26611:         $nodeps = array();
                   26612:         $inquote = false;
                   26613:         $interface = false;
                   26614:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   26615:             if (is_array($tokens[$i])) {
                   26616:                 list($token, $data) = $tokens[$i];
                   26617:             } else {
                   26618:                 $token = $tokens[$i];
                   26619:                 $data = '';
                   26620:             }
                   26621: 
                   26622:             if ($inquote) {
                   26623:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   26624:                     continue;
                   26625:                 } else {
                   26626:                     $inquote = false;
                   26627:                     continue;
                   26628:                 }
                   26629:             }
                   26630: 
                   26631:             switch ($token) {
                   26632:                 case T_WHITESPACE :
                   26633:                     continue;
                   26634:                 case ';':
                   26635:                     if ($interface) {
                   26636:                         $current_function = '';
                   26637:                         $current_function_level = -1;
                   26638:                     }
                   26639:                     break;
                   26640:                 case '"':
                   26641:                 case T_START_HEREDOC:
                   26642:                     $inquote = true;
                   26643:                     break;
                   26644:                 case T_CURLY_OPEN:
                   26645:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   26646:                 case '{': $brace_level++; continue 2;
                   26647:                 case '}':
                   26648:                     $brace_level--;
                   26649:                     if ($current_class_level == $brace_level) {
                   26650:                         $current_class = '';
                   26651:                         $current_class_level = -1;
                   26652:                     }
                   26653:                     if ($current_function_level == $brace_level) {
                   26654:                         $current_function = '';
                   26655:                         $current_function_level = -1;
                   26656:                     }
                   26657:                     continue 2;
                   26658:                 case '[': $bracket_level++; continue 2;
                   26659:                 case ']': $bracket_level--; continue 2;
                   26660:                 case '(': $paren_level++;   continue 2;
                   26661:                 case ')': $paren_level--;   continue 2;
                   26662:                 case T_INTERFACE:
                   26663:                     $interface = true;
                   26664:                 case T_CLASS:
                   26665:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   26666:                         if (isset($this->_stack)) {
                   26667:                             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26668:                             'Parser error: invalid PHP found in file "%file%"');
                   26669:                         } else {
                   26670:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   26671:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   26672:                         }
                   26673: 
                   26674:                         return false;
                   26675:                     }
                   26676:                 case T_FUNCTION:
                   26677:                 case T_NEW:
                   26678:                 case T_EXTENDS:
                   26679:                 case T_IMPLEMENTS:
                   26680:                     $look_for = $token;
                   26681:                     continue 2;
                   26682:                 case T_STRING:
                   26683:                     if (version_compare(zend_version(), '2.0', '<')) {
                   26684:                         if (in_array(strtolower($data),
                   26685:                             array('public', 'private', 'protected', 'abstract',
                   26686:                                   'interface', 'implements', 'throw')
                   26687:                                  )
                   26688:                         ) {
                   26689:                             if (isset($this->_stack)) {
                   26690:                                 $this->_stack->push(__FUNCTION__, 'warning', array(
                   26691:                                     'file' => $file),
                   26692:                                     'Error, PHP5 token encountered in %file%,' .
                   26693:                                     ' analysis should be in PHP5');
                   26694:                             } else {
                   26695:                                 PEAR::raiseError('Error: PHP5 token encountered in ' . $file .
                   26696:                                     'packaging should be done in PHP 5');
                   26697:                                 return false;
                   26698:                             }
                   26699:                         }
                   26700:                     }
                   26701: 
                   26702:                     if ($look_for == T_CLASS) {
                   26703:                         $current_class = $data;
                   26704:                         $current_class_level = $brace_level;
                   26705:                         $declared_classes[] = $current_class;
                   26706:                     } elseif ($look_for == T_INTERFACE) {
                   26707:                         $current_interface = $data;
                   26708:                         $current_class_level = $brace_level;
                   26709:                         $declared_interfaces[] = $current_interface;
                   26710:                     } elseif ($look_for == T_IMPLEMENTS) {
                   26711:                         $implements[$current_class] = $data;
                   26712:                     } elseif ($look_for == T_EXTENDS) {
                   26713:                         $extends[$current_class] = $data;
                   26714:                     } elseif ($look_for == T_FUNCTION) {
                   26715:                         if ($current_class) {
                   26716:                             $current_function = "$current_class::$data";
                   26717:                             $declared_methods[$current_class][] = $data;
                   26718:                         } elseif ($current_interface) {
                   26719:                             $current_function = "$current_interface::$data";
                   26720:                             $declared_methods[$current_interface][] = $data;
                   26721:                         } else {
                   26722:                             $current_function = $data;
                   26723:                             $declared_functions[] = $current_function;
                   26724:                         }
                   26725: 
                   26726:                         $current_function_level = $brace_level;
                   26727:                         $m = array();
                   26728:                     } elseif ($look_for == T_NEW) {
                   26729:                         $used_classes[$data] = true;
                   26730:                     }
                   26731: 
                   26732:                     $look_for = 0;
                   26733:                     continue 2;
                   26734:                 case T_VARIABLE:
                   26735:                     $look_for = 0;
                   26736:                     continue 2;
                   26737:                 case T_DOC_COMMENT:
                   26738:                 case T_COMMENT:
                   26739:                     if (preg_match('!^/\*\*\s!', $data)) {
                   26740:                         $lastphpdoc = $data;
                   26741:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   26742:                             $nodeps = array_merge($nodeps, $m[1]);
                   26743:                         }
                   26744:                     }
                   26745:                     continue 2;
                   26746:                 case T_DOUBLE_COLON:
                   26747:                     $token = $tokens[$i - 1][0];
                   26748:                     if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC)) {
                   26749:                         if (isset($this->_stack)) {
                   26750:                             $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
                   26751:                                 'Parser error: invalid PHP found in file "%file%"');
                   26752:                         } else {
                   26753:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   26754:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   26755:                         }
                   26756: 
                   26757:                         return false;
                   26758:                     }
                   26759: 
                   26760:                     $class = $tokens[$i - 1][1];
                   26761:                     if (strtolower($class) != 'parent') {
                   26762:                         $used_classes[$class] = true;
                   26763:                     }
                   26764: 
                   26765:                     continue 2;
                   26766:             }
                   26767:         }
                   26768: 
                   26769:         return array(
                   26770:             "source_file" => $file,
                   26771:             "declared_classes" => $declared_classes,
                   26772:             "declared_interfaces" => $declared_interfaces,
                   26773:             "declared_methods" => $declared_methods,
                   26774:             "declared_functions" => $declared_functions,
                   26775:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   26776:             "inheritance" => $extends,
                   26777:             "implements" => $implements,
                   26778:         );
                   26779:     }
                   26780: 
                   26781:     /**
                   26782:      * Build a "provides" array from data returned by
                   26783:      * analyzeSourceCode().  The format of the built array is like
                   26784:      * this:
                   26785:      *
                   26786:      *  array(
                   26787:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   26788:      *    ...
                   26789:      *  )
                   26790:      *
                   26791:      *
                   26792:      * @param array $srcinfo array with information about a source file
                   26793:      * as returned by the analyzeSourceCode() method.
                   26794:      *
                   26795:      * @return void
                   26796:      *
                   26797:      * @access private
                   26798:      *
                   26799:      */
                   26800:     function _buildProvidesArray($srcinfo)
                   26801:     {
                   26802:         if (!$this->_isValid) {
                   26803:             return array();
                   26804:         }
                   26805: 
                   26806:         $providesret = array();
                   26807:         $file        = basename($srcinfo['source_file']);
                   26808:         $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
                   26809:         $pnl         = strlen($pn);
                   26810:         foreach ($srcinfo['declared_classes'] as $class) {
                   26811:             $key = "class;$class";
                   26812:             if (isset($providesret[$key])) {
                   26813:                 continue;
                   26814:             }
                   26815: 
                   26816:             $providesret[$key] =
                   26817:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   26818:             if (isset($srcinfo['inheritance'][$class])) {
                   26819:                 $providesret[$key]['extends'] =
                   26820:                     $srcinfo['inheritance'][$class];
                   26821:             }
                   26822:         }
                   26823: 
                   26824:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   26825:             foreach ($methods as $method) {
                   26826:                 $function = "$class::$method";
                   26827:                 $key = "function;$function";
                   26828:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   26829:                     isset($providesret[$key])) {
                   26830:                     continue;
                   26831:                 }
                   26832: 
                   26833:                 $providesret[$key] =
                   26834:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   26835:             }
                   26836:         }
                   26837: 
                   26838:         foreach ($srcinfo['declared_functions'] as $function) {
                   26839:             $key = "function;$function";
                   26840:             if ($function{0} == '_' || isset($providesret[$key])) {
                   26841:                 continue;
                   26842:             }
                   26843: 
                   26844:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   26845:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   26846:             }
                   26847: 
                   26848:             $providesret[$key] =
                   26849:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   26850:         }
                   26851: 
                   26852:         return $providesret;
                   26853:     }
                   26854: }PEAR-1.9.4/PEAR/PackageFile/v1.php0000644000076500000240000014376011605156760015172 0ustar  helgistaff<?php
                   26855: /**
                   26856:  * PEAR_PackageFile_v1, package.xml version 1.0
                   26857:  *
                   26858:  * PHP versions 4 and 5
                   26859:  *
                   26860:  * @category   pear
                   26861:  * @package    PEAR
                   26862:  * @author     Greg Beaver <cellog@php.net>
                   26863:  * @copyright  1997-2009 The Authors
                   26864:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   26865:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   26866:  * @link       http://pear.php.net/package/PEAR
                   26867:  * @since      File available since Release 1.4.0a1
                   26868:  */
                   26869: /**
                   26870:  * For error handling
                   26871:  */
                   26872: require_once 'PEAR/ErrorStack.php';
                   26873: 
                   26874: /**
                   26875:  * Error code if parsing is attempted with no xml extension
                   26876:  */
                   26877: define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
                   26878: 
                   26879: /**
                   26880:  * Error code if creating the xml parser resource fails
                   26881:  */
                   26882: define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
                   26883: 
                   26884: /**
                   26885:  * Error code used for all sax xml parsing errors
                   26886:  */
                   26887: define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
                   26888: 
                   26889: /**
                   26890:  * Error code used when there is no name
                   26891:  */
                   26892: define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
                   26893: 
                   26894: /**
                   26895:  * Error code when a package name is not valid
                   26896:  */
                   26897: define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
                   26898: 
                   26899: /**
                   26900:  * Error code used when no summary is parsed
                   26901:  */
                   26902: define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
                   26903: 
                   26904: /**
                   26905:  * Error code for summaries that are more than 1 line
                   26906:  */
                   26907: define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
                   26908: 
                   26909: /**
                   26910:  * Error code used when no description is present
                   26911:  */
                   26912: define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
                   26913: 
                   26914: /**
                   26915:  * Error code used when no license is present
                   26916:  */
                   26917: define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
                   26918: 
                   26919: /**
                   26920:  * Error code used when a <version> version number is not present
                   26921:  */
                   26922: define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
                   26923: 
                   26924: /**
                   26925:  * Error code used when a <version> version number is invalid
                   26926:  */
                   26927: define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
                   26928: 
                   26929: /**
                   26930:  * Error code when release state is missing
                   26931:  */
                   26932: define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
                   26933: 
                   26934: /**
                   26935:  * Error code when release state is invalid
                   26936:  */
                   26937: define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
                   26938: 
                   26939: /**
                   26940:  * Error code when release state is missing
                   26941:  */
                   26942: define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
                   26943: 
                   26944: /**
                   26945:  * Error code when release state is invalid
                   26946:  */
                   26947: define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
                   26948: 
                   26949: /**
                   26950:  * Error code when no release notes are found
                   26951:  */
                   26952: define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
                   26953: 
                   26954: /**
                   26955:  * Error code when no maintainers are found
                   26956:  */
                   26957: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
                   26958: 
                   26959: /**
                   26960:  * Error code when a maintainer has no handle
                   26961:  */
                   26962: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
                   26963: 
                   26964: /**
                   26965:  * Error code when a maintainer has no handle
                   26966:  */
                   26967: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
                   26968: 
                   26969: /**
                   26970:  * Error code when a maintainer has no name
                   26971:  */
                   26972: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
                   26973: 
                   26974: /**
                   26975:  * Error code when a maintainer has no email
                   26976:  */
                   26977: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
                   26978: 
                   26979: /**
                   26980:  * Error code when a maintainer has no handle
                   26981:  */
                   26982: define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
                   26983: 
                   26984: /**
                   26985:  * Error code when a dependency is not a PHP dependency, but has no name
                   26986:  */
                   26987: define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
                   26988: 
                   26989: /**
                   26990:  * Error code when a dependency has no type (pkg, php, etc.)
                   26991:  */
                   26992: define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
                   26993: 
                   26994: /**
                   26995:  * Error code when a dependency has no relation (lt, ge, has, etc.)
                   26996:  */
                   26997: define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
                   26998: 
                   26999: /**
                   27000:  * Error code when a dependency is not a 'has' relation, but has no version
                   27001:  */
                   27002: define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
                   27003: 
                   27004: /**
                   27005:  * Error code when a dependency has an invalid relation
                   27006:  */
                   27007: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
                   27008: 
                   27009: /**
                   27010:  * Error code when a dependency has an invalid type
                   27011:  */
                   27012: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
                   27013: 
                   27014: /**
                   27015:  * Error code when a dependency has an invalid optional option
                   27016:  */
                   27017: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
                   27018: 
                   27019: /**
                   27020:  * Error code when a dependency is a pkg dependency, and has an invalid package name
                   27021:  */
                   27022: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
                   27023: 
                   27024: /**
                   27025:  * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
                   27026:  */
                   27027: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
                   27028: 
                   27029: /**
                   27030:  * Error code when rel="has" and version attribute is present.
                   27031:  */
                   27032: define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
                   27033: 
                   27034: /**
                   27035:  * Error code when type="php" and dependency name is present
                   27036:  */
                   27037: define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
                   27038: 
                   27039: /**
                   27040:  * Error code when a configure option has no name
                   27041:  */
                   27042: define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
                   27043: 
                   27044: /**
                   27045:  * Error code when a configure option has no name
                   27046:  */
                   27047: define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
                   27048: 
                   27049: /**
                   27050:  * Error code when a file in the filelist has an invalid role
                   27051:  */
                   27052: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
                   27053: 
                   27054: /**
                   27055:  * Error code when a file in the filelist has no role
                   27056:  */
                   27057: define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
                   27058: 
                   27059: /**
                   27060:  * Error code when analyzing a php source file that has parse errors
                   27061:  */
                   27062: define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
                   27063: 
                   27064: /**
                   27065:  * Error code when analyzing a php source file reveals a source element
                   27066:  * without a package name prefix
                   27067:  */
                   27068: define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
                   27069: 
                   27070: /**
                   27071:  * Error code when an unknown channel is specified
                   27072:  */
                   27073: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
                   27074: 
                   27075: /**
                   27076:  * Error code when no files are found in the filelist
                   27077:  */
                   27078: define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
                   27079: 
                   27080: /**
                   27081:  * Error code when a file is not valid php according to _analyzeSourceCode()
                   27082:  */
                   27083: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
                   27084: 
                   27085: /**
                   27086:  * Error code when the channel validator returns an error or warning
                   27087:  */
                   27088: define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
                   27089: 
                   27090: /**
                   27091:  * Error code when a php5 package is packaged in php4 (analysis doesn't work)
                   27092:  */
                   27093: define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
                   27094: 
                   27095: /**
                   27096:  * Error code when a file is listed in package.xml but does not exist
                   27097:  */
                   27098: define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
                   27099: 
                   27100: /**
                   27101:  * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
                   27102:  */
                   27103: define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
                   27104: 
                   27105: /**
                   27106:  * Error code when a package.xml contains non-ISO-8859-1 characters
                   27107:  */
                   27108: define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
                   27109: 
                   27110: /**
                   27111:  * Error code when a dependency is not a 'has' relation, but has no version
                   27112:  */
                   27113: define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
                   27114: 
                   27115: /**
                   27116:  * Error code when a package has no lead developer
                   27117:  */
                   27118: define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
                   27119: 
                   27120: /**
                   27121:  * Error code when a filename begins with "."
                   27122:  */
                   27123: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
                   27124: /**
                   27125:  * package.xml encapsulator
                   27126:  * @category   pear
                   27127:  * @package    PEAR
                   27128:  * @author     Greg Beaver <cellog@php.net>
                   27129:  * @copyright  1997-2009 The Authors
                   27130:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   27131:  * @version    Release: 1.9.4
                   27132:  * @link       http://pear.php.net/package/PEAR
                   27133:  * @since      Class available since Release 1.4.0a1
                   27134:  */
                   27135: class PEAR_PackageFile_v1
                   27136: {
                   27137:     /**
                   27138:      * @access private
                   27139:      * @var PEAR_ErrorStack
                   27140:      * @access private
                   27141:      */
                   27142:     var $_stack;
                   27143: 
                   27144:     /**
                   27145:      * A registry object, used to access the package name validation regex for non-standard channels
                   27146:      * @var PEAR_Registry
                   27147:      * @access private
                   27148:      */
                   27149:     var $_registry;
                   27150: 
                   27151:     /**
                   27152:      * An object that contains a log method that matches PEAR_Common::log's signature
                   27153:      * @var object
                   27154:      * @access private
                   27155:      */
                   27156:     var $_logger;
                   27157: 
                   27158:     /**
                   27159:      * Parsed package information
                   27160:      * @var array
                   27161:      * @access private
                   27162:      */
                   27163:     var $_packageInfo;
                   27164: 
                   27165:     /**
                   27166:      * path to package.xml
                   27167:      * @var string
                   27168:      * @access private
                   27169:      */
                   27170:     var $_packageFile;
                   27171: 
                   27172:     /**
                   27173:      * path to package .tgz or false if this is a local/extracted package.xml
                   27174:      * @var string
                   27175:      * @access private
                   27176:      */
                   27177:     var $_archiveFile;
                   27178: 
                   27179:     /**
                   27180:      * @var int
                   27181:      * @access private
                   27182:      */
                   27183:     var $_isValid = 0;
                   27184: 
                   27185:     /**
                   27186:      * Determines whether this packagefile was initialized only with partial package info
                   27187:      *
                   27188:      * If this package file was constructed via parsing REST, it will only contain
                   27189:      *
                   27190:      * - package name
                   27191:      * - channel name
                   27192:      * - dependencies 
                   27193:      * @var boolean
                   27194:      * @access private
                   27195:      */
                   27196:     var $_incomplete = true;
                   27197: 
                   27198:     /**
                   27199:      * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
                   27200:      * @param string Name of Error Stack class to use.
                   27201:      */
                   27202:     function PEAR_PackageFile_v1()
                   27203:     {
                   27204:         $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
                   27205:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   27206:         $this->_isValid = 0;
                   27207:     }
                   27208: 
                   27209:     function installBinary($installer)
                   27210:     {
                   27211:         return false;
                   27212:     }
                   27213: 
                   27214:     function isExtension($name)
                   27215:     {
                   27216:         return false;
                   27217:     }
                   27218: 
                   27219:     function setConfig(&$config)
                   27220:     {
                   27221:         $this->_config = &$config;
                   27222:         $this->_registry = &$config->getRegistry();
                   27223:     }
                   27224: 
                   27225:     function setRequestedGroup()
                   27226:     {
                   27227:         // placeholder
                   27228:     }
                   27229: 
                   27230:     /**
                   27231:      * For saving in the registry.
                   27232:      *
                   27233:      * Set the last version that was installed
                   27234:      * @param string
                   27235:      */
                   27236:     function setLastInstalledVersion($version)
                   27237:     {
                   27238:         $this->_packageInfo['_lastversion'] = $version;
                   27239:     }
                   27240: 
                   27241:     /**
                   27242:      * @return string|false
                   27243:      */
                   27244:     function getLastInstalledVersion()
                   27245:     {
                   27246:         if (isset($this->_packageInfo['_lastversion'])) {
                   27247:             return $this->_packageInfo['_lastversion'];
                   27248:         }
                   27249:         return false;
                   27250:     }
                   27251: 
                   27252:     function getInstalledBinary()
                   27253:     {
                   27254:         return false;
                   27255:     }
                   27256: 
                   27257:     function listPostinstallScripts()
                   27258:     {
                   27259:         return false;
                   27260:     }
                   27261: 
                   27262:     function initPostinstallScripts()
                   27263:     {
                   27264:         return false;
                   27265:     }
                   27266: 
                   27267:     function setLogger(&$logger)
                   27268:     {
                   27269:         if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
                   27270:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   27271:         }
                   27272:         $this->_logger = &$logger;
                   27273:     }
                   27274: 
                   27275:     function setPackagefile($file, $archive = false)
                   27276:     {
                   27277:         $this->_packageFile = $file;
                   27278:         $this->_archiveFile = $archive ? $archive : $file;
                   27279:     }
                   27280: 
                   27281:     function getPackageFile()
                   27282:     {
                   27283:         return isset($this->_packageFile) ? $this->_packageFile : false;
                   27284:     }
                   27285: 
                   27286:     function getPackageType()
                   27287:     {
                   27288:         return 'php';
                   27289:     }
                   27290: 
                   27291:     function getArchiveFile()
                   27292:     {
                   27293:         return $this->_archiveFile;
                   27294:     }
                   27295: 
                   27296:     function packageInfo($field)
                   27297:     {
                   27298:         if (!is_string($field) || empty($field) ||
                   27299:             !isset($this->_packageInfo[$field])) {
                   27300:             return false;
                   27301:         }
                   27302:         return $this->_packageInfo[$field];
                   27303:     }
                   27304: 
                   27305:     function setDirtree($path)
                   27306:     {
                   27307:         if (!isset($this->_packageInfo['dirtree'])) {
                   27308:             $this->_packageInfo['dirtree'] = array();
                   27309:         }
                   27310:         $this->_packageInfo['dirtree'][$path] = true;
                   27311:     }
                   27312: 
                   27313:     function getDirtree()
                   27314:     {
                   27315:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   27316:             return $this->_packageInfo['dirtree'];
                   27317:         }
                   27318:         return false;
                   27319:     }
                   27320: 
                   27321:     function resetDirtree()
                   27322:     {
                   27323:         unset($this->_packageInfo['dirtree']);
                   27324:     }
                   27325: 
                   27326:     function fromArray($pinfo)
                   27327:     {
                   27328:         $this->_incomplete = false;
                   27329:         $this->_packageInfo = $pinfo;
                   27330:     }
                   27331: 
                   27332:     function isIncomplete()
                   27333:     {
                   27334:         return $this->_incomplete;
                   27335:     }
                   27336: 
                   27337:     function getChannel()
                   27338:     {
                   27339:         return 'pear.php.net';
                   27340:     }
                   27341: 
                   27342:     function getUri()
                   27343:     {
                   27344:         return false;
                   27345:     }
                   27346: 
                   27347:     function getTime()
                   27348:     {
                   27349:         return false;
                   27350:     }
                   27351: 
                   27352:     function getExtends()
                   27353:     {
                   27354:         if (isset($this->_packageInfo['extends'])) {
                   27355:             return $this->_packageInfo['extends'];
                   27356:         }
                   27357:         return false;
                   27358:     }
                   27359: 
                   27360:     /**
                   27361:      * @return array
                   27362:      */
                   27363:     function toArray()
                   27364:     {
                   27365:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   27366:             return false;
                   27367:         }
                   27368:         return $this->getArray();
                   27369:     }
                   27370: 
                   27371:     function getArray()
                   27372:     {
                   27373:         return $this->_packageInfo;
                   27374:     }
                   27375: 
                   27376:     function getName()
                   27377:     {
                   27378:         return $this->getPackage();
                   27379:     }
                   27380: 
                   27381:     function getPackage()
                   27382:     {
                   27383:         if (isset($this->_packageInfo['package'])) {
                   27384:             return $this->_packageInfo['package'];
                   27385:         }
                   27386:         return false;
                   27387:     }
                   27388: 
                   27389:     /**
                   27390:      * WARNING - don't use this unless you know what you are doing
                   27391:      */
                   27392:     function setRawPackage($package)
                   27393:     {
                   27394:         $this->_packageInfo['package'] = $package;
                   27395:     }
                   27396: 
                   27397:     function setPackage($package)
                   27398:     {
                   27399:         $this->_packageInfo['package'] = $package;
                   27400:         $this->_isValid = false;
                   27401:     }
                   27402: 
                   27403:     function getVersion()
                   27404:     {
                   27405:         if (isset($this->_packageInfo['version'])) {
                   27406:             return $this->_packageInfo['version'];
                   27407:         }
                   27408:         return false;
                   27409:     }
                   27410: 
                   27411:     function setVersion($version)
                   27412:     {
                   27413:         $this->_packageInfo['version'] = $version;
                   27414:         $this->_isValid = false;
                   27415:     }
                   27416: 
                   27417:     function clearMaintainers()
                   27418:     {
                   27419:         unset($this->_packageInfo['maintainers']);
                   27420:     }
                   27421: 
                   27422:     function getMaintainers()
                   27423:     {
                   27424:         if (isset($this->_packageInfo['maintainers'])) {
                   27425:             return $this->_packageInfo['maintainers'];
                   27426:         }
                   27427:         return false;
                   27428:     }
                   27429: 
                   27430:     /**
                   27431:      * Adds a new maintainer - no checking of duplicates is performed, use
                   27432:      * updatemaintainer for that purpose.
                   27433:      */
                   27434:     function addMaintainer($role, $handle, $name, $email)
                   27435:     {
                   27436:         $this->_packageInfo['maintainers'][] =
                   27437:             array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
                   27438:         $this->_isValid = false;
                   27439:     }
                   27440: 
                   27441:     function updateMaintainer($role, $handle, $name, $email)
                   27442:     {
                   27443:         $found = false;
                   27444:         if (!isset($this->_packageInfo['maintainers']) ||
                   27445:               !is_array($this->_packageInfo['maintainers'])) {
                   27446:             return $this->addMaintainer($role, $handle, $name, $email);
                   27447:         }
                   27448:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   27449:             if ($maintainer['handle'] == $handle) {
                   27450:                 $found = $i;
                   27451:                 break;
                   27452:             }
                   27453:         }
                   27454:         if ($found !== false) {
                   27455:             unset($this->_packageInfo['maintainers'][$found]);
                   27456:             $this->_packageInfo['maintainers'] =
                   27457:                 array_values($this->_packageInfo['maintainers']);
                   27458:         }
                   27459:         $this->addMaintainer($role, $handle, $name, $email);
                   27460:     }
                   27461: 
                   27462:     function deleteMaintainer($handle)
                   27463:     {
                   27464:         $found = false;
                   27465:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   27466:             if ($maintainer['handle'] == $handle) {
                   27467:                 $found = $i;
                   27468:                 break;
                   27469:             }
                   27470:         }
                   27471:         if ($found !== false) {
                   27472:             unset($this->_packageInfo['maintainers'][$found]);
                   27473:             $this->_packageInfo['maintainers'] =
                   27474:                 array_values($this->_packageInfo['maintainers']);
                   27475:             return true;
                   27476:         }
                   27477:         return false;
                   27478:     }
                   27479: 
                   27480:     function getState()
                   27481:     {
                   27482:         if (isset($this->_packageInfo['release_state'])) {
                   27483:             return $this->_packageInfo['release_state'];
                   27484:         }
                   27485:         return false;
                   27486:     }
                   27487: 
                   27488:     function setRawState($state)
                   27489:     {
                   27490:         $this->_packageInfo['release_state'] = $state;
                   27491:     }
                   27492: 
                   27493:     function setState($state)
                   27494:     {
                   27495:         $this->_packageInfo['release_state'] = $state;
                   27496:         $this->_isValid = false;
                   27497:     }
                   27498: 
                   27499:     function getDate()
                   27500:     {
                   27501:         if (isset($this->_packageInfo['release_date'])) {
                   27502:             return $this->_packageInfo['release_date'];
                   27503:         }
                   27504:         return false;
                   27505:     }
                   27506: 
                   27507:     function setDate($date)
                   27508:     {
                   27509:         $this->_packageInfo['release_date'] = $date;
                   27510:         $this->_isValid = false;
                   27511:     }
                   27512: 
                   27513:     function getLicense()
                   27514:     {
                   27515:         if (isset($this->_packageInfo['release_license'])) {
                   27516:             return $this->_packageInfo['release_license'];
                   27517:         }
                   27518:         return false;
                   27519:     }
                   27520: 
                   27521:     function setLicense($date)
                   27522:     {
                   27523:         $this->_packageInfo['release_license'] = $date;
                   27524:         $this->_isValid = false;
                   27525:     }
                   27526: 
                   27527:     function getSummary()
                   27528:     {
                   27529:         if (isset($this->_packageInfo['summary'])) {
                   27530:             return $this->_packageInfo['summary'];
                   27531:         }
                   27532:         return false;
                   27533:     }
                   27534: 
                   27535:     function setSummary($summary)
                   27536:     {
                   27537:         $this->_packageInfo['summary'] = $summary;
                   27538:         $this->_isValid = false;
                   27539:     }
                   27540: 
                   27541:     function getDescription()
                   27542:     {
                   27543:         if (isset($this->_packageInfo['description'])) {
                   27544:             return $this->_packageInfo['description'];
                   27545:         }
                   27546:         return false;
                   27547:     }
                   27548: 
                   27549:     function setDescription($desc)
                   27550:     {
                   27551:         $this->_packageInfo['description'] = $desc;
                   27552:         $this->_isValid = false;
                   27553:     }
                   27554: 
                   27555:     function getNotes()
                   27556:     {
                   27557:         if (isset($this->_packageInfo['release_notes'])) {
                   27558:             return $this->_packageInfo['release_notes'];
                   27559:         }
                   27560:         return false;
                   27561:     }
                   27562: 
                   27563:     function setNotes($notes)
                   27564:     {
                   27565:         $this->_packageInfo['release_notes'] = $notes;
                   27566:         $this->_isValid = false;
                   27567:     }
                   27568: 
                   27569:     function getDeps()
                   27570:     {
                   27571:         if (isset($this->_packageInfo['release_deps'])) {
                   27572:             return $this->_packageInfo['release_deps'];
                   27573:         }
                   27574:         return false;
                   27575:     }
                   27576: 
                   27577:     /**
                   27578:      * Reset dependencies prior to adding new ones
                   27579:      */
                   27580:     function clearDeps()
                   27581:     {
                   27582:         unset($this->_packageInfo['release_deps']);
                   27583:     }
                   27584: 
                   27585:     function addPhpDep($version, $rel)
                   27586:     {
                   27587:         $this->_isValid = false;
                   27588:         $this->_packageInfo['release_deps'][] =
                   27589:             array('type' => 'php',
                   27590:                   'rel' => $rel,
                   27591:                   'version' => $version);
                   27592:     }
                   27593: 
                   27594:     function addPackageDep($name, $version, $rel, $optional = 'no')
                   27595:     {
                   27596:         $this->_isValid = false;
                   27597:         $dep =
                   27598:             array('type' => 'pkg',
                   27599:                   'name' => $name,
                   27600:                   'rel' => $rel,
                   27601:                   'optional' => $optional);
                   27602:         if ($rel != 'has' && $rel != 'not') {
                   27603:             $dep['version'] = $version;
                   27604:         }
                   27605:         $this->_packageInfo['release_deps'][] = $dep;
                   27606:     }
                   27607: 
                   27608:     function addExtensionDep($name, $version, $rel, $optional = 'no')
                   27609:     {
                   27610:         $this->_isValid = false;
                   27611:         $this->_packageInfo['release_deps'][] =
                   27612:             array('type' => 'ext',
                   27613:                   'name' => $name,
                   27614:                   'rel' => $rel,
                   27615:                   'version' => $version,
                   27616:                   'optional' => $optional);
                   27617:     }
                   27618: 
                   27619:     /**
                   27620:      * WARNING - do not use this function directly unless you know what you're doing
                   27621:      */
                   27622:     function setDeps($deps)
                   27623:     {
                   27624:         $this->_packageInfo['release_deps'] = $deps;
                   27625:     }
                   27626: 
                   27627:     function hasDeps()
                   27628:     {
                   27629:         return isset($this->_packageInfo['release_deps']) &&
                   27630:             count($this->_packageInfo['release_deps']);
                   27631:     }
                   27632: 
                   27633:     function getDependencyGroup($group)
                   27634:     {
                   27635:         return false;
                   27636:     }
                   27637: 
                   27638:     function isCompatible($pf)
                   27639:     {
                   27640:         return false;
                   27641:     }
                   27642: 
                   27643:     function isSubpackageOf($p)
                   27644:     {
                   27645:         return $p->isSubpackage($this);
                   27646:     }
                   27647: 
                   27648:     function isSubpackage($p)
                   27649:     {
                   27650:         return false;
                   27651:     }
                   27652: 
                   27653:     function dependsOn($package, $channel)
                   27654:     {
                   27655:         if (strtolower($channel) != 'pear.php.net') {
                   27656:             return false;
                   27657:         }
                   27658:         if (!($deps = $this->getDeps())) {
                   27659:             return false;
                   27660:         }
                   27661:         foreach ($deps as $dep) {
                   27662:             if ($dep['type'] != 'pkg') {
                   27663:                 continue;
                   27664:             }
                   27665:             if (strtolower($dep['name']) == strtolower($package)) {
                   27666:                 return true;
                   27667:             }
                   27668:         }
                   27669:         return false;
                   27670:     }
                   27671: 
                   27672:     function getConfigureOptions()
                   27673:     {
                   27674:         if (isset($this->_packageInfo['configure_options'])) {
                   27675:             return $this->_packageInfo['configure_options'];
                   27676:         }
                   27677:         return false;
                   27678:     }
                   27679: 
                   27680:     function hasConfigureOptions()
                   27681:     {
                   27682:         return isset($this->_packageInfo['configure_options']) &&
                   27683:             count($this->_packageInfo['configure_options']);
                   27684:     }
                   27685: 
                   27686:     function addConfigureOption($name, $prompt, $default = false)
                   27687:     {
                   27688:         $o = array('name' => $name, 'prompt' => $prompt);
                   27689:         if ($default !== false) {
                   27690:             $o['default'] = $default;
                   27691:         }
                   27692:         if (!isset($this->_packageInfo['configure_options'])) {
                   27693:             $this->_packageInfo['configure_options'] = array();
                   27694:         }
                   27695:         $this->_packageInfo['configure_options'][] = $o;
                   27696:     }
                   27697: 
                   27698:     function clearConfigureOptions()
                   27699:     {
                   27700:         unset($this->_packageInfo['configure_options']);
                   27701:     }
                   27702: 
                   27703:     function getProvides()
                   27704:     {
                   27705:         if (isset($this->_packageInfo['provides'])) {
                   27706:             return $this->_packageInfo['provides'];
                   27707:         }
                   27708:         return false;
                   27709:     }
                   27710: 
                   27711:     function getProvidesExtension()
                   27712:     {
                   27713:         return false;
                   27714:     }
                   27715: 
                   27716:     function addFile($dir, $file, $attrs)
                   27717:     {
                   27718:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
                   27719:         if ($dir == '/' || $dir == '') {
                   27720:             $dir = '';
                   27721:         } else {
                   27722:             $dir .= '/';
                   27723:         }
                   27724:         $file = $dir . $file;
                   27725:         $file = preg_replace('![\\/]+!', '/', $file);
                   27726:         $this->_packageInfo['filelist'][$file] = $attrs;
                   27727:     }
                   27728: 
                   27729:     function getInstallationFilelist()
                   27730:     {
                   27731:         return $this->getFilelist();
                   27732:     }
                   27733: 
                   27734:     function getFilelist()
                   27735:     {
                   27736:         if (isset($this->_packageInfo['filelist'])) {
                   27737:             return $this->_packageInfo['filelist'];
                   27738:         }
                   27739:         return false;
                   27740:     }
                   27741: 
                   27742:     function setFileAttribute($file, $attr, $value)
                   27743:     {
                   27744:         $this->_packageInfo['filelist'][$file][$attr] = $value;
                   27745:     }
                   27746: 
                   27747:     function resetFilelist()
                   27748:     {
                   27749:         $this->_packageInfo['filelist'] = array();
                   27750:     }
                   27751: 
                   27752:     function setInstalledAs($file, $path)
                   27753:     {
                   27754:         if ($path) {
                   27755:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   27756:         }
                   27757:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   27758:     }
                   27759: 
                   27760:     function installedFile($file, $atts)
                   27761:     {
                   27762:         if (isset($this->_packageInfo['filelist'][$file])) {
                   27763:             $this->_packageInfo['filelist'][$file] =
                   27764:                 array_merge($this->_packageInfo['filelist'][$file], $atts);
                   27765:         } else {
                   27766:             $this->_packageInfo['filelist'][$file] = $atts;
                   27767:         }
                   27768:     }
                   27769: 
                   27770:     function getChangelog()
                   27771:     {
                   27772:         if (isset($this->_packageInfo['changelog'])) {
                   27773:             return $this->_packageInfo['changelog'];
                   27774:         }
                   27775:         return false;
                   27776:     }
                   27777: 
                   27778:     function getPackagexmlVersion()
                   27779:     {
                   27780:         return '1.0';
                   27781:     }
                   27782: 
                   27783:     /**
                   27784:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   27785:      * @param boolean determines whether to purge the error stack after retrieving
                   27786:      * @return array
                   27787:      */
                   27788:     function getValidationWarnings($purge = true)
                   27789:     {
                   27790:         return $this->_stack->getErrors($purge);
                   27791:     }
                   27792: 
                   27793:     // }}}
                   27794:     /**
                   27795:      * Validation error.  Also marks the object contents as invalid
                   27796:      * @param error code
                   27797:      * @param array error information
                   27798:      * @access private
                   27799:      */
                   27800:     function _validateError($code, $params = array())
                   27801:     {
                   27802:         $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
                   27803:         $this->_isValid = false;
                   27804:     }
                   27805: 
                   27806:     /**
                   27807:      * Validation warning.  Does not mark the object contents invalid.
                   27808:      * @param error code
                   27809:      * @param array error information
                   27810:      * @access private
                   27811:      */
                   27812:     function _validateWarning($code, $params = array())
                   27813:     {
                   27814:         $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
                   27815:     }
                   27816: 
                   27817:     /**
                   27818:      * @param integer error code
                   27819:      * @access protected
                   27820:      */
                   27821:     function _getErrorMessage()
                   27822:     {
                   27823:         return array(
                   27824:                 PEAR_PACKAGEFILE_ERROR_NO_NAME =>
                   27825:                     'Missing Package Name',
                   27826:                 PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
                   27827:                     'No summary found',
                   27828:                 PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
                   27829:                     'Summary should be on one line',
                   27830:                 PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
                   27831:                     'Missing description',
                   27832:                 PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
                   27833:                     'Missing license',
                   27834:                 PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
                   27835:                     'No release version found',
                   27836:                 PEAR_PACKAGEFILE_ERROR_NO_STATE =>
                   27837:                     'No release state found',
                   27838:                 PEAR_PACKAGEFILE_ERROR_NO_DATE =>
                   27839:                     'No release date found',
                   27840:                 PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
                   27841:                     'No release notes found',
                   27842:                 PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
                   27843:                     'Package must have at least one lead maintainer',
                   27844:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
                   27845:                     'No maintainers found, at least one must be defined',
                   27846:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
                   27847:                     'Maintainer %index% has no handle (user ID at channel server)',
                   27848:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
                   27849:                     'Maintainer %index% has no role',
                   27850:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
                   27851:                     'Maintainer %index% has no name',
                   27852:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
                   27853:                     'Maintainer %index% has no email',
                   27854:                 PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
                   27855:                     'Dependency %index% is not a php dependency, and has no name',
                   27856:                 PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
                   27857:                     'Dependency %index% has no relation (rel)',
                   27858:                 PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
                   27859:                     'Dependency %index% has no type',
                   27860:                 PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
                   27861:                     'PHP Dependency %index% has a name attribute of "%name%" which will be' .
                   27862:                         ' ignored!',
                   27863:                 PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
                   27864:                     'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
                   27865:                         'and has no version',
                   27866:                 PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
                   27867:                     'Dependency %index% is a type="php" dependency, ' .
                   27868:                         'and has no version',
                   27869:                 PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
                   27870:                     'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
                   27871:                 PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
                   27872:                     'Dependency %index% has invalid optional value "%opt%", should be yes or no',
                   27873:                 PEAR_PACKAGEFILE_PHP_NO_NOT =>
                   27874:                     'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
                   27875:                         ' to exclude specific versions',
                   27876:                 PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
                   27877:                     'Configure Option %index% has no name',
                   27878:                 PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
                   27879:                     'Configure Option %index% has no prompt',
                   27880:                 PEAR_PACKAGEFILE_ERROR_NO_FILES =>
                   27881:                     'No files in <filelist> section of package.xml',
                   27882:                 PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
                   27883:                     'File "%file%" has no role, expecting one of "%roles%"',
                   27884:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
                   27885:                     'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
                   27886:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
                   27887:                     'File "%file%" cannot start with ".", cannot package or install',
                   27888:                 PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
                   27889:                     'Parser error: invalid PHP found in file "%file%"',
                   27890:                 PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
                   27891:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"',
                   27892:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
                   27893:                     'Parser error: invalid PHP file "%file%"',
                   27894:                 PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
                   27895:                     'Channel validator error: field "%field%" - %reason%',
                   27896:                 PEAR_PACKAGEFILE_ERROR_PHP5 =>
                   27897:                     'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
                   27898:                 PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
                   27899:                     'File "%file%" in package.xml does not exist',
                   27900:                 PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
                   27901:                     'Package.xml contains non-ISO-8859-1 characters, and may not validate',
                   27902:             );
                   27903:     }
                   27904: 
                   27905:     /**
                   27906:      * Validate XML package definition file.
                   27907:      *
                   27908:      * @access public
                   27909:      * @return boolean
                   27910:      */
                   27911:     function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
                   27912:     {
                   27913:         if (($this->_isValid & $state) == $state) {
                   27914:             return true;
                   27915:         }
                   27916:         $this->_isValid = true;
                   27917:         $info = $this->_packageInfo;
                   27918:         if (empty($info['package'])) {
                   27919:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
                   27920:             $this->_packageName = $pn = 'unknown';
                   27921:         } else {
                   27922:             $this->_packageName = $pn = $info['package'];
                   27923:         }
                   27924: 
                   27925:         if (empty($info['summary'])) {
                   27926:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
                   27927:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   27928:             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
                   27929:                 array('summary' => $info['summary']));
                   27930:         }
                   27931:         if (empty($info['description'])) {
                   27932:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
                   27933:         }
                   27934:         if (empty($info['release_license'])) {
                   27935:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
                   27936:         }
                   27937:         if (empty($info['version'])) {
                   27938:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
                   27939:         }
                   27940:         if (empty($info['release_state'])) {
                   27941:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
                   27942:         }
                   27943:         if (empty($info['release_date'])) {
                   27944:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
                   27945:         }
                   27946:         if (empty($info['release_notes'])) {
                   27947:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
                   27948:         }
                   27949:         if (empty($info['maintainers'])) {
                   27950:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
                   27951:         } else {
                   27952:             $haslead = false;
                   27953:             $i = 1;
                   27954:             foreach ($info['maintainers'] as $m) {
                   27955:                 if (empty($m['handle'])) {
                   27956:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
                   27957:                         array('index' => $i));
                   27958:                 }
                   27959:                 if (empty($m['role'])) {
                   27960:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
                   27961:                         array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
                   27962:                 } elseif ($m['role'] == 'lead') {
                   27963:                     $haslead = true;
                   27964:                 }
                   27965:                 if (empty($m['name'])) {
                   27966:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
                   27967:                         array('index' => $i));
                   27968:                 }
                   27969:                 if (empty($m['email'])) {
                   27970:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
                   27971:                         array('index' => $i));
                   27972:                 }
                   27973:                 $i++;
                   27974:             }
                   27975:             if (!$haslead) {
                   27976:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
                   27977:             }
                   27978:         }
                   27979:         if (!empty($info['release_deps'])) {
                   27980:             $i = 1;
                   27981:             foreach ($info['release_deps'] as $d) {
                   27982:                 if (!isset($d['type']) || empty($d['type'])) {
                   27983:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
                   27984:                         array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
                   27985:                     continue;
                   27986:                 }
                   27987:                 if (!isset($d['rel']) || empty($d['rel'])) {
                   27988:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
                   27989:                         array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
                   27990:                     continue;
                   27991:                 }
                   27992:                 if (!empty($d['optional'])) {
                   27993:                     if (!in_array($d['optional'], array('yes', 'no'))) {
                   27994:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
                   27995:                             array('index' => $i, 'opt' => $d['optional']));
                   27996:                     }
                   27997:                 }
                   27998:                 if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
                   27999:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
                   28000:                         array('index' => $i));
                   28001:                 } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
                   28002:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
                   28003:                         array('index' => $i, 'rel' => $d['rel']));
                   28004:                 }
                   28005:                 if ($d['type'] == 'php' && !empty($d['name'])) {
                   28006:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
                   28007:                         array('index' => $i, 'name' => $d['name']));
                   28008:                 } elseif ($d['type'] != 'php' && empty($d['name'])) {
                   28009:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
                   28010:                         array('index' => $i));
                   28011:                 }
                   28012:                 if ($d['type'] == 'php' && empty($d['version'])) {
                   28013:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
                   28014:                         array('index' => $i));
                   28015:                 }
                   28016:                 if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
                   28017:                     $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
                   28018:                         array('index' => $i));
                   28019:                 }
                   28020:                 $i++;
                   28021:             }
                   28022:         }
                   28023:         if (!empty($info['configure_options'])) {
                   28024:             $i = 1;
                   28025:             foreach ($info['configure_options'] as $c) {
                   28026:                 if (empty($c['name'])) {
                   28027:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
                   28028:                         array('index' => $i));
                   28029:                 }
                   28030:                 if (empty($c['prompt'])) {
                   28031:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
                   28032:                         array('index' => $i));
                   28033:                 }
                   28034:                 $i++;
                   28035:             }
                   28036:         }
                   28037:         if (empty($info['filelist'])) {
                   28038:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
                   28039:             $errors[] = 'no files';
                   28040:         } else {
                   28041:             foreach ($info['filelist'] as $file => $fa) {
                   28042:                 if (empty($fa['role'])) {
                   28043:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
                   28044:                         array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
                   28045:                     continue;
                   28046:                 } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
                   28047:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
                   28048:                         array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
                   28049:                 }
                   28050:                 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
                   28051:                     // file contains .. parent directory or . cur directory references
                   28052:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28053:                         array('file' => $file));
                   28054:                 }
                   28055:                 if (isset($fa['install-as']) &&
                   28056:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                   28057:                                  str_replace('\\', '/', $fa['install-as']))) {
                   28058:                     // install-as contains .. parent directory or . cur directory references
                   28059:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28060:                         array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
                   28061:                 }
                   28062:                 if (isset($fa['baseinstalldir']) &&
                   28063:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                   28064:                                  str_replace('\\', '/', $fa['baseinstalldir']))) {
                   28065:                     // install-as contains .. parent directory or . cur directory references
                   28066:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28067:                         array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
                   28068:                 }
                   28069:             }
                   28070:         }
                   28071:         if (isset($this->_registry) && $this->_isValid) {
                   28072:             $chan = $this->_registry->getChannel('pear.php.net');
                   28073:             if (PEAR::isError($chan)) {
                   28074:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
                   28075:                 return $this->_isValid = 0;
                   28076:             }
                   28077:             $validator = $chan->getValidationObject();
                   28078:             $validator->setPackageFile($this);
                   28079:             $validator->validate($state);
                   28080:             $failures = $validator->getFailures();
                   28081:             foreach ($failures['errors'] as $error) {
                   28082:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
                   28083:             }
                   28084:             foreach ($failures['warnings'] as $warning) {
                   28085:                 $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
                   28086:             }
                   28087:         }
                   28088:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
                   28089:             if ($this->_analyzePhpFiles()) {
                   28090:                 $this->_isValid = true;
                   28091:             }
                   28092:         }
                   28093:         if ($this->_isValid) {
                   28094:             return $this->_isValid = $state;
                   28095:         }
                   28096:         return $this->_isValid = 0;
                   28097:     }
                   28098: 
                   28099:     function _analyzePhpFiles()
                   28100:     {
                   28101:         if (!$this->_isValid) {
                   28102:             return false;
                   28103:         }
                   28104:         if (!isset($this->_packageFile)) {
                   28105:             return false;
                   28106:         }
                   28107:         $dir_prefix = dirname($this->_packageFile);
                   28108:         $common = new PEAR_Common;
                   28109:         $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
                   28110:             array($common, 'log');
                   28111:         $info = $this->getFilelist();
                   28112:         foreach ($info as $file => $fa) {
                   28113:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   28114:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
                   28115:                     array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
                   28116:                 continue;
                   28117:             }
                   28118:             if ($fa['role'] == 'php' && $dir_prefix) {
                   28119:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   28120:                 $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   28121:                 if ($srcinfo) {
                   28122:                     $this->_buildProvidesArray($srcinfo);
                   28123:                 }
                   28124:             }
                   28125:         }
                   28126:         $this->_packageName = $pn = $this->getPackage();
                   28127:         $pnl = strlen($pn);
                   28128:         if (isset($this->_packageInfo['provides'])) {
                   28129:             foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
                   28130:                 if (isset($what['explicit'])) {
                   28131:                     // skip conformance checks if the provides entry is
                   28132:                     // specified in the package.xml file
                   28133:                     continue;
                   28134:                 }
                   28135:                 extract($what);
                   28136:                 if ($type == 'class') {
                   28137:                     if (!strncasecmp($name, $pn, $pnl)) {
                   28138:                         continue;
                   28139:                     }
                   28140:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   28141:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   28142:                 } elseif ($type == 'function') {
                   28143:                     if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   28144:                         continue;
                   28145:                     }
                   28146:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   28147:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   28148:                 }
                   28149:             }
                   28150:         }
                   28151:         return $this->_isValid;
                   28152:     }
                   28153: 
                   28154:     /**
                   28155:      * Get the default xml generator object
                   28156:      *
                   28157:      * @return PEAR_PackageFile_Generator_v1
                   28158:      */
                   28159:     function &getDefaultGenerator()
                   28160:     {
                   28161:         if (!class_exists('PEAR_PackageFile_Generator_v1')) {
                   28162:             require_once 'PEAR/PackageFile/Generator/v1.php';
                   28163:         }
                   28164:         $a = &new PEAR_PackageFile_Generator_v1($this);
                   28165:         return $a;
                   28166:     }
                   28167: 
                   28168:     /**
                   28169:      * Get the contents of a file listed within the package.xml
                   28170:      * @param string
                   28171:      * @return string
                   28172:      */
                   28173:     function getFileContents($file)
                   28174:     {
                   28175:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   28176:             $dir = dirname($this->_packageFile);
                   28177:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   28178:             $file = str_replace(array('/', '\\'),
                   28179:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   28180:             if (file_exists($file) && is_readable($file)) {
                   28181:                 return implode('', file($file));
                   28182:             }
                   28183:         } else { // tgz
                   28184:             if (!class_exists('Archive_Tar')) {
                   28185:                 require_once 'Archive/Tar.php';
                   28186:             }
                   28187:             $tar = &new Archive_Tar($this->_archiveFile);
                   28188:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   28189:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   28190:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   28191:             }
                   28192:             $file = $tar->extractInString($file);
                   28193:             $tar->popErrorHandling();
                   28194:             if (PEAR::isError($file)) {
                   28195:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   28196:             }
                   28197:             return $file;
                   28198:         }
                   28199:     }
                   28200: 
                   28201:     // {{{ analyzeSourceCode()
                   28202:     /**
                   28203:      * Analyze the source code of the given PHP file
                   28204:      *
                   28205:      * @param  string Filename of the PHP file
                   28206:      * @return mixed
                   28207:      * @access private
                   28208:      */
                   28209:     function _analyzeSourceCode($file)
                   28210:     {
                   28211:         if (!function_exists("token_get_all")) {
                   28212:             return false;
                   28213:         }
                   28214:         if (!defined('T_DOC_COMMENT')) {
                   28215:             define('T_DOC_COMMENT', T_COMMENT);
                   28216:         }
                   28217:         if (!defined('T_INTERFACE')) {
                   28218:             define('T_INTERFACE', -1);
                   28219:         }
                   28220:         if (!defined('T_IMPLEMENTS')) {
                   28221:             define('T_IMPLEMENTS', -1);
                   28222:         }
                   28223:         if (!$fp = @fopen($file, "r")) {
                   28224:             return false;
                   28225:         }
                   28226:         fclose($fp);
                   28227:         $contents = file_get_contents($file);
                   28228:         $tokens = token_get_all($contents);
                   28229: /*
                   28230:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   28231:             @list($token, $data) = $tokens[$i];
                   28232:             if (is_string($token)) {
                   28233:                 var_dump($token);
                   28234:             } else {
                   28235:                 print token_name($token) . ' ';
                   28236:                 var_dump(rtrim($data));
                   28237:             }
                   28238:         }
                   28239: */
                   28240:         $look_for = 0;
                   28241:         $paren_level = 0;
                   28242:         $bracket_level = 0;
                   28243:         $brace_level = 0;
                   28244:         $lastphpdoc = '';
                   28245:         $current_class = '';
                   28246:         $current_interface = '';
                   28247:         $current_class_level = -1;
                   28248:         $current_function = '';
                   28249:         $current_function_level = -1;
                   28250:         $declared_classes = array();
                   28251:         $declared_interfaces = array();
                   28252:         $declared_functions = array();
                   28253:         $declared_methods = array();
                   28254:         $used_classes = array();
                   28255:         $used_functions = array();
                   28256:         $extends = array();
                   28257:         $implements = array();
                   28258:         $nodeps = array();
                   28259:         $inquote = false;
                   28260:         $interface = false;
                   28261:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   28262:             if (is_array($tokens[$i])) {
                   28263:                 list($token, $data) = $tokens[$i];
                   28264:             } else {
                   28265:                 $token = $tokens[$i];
                   28266:                 $data = '';
                   28267:             }
                   28268:             if ($inquote) {
                   28269:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   28270:                     continue;
                   28271:                 } else {
                   28272:                     $inquote = false;
                   28273:                     continue;
                   28274:                 }
                   28275:             }
                   28276:             switch ($token) {
                   28277:                 case T_WHITESPACE :
                   28278:                     continue;
                   28279:                 case ';':
                   28280:                     if ($interface) {
                   28281:                         $current_function = '';
                   28282:                         $current_function_level = -1;
                   28283:                     }
                   28284:                     break;
                   28285:                 case '"':
                   28286:                 case T_START_HEREDOC:
                   28287:                     $inquote = true;
                   28288:                     break;
                   28289:                 case T_CURLY_OPEN:
                   28290:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   28291:                 case '{': $brace_level++; continue 2;
                   28292:                 case '}':
                   28293:                     $brace_level--;
                   28294:                     if ($current_class_level == $brace_level) {
                   28295:                         $current_class = '';
                   28296:                         $current_class_level = -1;
                   28297:                     }
                   28298:                     if ($current_function_level == $brace_level) {
                   28299:                         $current_function = '';
                   28300:                         $current_function_level = -1;
                   28301:                     }
                   28302:                     continue 2;
                   28303:                 case '[': $bracket_level++; continue 2;
                   28304:                 case ']': $bracket_level--; continue 2;
                   28305:                 case '(': $paren_level++;   continue 2;
                   28306:                 case ')': $paren_level--;   continue 2;
                   28307:                 case T_INTERFACE:
                   28308:                     $interface = true;
                   28309:                 case T_CLASS:
                   28310:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   28311:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   28312:                             array('file' => $file));
                   28313:                         return false;
                   28314:                     }
                   28315:                 case T_FUNCTION:
                   28316:                 case T_NEW:
                   28317:                 case T_EXTENDS:
                   28318:                 case T_IMPLEMENTS:
                   28319:                     $look_for = $token;
                   28320:                     continue 2;
                   28321:                 case T_STRING:
                   28322:                     if (version_compare(zend_version(), '2.0', '<')) {
                   28323:                         if (in_array(strtolower($data),
                   28324:                             array('public', 'private', 'protected', 'abstract',
                   28325:                                   'interface', 'implements', 'throw') 
                   28326:                                  )) {
                   28327:                             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
                   28328:                                 array($file));
                   28329:                         }
                   28330:                     }
                   28331:                     if ($look_for == T_CLASS) {
                   28332:                         $current_class = $data;
                   28333:                         $current_class_level = $brace_level;
                   28334:                         $declared_classes[] = $current_class;
                   28335:                     } elseif ($look_for == T_INTERFACE) {
                   28336:                         $current_interface = $data;
                   28337:                         $current_class_level = $brace_level;
                   28338:                         $declared_interfaces[] = $current_interface;
                   28339:                     } elseif ($look_for == T_IMPLEMENTS) {
                   28340:                         $implements[$current_class] = $data;
                   28341:                     } elseif ($look_for == T_EXTENDS) {
                   28342:                         $extends[$current_class] = $data;
                   28343:                     } elseif ($look_for == T_FUNCTION) {
                   28344:                         if ($current_class) {
                   28345:                             $current_function = "$current_class::$data";
                   28346:                             $declared_methods[$current_class][] = $data;
                   28347:                         } elseif ($current_interface) {
                   28348:                             $current_function = "$current_interface::$data";
                   28349:                             $declared_methods[$current_interface][] = $data;
                   28350:                         } else {
                   28351:                             $current_function = $data;
                   28352:                             $declared_functions[] = $current_function;
                   28353:                         }
                   28354:                         $current_function_level = $brace_level;
                   28355:                         $m = array();
                   28356:                     } elseif ($look_for == T_NEW) {
                   28357:                         $used_classes[$data] = true;
                   28358:                     }
                   28359:                     $look_for = 0;
                   28360:                     continue 2;
                   28361:                 case T_VARIABLE:
                   28362:                     $look_for = 0;
                   28363:                     continue 2;
                   28364:                 case T_DOC_COMMENT:
                   28365:                 case T_COMMENT:
                   28366:                     if (preg_match('!^/\*\*\s!', $data)) {
                   28367:                         $lastphpdoc = $data;
                   28368:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   28369:                             $nodeps = array_merge($nodeps, $m[1]);
                   28370:                         }
                   28371:                     }
                   28372:                     continue 2;
                   28373:                 case T_DOUBLE_COLON:
                   28374:                     if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
                   28375:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   28376:                             array('file' => $file));
                   28377:                         return false;
                   28378:                     }
                   28379:                     $class = $tokens[$i - 1][1];
                   28380:                     if (strtolower($class) != 'parent') {
                   28381:                         $used_classes[$class] = true;
                   28382:                     }
                   28383:                     continue 2;
                   28384:             }
                   28385:         }
                   28386:         return array(
                   28387:             "source_file" => $file,
                   28388:             "declared_classes" => $declared_classes,
                   28389:             "declared_interfaces" => $declared_interfaces,
                   28390:             "declared_methods" => $declared_methods,
                   28391:             "declared_functions" => $declared_functions,
                   28392:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   28393:             "inheritance" => $extends,
                   28394:             "implements" => $implements,
                   28395:             );
                   28396:     }
                   28397: 
                   28398:     /**
                   28399:      * Build a "provides" array from data returned by
                   28400:      * analyzeSourceCode().  The format of the built array is like
                   28401:      * this:
                   28402:      *
                   28403:      *  array(
                   28404:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   28405:      *    ...
                   28406:      *  )
                   28407:      *
                   28408:      *
                   28409:      * @param array $srcinfo array with information about a source file
                   28410:      * as returned by the analyzeSourceCode() method.
                   28411:      *
                   28412:      * @return void
                   28413:      *
                   28414:      * @access private
                   28415:      *
                   28416:      */
                   28417:     function _buildProvidesArray($srcinfo)
                   28418:     {
                   28419:         if (!$this->_isValid) {
                   28420:             return false;
                   28421:         }
                   28422:         $file = basename($srcinfo['source_file']);
                   28423:         $pn = $this->getPackage();
                   28424:         $pnl = strlen($pn);
                   28425:         foreach ($srcinfo['declared_classes'] as $class) {
                   28426:             $key = "class;$class";
                   28427:             if (isset($this->_packageInfo['provides'][$key])) {
                   28428:                 continue;
                   28429:             }
                   28430:             $this->_packageInfo['provides'][$key] =
                   28431:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   28432:             if (isset($srcinfo['inheritance'][$class])) {
                   28433:                 $this->_packageInfo['provides'][$key]['extends'] =
                   28434:                     $srcinfo['inheritance'][$class];
                   28435:             }
                   28436:         }
                   28437:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   28438:             foreach ($methods as $method) {
                   28439:                 $function = "$class::$method";
                   28440:                 $key = "function;$function";
                   28441:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   28442:                     isset($this->_packageInfo['provides'][$key])) {
                   28443:                     continue;
                   28444:                 }
                   28445:                 $this->_packageInfo['provides'][$key] =
                   28446:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   28447:             }
                   28448:         }
                   28449: 
                   28450:         foreach ($srcinfo['declared_functions'] as $function) {
                   28451:             $key = "function;$function";
                   28452:             if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
                   28453:                 continue;
                   28454:             }
                   28455:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   28456:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   28457:             }
                   28458:             $this->_packageInfo['provides'][$key] =
                   28459:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   28460:         }
                   28461:     }
                   28462: 
                   28463:     // }}}
                   28464: }
                   28465: ?>
                   28466: PEAR-1.9.4/PEAR/PackageFile/v2.php0000644000076500000240000021011311605156760015156 0ustar  helgistaff<?php
                   28467: /**
                   28468:  * PEAR_PackageFile_v2, package.xml version 2.0
                   28469:  *
                   28470:  * PHP versions 4 and 5
                   28471:  *
                   28472:  * @category   pear
                   28473:  * @package    PEAR
                   28474:  * @author     Greg Beaver <cellog@php.net>
                   28475:  * @copyright  1997-2009 The Authors
                   28476:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   28477:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   28478:  * @link       http://pear.php.net/package/PEAR
                   28479:  * @since      File available since Release 1.4.0a1
                   28480:  */
                   28481: /**
                   28482:  * For error handling
                   28483:  */
                   28484: require_once 'PEAR/ErrorStack.php';
                   28485: /**
                   28486:  * @category   pear
                   28487:  * @package    PEAR
                   28488:  * @author     Greg Beaver <cellog@php.net>
                   28489:  * @copyright  1997-2009 The Authors
                   28490:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   28491:  * @version    Release: 1.9.4
                   28492:  * @link       http://pear.php.net/package/PEAR
                   28493:  * @since      Class available since Release 1.4.0a1
                   28494:  */
                   28495: class PEAR_PackageFile_v2
                   28496: {
                   28497: 
                   28498:     /**
                   28499:      * Parsed package information
                   28500:      * @var array
                   28501:      * @access private
                   28502:      */
                   28503:     var $_packageInfo = array();
                   28504: 
                   28505:     /**
                   28506:      * path to package .tgz or false if this is a local/extracted package.xml
                   28507:      * @var string|false
                   28508:      * @access private
                   28509:      */
                   28510:     var $_archiveFile;
                   28511: 
                   28512:     /**
                   28513:      * path to package .xml or false if this is an abstract parsed-from-string xml
                   28514:      * @var string|false
                   28515:      * @access private
                   28516:      */
                   28517:     var $_packageFile;
                   28518: 
                   28519:     /**
                   28520:      * This is used by file analysis routines to log progress information
                   28521:      * @var PEAR_Common
                   28522:      * @access protected
                   28523:      */
                   28524:     var $_logger;
                   28525: 
                   28526:     /**
                   28527:      * This is set to the highest validation level that has been validated
                   28528:      *
                   28529:      * If the package.xml is invalid or unknown, this is set to 0.  If
                   28530:      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
                   28531:      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
                   28532:      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
                   28533:      * "caching" to occur, which is particularly important for package validation, so
                   28534:      * that PHP files are not validated twice
                   28535:      * @var int
                   28536:      * @access private
                   28537:      */
                   28538:     var $_isValid = 0;
                   28539: 
                   28540:     /**
                   28541:      * True if the filelist has been validated
                   28542:      * @param bool
                   28543:      */
                   28544:     var $_filesValid = false;
                   28545: 
                   28546:     /**
                   28547:      * @var PEAR_Registry
                   28548:      * @access protected
                   28549:      */
                   28550:     var $_registry;
                   28551: 
                   28552:     /**
                   28553:      * @var PEAR_Config
                   28554:      * @access protected
                   28555:      */
                   28556:     var $_config;
                   28557: 
                   28558:     /**
                   28559:      * Optional Dependency group requested for installation
                   28560:      * @var string
                   28561:      * @access private
                   28562:      */
                   28563:     var $_requestedGroup = false;
                   28564: 
                   28565:     /**
                   28566:      * @var PEAR_ErrorStack
                   28567:      * @access protected
                   28568:      */
                   28569:     var $_stack;
                   28570: 
                   28571:     /**
                   28572:      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
                   28573:      */
                   28574:     var $_tasksNs;
                   28575: 
                   28576:     /**
                   28577:      * Determines whether this packagefile was initialized only with partial package info
                   28578:      *
                   28579:      * If this package file was constructed via parsing REST, it will only contain
                   28580:      *
                   28581:      * - package name
                   28582:      * - channel name
                   28583:      * - dependencies
                   28584:      * @var boolean
                   28585:      * @access private
                   28586:      */
                   28587:     var $_incomplete = true;
                   28588: 
                   28589:     /**
                   28590:      * @var PEAR_PackageFile_v2_Validator
                   28591:      */
                   28592:     var $_v2Validator;
                   28593: 
                   28594:     /**
                   28595:      * The constructor merely sets up the private error stack
                   28596:      */
                   28597:     function PEAR_PackageFile_v2()
                   28598:     {
                   28599:         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
                   28600:         $this->_isValid = false;
                   28601:     }
                   28602: 
                   28603:     /**
                   28604:      * To make unit-testing easier
                   28605:      * @param PEAR_Frontend_*
                   28606:      * @param array options
                   28607:      * @param PEAR_Config
                   28608:      * @return PEAR_Downloader
                   28609:      * @access protected
                   28610:      */
                   28611:     function &getPEARDownloader(&$i, $o, &$c)
                   28612:     {
                   28613:         $z = &new PEAR_Downloader($i, $o, $c);
                   28614:         return $z;
                   28615:     }
                   28616: 
                   28617:     /**
                   28618:      * To make unit-testing easier
                   28619:      * @param PEAR_Config
                   28620:      * @param array options
                   28621:      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
                   28622:      * @param int PEAR_VALIDATE_* constant
                   28623:      * @return PEAR_Dependency2
                   28624:      * @access protected
                   28625:      */
                   28626:     function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
                   28627:     {
                   28628:         if (!class_exists('PEAR_Dependency2')) {
                   28629:             require_once 'PEAR/Dependency2.php';
                   28630:         }
                   28631:         $z = &new PEAR_Dependency2($c, $o, $p, $s);
                   28632:         return $z;
                   28633:     }
                   28634: 
                   28635:     function getInstalledBinary()
                   28636:     {
                   28637:         return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
                   28638:             false;
                   28639:     }
                   28640: 
                   28641:     /**
                   28642:      * Installation of source package has failed, attempt to download and install the
                   28643:      * binary version of this package.
                   28644:      * @param PEAR_Installer
                   28645:      * @return array|false
                   28646:      */
                   28647:     function installBinary(&$installer)
                   28648:     {
                   28649:         if (!OS_WINDOWS) {
                   28650:             $a = false;
                   28651:             return $a;
                   28652:         }
                   28653:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   28654:             $releasetype = $this->getPackageType() . 'release';
                   28655:             if (!is_array($installer->getInstallPackages())) {
                   28656:                 $a = false;
                   28657:                 return $a;
                   28658:             }
                   28659:             foreach ($installer->getInstallPackages() as $p) {
                   28660:                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
                   28661:                     if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
                   28662:                         $a = false;
                   28663:                         return $a; // the user probably downloaded it separately
                   28664:                     }
                   28665:                 }
                   28666:             }
                   28667:             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
                   28668:                 $installer->log(0, 'Attempting to download binary version of extension "' .
                   28669:                     $this->_packageInfo['providesextension'] . '"');
                   28670:                 $params = $this->_packageInfo[$releasetype]['binarypackage'];
                   28671:                 if (!is_array($params) || !isset($params[0])) {
                   28672:                     $params = array($params);
                   28673:                 }
                   28674:                 if (isset($this->_packageInfo['channel'])) {
                   28675:                     foreach ($params as $i => $param) {
                   28676:                         $params[$i] = array('channel' => $this->_packageInfo['channel'],
                   28677:                             'package' => $param, 'version' => $this->getVersion());
                   28678:                     }
                   28679:                 }
                   28680:                 $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
                   28681:                     $installer->config);
                   28682:                 $verbose = $dl->config->get('verbose');
                   28683:                 $dl->config->set('verbose', -1);
                   28684:                 foreach ($params as $param) {
                   28685:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   28686:                     $ret = $dl->download(array($param));
                   28687:                     PEAR::popErrorHandling();
                   28688:                     if (is_array($ret) && count($ret)) {
                   28689:                         break;
                   28690:                     }
                   28691:                 }
                   28692:                 $dl->config->set('verbose', $verbose);
                   28693:                 if (is_array($ret)) {
                   28694:                     if (count($ret) == 1) {
                   28695:                         $pf = $ret[0]->getPackageFile();
                   28696:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   28697:                         $err = $installer->install($ret[0]);
                   28698:                         PEAR::popErrorHandling();
                   28699:                         if (is_array($err)) {
                   28700:                             $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
                   28701:                             // "install" self, so all dependencies will work transparently
                   28702:                             $this->_registry->addPackage2($this);
                   28703:                             $installer->log(0, 'Download and install of binary extension "' .
                   28704:                                 $this->_registry->parsedPackageNameToString(
                   28705:                                     array('channel' => $pf->getChannel(),
                   28706:                                           'package' => $pf->getPackage()), true) . '" successful');
                   28707:                             $a = array($ret[0], $err);
                   28708:                             return $a;
                   28709:                         }
                   28710:                         $installer->log(0, 'Download and install of binary extension "' .
                   28711:                             $this->_registry->parsedPackageNameToString(
                   28712:                                     array('channel' => $pf->getChannel(),
                   28713:                                           'package' => $pf->getPackage()), true) . '" failed');
                   28714:                     }
                   28715:                 }
                   28716:             }
                   28717:         }
                   28718:         $a = false;
                   28719:         return $a;
                   28720:     }
                   28721: 
                   28722:     /**
                   28723:      * @return string|false Extension name
                   28724:      */
                   28725:     function getProvidesExtension()
                   28726:     {
                   28727:         if (in_array($this->getPackageType(),
                   28728:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   28729:             if (isset($this->_packageInfo['providesextension'])) {
                   28730:                 return $this->_packageInfo['providesextension'];
                   28731:             }
                   28732:         }
                   28733:         return false;
                   28734:     }
                   28735: 
                   28736:     /**
                   28737:      * @param string Extension name
                   28738:      * @return bool
                   28739:      */
                   28740:     function isExtension($extension)
                   28741:     {
                   28742:         if (in_array($this->getPackageType(),
                   28743:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   28744:             return $this->_packageInfo['providesextension'] == $extension;
                   28745:         }
                   28746:         return false;
                   28747:     }
                   28748: 
                   28749:     /**
                   28750:      * Tests whether every part of the package.xml 1.0 is represented in
                   28751:      * this package.xml 2.0
                   28752:      * @param PEAR_PackageFile_v1
                   28753:      * @return bool
                   28754:      */
                   28755:     function isEquivalent($pf1)
                   28756:     {
                   28757:         if (!$pf1) {
                   28758:             return true;
                   28759:         }
                   28760:         if ($this->getPackageType() == 'bundle') {
                   28761:             return false;
                   28762:         }
                   28763:         $this->_stack->getErrors(true);
                   28764:         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
                   28765:             return false;
                   28766:         }
                   28767:         $pass = true;
                   28768:         if ($pf1->getPackage() != $this->getPackage()) {
                   28769:             $this->_differentPackage($pf1->getPackage());
                   28770:             $pass = false;
                   28771:         }
                   28772:         if ($pf1->getVersion() != $this->getVersion()) {
                   28773:             $this->_differentVersion($pf1->getVersion());
                   28774:             $pass = false;
                   28775:         }
                   28776:         if (trim($pf1->getSummary()) != $this->getSummary()) {
                   28777:             $this->_differentSummary($pf1->getSummary());
                   28778:             $pass = false;
                   28779:         }
                   28780:         if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
                   28781:               preg_replace('/\s+/', '', $this->getDescription())) {
                   28782:             $this->_differentDescription($pf1->getDescription());
                   28783:             $pass = false;
                   28784:         }
                   28785:         if ($pf1->getState() != $this->getState()) {
                   28786:             $this->_differentState($pf1->getState());
                   28787:             $pass = false;
                   28788:         }
                   28789:         if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
                   28790:               preg_replace('/\s+/', '', $pf1->getNotes()))) {
                   28791:             $this->_differentNotes($pf1->getNotes());
                   28792:             $pass = false;
                   28793:         }
                   28794:         $mymaintainers = $this->getMaintainers();
                   28795:         $yourmaintainers = $pf1->getMaintainers();
                   28796:         for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
                   28797:             $reset = false;
                   28798:             for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
                   28799:                 if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
                   28800:                     if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
                   28801:                         $this->_differentRole($mymaintainers[$i2]['handle'],
                   28802:                             $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
                   28803:                         $pass = false;
                   28804:                     }
                   28805:                     if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
                   28806:                         $this->_differentEmail($mymaintainers[$i2]['handle'],
                   28807:                             $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
                   28808:                         $pass = false;
                   28809:                     }
                   28810:                     if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
                   28811:                         $this->_differentName($mymaintainers[$i2]['handle'],
                   28812:                             $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
                   28813:                         $pass = false;
                   28814:                     }
                   28815:                     unset($mymaintainers[$i2]);
                   28816:                     $mymaintainers = array_values($mymaintainers);
                   28817:                     unset($yourmaintainers[$i1]);
                   28818:                     $yourmaintainers = array_values($yourmaintainers);
                   28819:                     $reset = true;
                   28820:                     break;
                   28821:                 }
                   28822:             }
                   28823:             if ($reset) {
                   28824:                 $i1 = -1;
                   28825:             }
                   28826:         }
                   28827:         $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
                   28828:         $filelist = $this->getFilelist();
                   28829:         foreach ($pf1->getFilelist() as $file => $atts) {
                   28830:             if (!isset($filelist[$file])) {
                   28831:                 $this->_missingFile($file);
                   28832:                 $pass = false;
                   28833:             }
                   28834:         }
                   28835:         return $pass;
                   28836:     }
                   28837: 
                   28838:     function _differentPackage($package)
                   28839:     {
                   28840:         $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
                   28841:             'self' => $this->getPackage()),
                   28842:             'package.xml 1.0 package "%package%" does not match "%self%"');
                   28843:     }
                   28844: 
                   28845:     function _differentVersion($version)
                   28846:     {
                   28847:         $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
                   28848:             'self' => $this->getVersion()),
                   28849:             'package.xml 1.0 version "%version%" does not match "%self%"');
                   28850:     }
                   28851: 
                   28852:     function _differentState($state)
                   28853:     {
                   28854:         $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
                   28855:             'self' => $this->getState()),
                   28856:             'package.xml 1.0 state "%state%" does not match "%self%"');
                   28857:     }
                   28858: 
                   28859:     function _differentRole($handle, $role, $selfrole)
                   28860:     {
                   28861:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   28862:             'role' => $role, 'self' => $selfrole),
                   28863:             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
                   28864:     }
                   28865: 
                   28866:     function _differentEmail($handle, $email, $selfemail)
                   28867:     {
                   28868:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   28869:             'email' => $email, 'self' => $selfemail),
                   28870:             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
                   28871:     }
                   28872: 
                   28873:     function _differentName($handle, $name, $selfname)
                   28874:     {
                   28875:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   28876:             'name' => $name, 'self' => $selfname),
                   28877:             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
                   28878:     }
                   28879: 
                   28880:     function _unmatchedMaintainers($my, $yours)
                   28881:     {
                   28882:         if ($my) {
                   28883:             array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
                   28884:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
                   28885:                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
                   28886:         }
                   28887:         if ($yours) {
                   28888:             array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
                   28889:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
                   28890:                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
                   28891:         }
                   28892:     }
                   28893: 
                   28894:     function _differentNotes($notes)
                   28895:     {
                   28896:         $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
                   28897:         $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
                   28898:             substr($this->getNotes(), 0, 24) . '...';
                   28899:         $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
                   28900:             'self' => $truncmynotes),
                   28901:             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
                   28902:     }
                   28903: 
                   28904:     function _differentSummary($summary)
                   28905:     {
                   28906:         $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
                   28907:         $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
                   28908:             substr($this->getsummary(), 0, 24) . '...';
                   28909:         $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
                   28910:             'self' => $truncmysummary),
                   28911:             'package.xml 1.0 summary "%summary%" does not match "%self%"');
                   28912:     }
                   28913: 
                   28914:     function _differentDescription($description)
                   28915:     {
                   28916:         $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
                   28917:         $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
                   28918:             substr($this->getdescription(), 0, 24) . '...');
                   28919:         $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
                   28920:             'self' => $truncmydescription),
                   28921:             'package.xml 1.0 description "%description%" does not match "%self%"');
                   28922:     }
                   28923: 
                   28924:     function _missingFile($file)
                   28925:     {
                   28926:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   28927:             'package.xml 1.0 file "%file%" is not present in <contents>');
                   28928:     }
                   28929: 
                   28930:     /**
                   28931:      * WARNING - do not use this function unless you know what you're doing
                   28932:      */
                   28933:     function setRawState($state)
                   28934:     {
                   28935:         if (!isset($this->_packageInfo['stability'])) {
                   28936:             $this->_packageInfo['stability'] = array();
                   28937:         }
                   28938:         $this->_packageInfo['stability']['release'] = $state;
                   28939:     }
                   28940: 
                   28941:     /**
                   28942:      * WARNING - do not use this function unless you know what you're doing
                   28943:      */
                   28944:     function setRawCompatible($compatible)
                   28945:     {
                   28946:         $this->_packageInfo['compatible'] = $compatible;
                   28947:     }
                   28948: 
                   28949:     /**
                   28950:      * WARNING - do not use this function unless you know what you're doing
                   28951:      */
                   28952:     function setRawPackage($package)
                   28953:     {
                   28954:         $this->_packageInfo['name'] = $package;
                   28955:     }
                   28956: 
                   28957:     /**
                   28958:      * WARNING - do not use this function unless you know what you're doing
                   28959:      */
                   28960:     function setRawChannel($channel)
                   28961:     {
                   28962:         $this->_packageInfo['channel'] = $channel;
                   28963:     }
                   28964: 
                   28965:     function setRequestedGroup($group)
                   28966:     {
                   28967:         $this->_requestedGroup = $group;
                   28968:     }
                   28969: 
                   28970:     function getRequestedGroup()
                   28971:     {
                   28972:         if (isset($this->_requestedGroup)) {
                   28973:             return $this->_requestedGroup;
                   28974:         }
                   28975:         return false;
                   28976:     }
                   28977: 
                   28978:     /**
                   28979:      * For saving in the registry.
                   28980:      *
                   28981:      * Set the last version that was installed
                   28982:      * @param string
                   28983:      */
                   28984:     function setLastInstalledVersion($version)
                   28985:     {
                   28986:         $this->_packageInfo['_lastversion'] = $version;
                   28987:     }
                   28988: 
                   28989:     /**
                   28990:      * @return string|false
                   28991:      */
                   28992:     function getLastInstalledVersion()
                   28993:     {
                   28994:         if (isset($this->_packageInfo['_lastversion'])) {
                   28995:             return $this->_packageInfo['_lastversion'];
                   28996:         }
                   28997:         return false;
                   28998:     }
                   28999: 
                   29000:     /**
                   29001:      * Determines whether this package.xml has post-install scripts or not
                   29002:      * @return array|false
                   29003:      */
                   29004:     function listPostinstallScripts()
                   29005:     {
                   29006:         $filelist = $this->getFilelist();
                   29007:         $contents = $this->getContents();
                   29008:         $contents = $contents['dir']['file'];
                   29009:         if (!is_array($contents) || !isset($contents[0])) {
                   29010:             $contents = array($contents);
                   29011:         }
                   29012:         $taskfiles = array();
                   29013:         foreach ($contents as $file) {
                   29014:             $atts = $file['attribs'];
                   29015:             unset($file['attribs']);
                   29016:             if (count($file)) {
                   29017:                 $taskfiles[$atts['name']] = $file;
                   29018:             }
                   29019:         }
                   29020:         $common = new PEAR_Common;
                   29021:         $common->debug = $this->_config->get('verbose');
                   29022:         $this->_scripts = array();
                   29023:         $ret = array();
                   29024:         foreach ($taskfiles as $name => $tasks) {
                   29025:             if (!isset($filelist[$name])) {
                   29026:                 // ignored files will not be in the filelist
                   29027:                 continue;
                   29028:             }
                   29029:             $atts = $filelist[$name];
                   29030:             foreach ($tasks as $tag => $raw) {
                   29031:                 $task = $this->getTask($tag);
                   29032:                 $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
                   29033:                 if ($task->isScript()) {
                   29034:                     $ret[] = $filelist[$name]['installed_as'];
                   29035:                 }
                   29036:             }
                   29037:         }
                   29038:         if (count($ret)) {
                   29039:             return $ret;
                   29040:         }
                   29041:         return false;
                   29042:     }
                   29043: 
                   29044:     /**
                   29045:      * Initialize post-install scripts for running
                   29046:      *
                   29047:      * This method can be used to detect post-install scripts, as the return value
                   29048:      * indicates whether any exist
                   29049:      * @return bool
                   29050:      */
                   29051:     function initPostinstallScripts()
                   29052:     {
                   29053:         $filelist = $this->getFilelist();
                   29054:         $contents = $this->getContents();
                   29055:         $contents = $contents['dir']['file'];
                   29056:         if (!is_array($contents) || !isset($contents[0])) {
                   29057:             $contents = array($contents);
                   29058:         }
                   29059:         $taskfiles = array();
                   29060:         foreach ($contents as $file) {
                   29061:             $atts = $file['attribs'];
                   29062:             unset($file['attribs']);
                   29063:             if (count($file)) {
                   29064:                 $taskfiles[$atts['name']] = $file;
                   29065:             }
                   29066:         }
                   29067:         $common = new PEAR_Common;
                   29068:         $common->debug = $this->_config->get('verbose');
                   29069:         $this->_scripts = array();
                   29070:         foreach ($taskfiles as $name => $tasks) {
                   29071:             if (!isset($filelist[$name])) {
                   29072:                 // file was not installed due to installconditions
                   29073:                 continue;
                   29074:             }
                   29075:             $atts = $filelist[$name];
                   29076:             foreach ($tasks as $tag => $raw) {
                   29077:                 $taskname = $this->getTask($tag);
                   29078:                 $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
                   29079:                 if (!$task->isScript()) {
                   29080:                     continue; // scripts are only handled after installation
                   29081:                 }
                   29082:                 $lastversion = isset($this->_packageInfo['_lastversion']) ?
                   29083:                     $this->_packageInfo['_lastversion'] : null;
                   29084:                 $task->init($raw, $atts, $lastversion);
                   29085:                 $res = $task->startSession($this, $atts['installed_as']);
                   29086:                 if (!$res) {
                   29087:                     continue; // skip this file
                   29088:                 }
                   29089:                 if (PEAR::isError($res)) {
                   29090:                     return $res;
                   29091:                 }
                   29092:                 $assign = &$task;
                   29093:                 $this->_scripts[] = &$assign;
                   29094:             }
                   29095:         }
                   29096:         if (count($this->_scripts)) {
                   29097:             return true;
                   29098:         }
                   29099:         return false;
                   29100:     }
                   29101: 
                   29102:     function runPostinstallScripts()
                   29103:     {
                   29104:         if ($this->initPostinstallScripts()) {
                   29105:             $ui = &PEAR_Frontend::singleton();
                   29106:             if ($ui) {
                   29107:                 $ui->runPostinstallScripts($this->_scripts, $this);
                   29108:             }
                   29109:         }
                   29110:     }
                   29111: 
                   29112: 
                   29113:     /**
                   29114:      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
                   29115:      * <file> tags.
                   29116:      */
                   29117:     function flattenFilelist()
                   29118:     {
                   29119:         if (isset($this->_packageInfo['bundle'])) {
                   29120:             return;
                   29121:         }
                   29122:         $filelist = array();
                   29123:         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
                   29124:             $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
                   29125:             if (!isset($filelist[1])) {
                   29126:                 $filelist = $filelist[0];
                   29127:             }
                   29128:             $this->_packageInfo['contents']['dir']['file'] = $filelist;
                   29129:             unset($this->_packageInfo['contents']['dir']['dir']);
                   29130:         } else {
                   29131:             // else already flattened but check for baseinstalldir propagation
                   29132:             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
                   29133:                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
                   29134:                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
                   29135:                         if (isset($file['attribs']['baseinstalldir'])) {
                   29136:                             continue;
                   29137:                         }
                   29138:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
                   29139:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   29140:                     }
                   29141:                 } else {
                   29142:                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
                   29143:                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
                   29144:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   29145:                     }
                   29146:                 }
                   29147:             }
                   29148:         }
                   29149:     }
                   29150: 
                   29151:     /**
                   29152:      * @param array the final flattened file list
                   29153:      * @param array the current directory being processed
                   29154:      * @param string|false any recursively inherited baeinstalldir attribute
                   29155:      * @param string private recursion variable
                   29156:      * @return array
                   29157:      * @access protected
                   29158:      */
                   29159:     function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
                   29160:     {
                   29161:         if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
                   29162:             $baseinstall = $dir['attribs']['baseinstalldir'];
                   29163:         }
                   29164:         if (isset($dir['dir'])) {
                   29165:             if (!isset($dir['dir'][0])) {
                   29166:                 $dir['dir'] = array($dir['dir']);
                   29167:             }
                   29168:             foreach ($dir['dir'] as $subdir) {
                   29169:                 if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
                   29170:                     $name = '*unknown*';
                   29171:                 } else {
                   29172:                     $name = $subdir['attribs']['name'];
                   29173:                 }
                   29174:                 $newpath = empty($path) ? $name :
                   29175:                     $path . '/' . $name;
                   29176:                 $this->_getFlattenedFilelist($files, $subdir,
                   29177:                     $baseinstall, $newpath);
                   29178:             }
                   29179:         }
                   29180:         if (isset($dir['file'])) {
                   29181:             if (!isset($dir['file'][0])) {
                   29182:                 $dir['file'] = array($dir['file']);
                   29183:             }
                   29184:             foreach ($dir['file'] as $file) {
                   29185:                 $attrs = $file['attribs'];
                   29186:                 $name = $attrs['name'];
                   29187:                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
                   29188:                     $attrs['baseinstalldir'] = $baseinstall;
                   29189:                 }
                   29190:                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
                   29191:                 $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   29192:                     $attrs['name']);
                   29193:                 $file['attribs'] = $attrs;
                   29194:                 $files[] = $file;
                   29195:             }
                   29196:         }
                   29197:     }
                   29198: 
                   29199:     function setConfig(&$config)
                   29200:     {
                   29201:         $this->_config = &$config;
                   29202:         $this->_registry = &$config->getRegistry();
                   29203:     }
                   29204: 
                   29205:     function setLogger(&$logger)
                   29206:     {
                   29207:         if (!is_object($logger) || !method_exists($logger, 'log')) {
                   29208:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   29209:         }
                   29210:         $this->_logger = &$logger;
                   29211:     }
                   29212: 
                   29213:     /**
                   29214:      * WARNING - do not use this function directly unless you know what you're doing
                   29215:      */
                   29216:     function setDeps($deps)
                   29217:     {
                   29218:         $this->_packageInfo['dependencies'] = $deps;
                   29219:     }
                   29220: 
                   29221:     /**
                   29222:      * WARNING - do not use this function directly unless you know what you're doing
                   29223:      */
                   29224:     function setCompatible($compat)
                   29225:     {
                   29226:         $this->_packageInfo['compatible'] = $compat;
                   29227:     }
                   29228: 
                   29229:     function setPackagefile($file, $archive = false)
                   29230:     {
                   29231:         $this->_packageFile = $file;
                   29232:         $this->_archiveFile = $archive ? $archive : $file;
                   29233:     }
                   29234: 
                   29235:     /**
                   29236:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   29237:      * @param boolean determines whether to purge the error stack after retrieving
                   29238:      * @return array
                   29239:      */
                   29240:     function getValidationWarnings($purge = true)
                   29241:     {
                   29242:         return $this->_stack->getErrors($purge);
                   29243:     }
                   29244: 
                   29245:     function getPackageFile()
                   29246:     {
                   29247:         return $this->_packageFile;
                   29248:     }
                   29249: 
                   29250:     function getArchiveFile()
                   29251:     {
                   29252:         return $this->_archiveFile;
                   29253:     }
                   29254: 
                   29255: 
                   29256:     /**
                   29257:      * Directly set the array that defines this packagefile
                   29258:      *
                   29259:      * WARNING: no validation.  This should only be performed by internal methods
                   29260:      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
                   29261:      * @param array
                   29262:      */
                   29263:     function fromArray($pinfo)
                   29264:     {
                   29265:         unset($pinfo['old']);
                   29266:         unset($pinfo['xsdversion']);
                   29267:         // If the changelog isn't an array then it was passed in as an empty tag
                   29268:         if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
                   29269:           unset($pinfo['changelog']);
                   29270:         }
                   29271:         $this->_incomplete = false;
                   29272:         $this->_packageInfo = $pinfo;
                   29273:     }
                   29274: 
                   29275:     function isIncomplete()
                   29276:     {
                   29277:         return $this->_incomplete;
                   29278:     }
                   29279: 
                   29280:     /**
                   29281:      * @return array
                   29282:      */
                   29283:     function toArray($forreg = false)
                   29284:     {
                   29285:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   29286:             return false;
                   29287:         }
                   29288:         return $this->getArray($forreg);
                   29289:     }
                   29290: 
                   29291:     function getArray($forReg = false)
                   29292:     {
                   29293:         if ($forReg) {
                   29294:             $arr = $this->_packageInfo;
                   29295:             $arr['old'] = array();
                   29296:             $arr['old']['version'] = $this->getVersion();
                   29297:             $arr['old']['release_date'] = $this->getDate();
                   29298:             $arr['old']['release_state'] = $this->getState();
                   29299:             $arr['old']['release_license'] = $this->getLicense();
                   29300:             $arr['old']['release_notes'] = $this->getNotes();
                   29301:             $arr['old']['release_deps'] = $this->getDeps();
                   29302:             $arr['old']['maintainers'] = $this->getMaintainers();
                   29303:             $arr['xsdversion'] = '2.0';
                   29304:             return $arr;
                   29305:         } else {
                   29306:             $info = $this->_packageInfo;
                   29307:             unset($info['dirtree']);
                   29308:             if (isset($info['_lastversion'])) {
                   29309:                 unset($info['_lastversion']);
                   29310:             }
                   29311:             if (isset($info['#binarypackage'])) {
                   29312:                 unset($info['#binarypackage']);
                   29313:             }
                   29314:             return $info;
                   29315:         }
                   29316:     }
                   29317: 
                   29318:     function packageInfo($field)
                   29319:     {
                   29320:         $arr = $this->getArray(true);
                   29321:         if ($field == 'state') {
                   29322:             return $arr['stability']['release'];
                   29323:         }
                   29324:         if ($field == 'api-version') {
                   29325:             return $arr['version']['api'];
                   29326:         }
                   29327:         if ($field == 'api-state') {
                   29328:             return $arr['stability']['api'];
                   29329:         }
                   29330:         if (isset($arr['old'][$field])) {
                   29331:             if (!is_string($arr['old'][$field])) {
                   29332:                 return null;
                   29333:             }
                   29334:             return $arr['old'][$field];
                   29335:         }
                   29336:         if (isset($arr[$field])) {
                   29337:             if (!is_string($arr[$field])) {
                   29338:                 return null;
                   29339:             }
                   29340:             return $arr[$field];
                   29341:         }
                   29342:         return null;
                   29343:     }
                   29344: 
                   29345:     function getName()
                   29346:     {
                   29347:         return $this->getPackage();
                   29348:     }
                   29349: 
                   29350:     function getPackage()
                   29351:     {
                   29352:         if (isset($this->_packageInfo['name'])) {
                   29353:             return $this->_packageInfo['name'];
                   29354:         }
                   29355:         return false;
                   29356:     }
                   29357: 
                   29358:     function getChannel()
                   29359:     {
                   29360:         if (isset($this->_packageInfo['uri'])) {
                   29361:             return '__uri';
                   29362:         }
                   29363:         if (isset($this->_packageInfo['channel'])) {
                   29364:             return strtolower($this->_packageInfo['channel']);
                   29365:         }
                   29366:         return false;
                   29367:     }
                   29368: 
                   29369:     function getUri()
                   29370:     {
                   29371:         if (isset($this->_packageInfo['uri'])) {
                   29372:             return $this->_packageInfo['uri'];
                   29373:         }
                   29374:         return false;
                   29375:     }
                   29376: 
                   29377:     function getExtends()
                   29378:     {
                   29379:         if (isset($this->_packageInfo['extends'])) {
                   29380:             return $this->_packageInfo['extends'];
                   29381:         }
                   29382:         return false;
                   29383:     }
                   29384: 
                   29385:     function getSummary()
                   29386:     {
                   29387:         if (isset($this->_packageInfo['summary'])) {
                   29388:             return $this->_packageInfo['summary'];
                   29389:         }
                   29390:         return false;
                   29391:     }
                   29392: 
                   29393:     function getDescription()
                   29394:     {
                   29395:         if (isset($this->_packageInfo['description'])) {
                   29396:             return $this->_packageInfo['description'];
                   29397:         }
                   29398:         return false;
                   29399:     }
                   29400: 
                   29401:     function getMaintainers($raw = false)
                   29402:     {
                   29403:         if (!isset($this->_packageInfo['lead'])) {
                   29404:             return false;
                   29405:         }
                   29406:         if ($raw) {
                   29407:             $ret = array('lead' => $this->_packageInfo['lead']);
                   29408:             (isset($this->_packageInfo['developer'])) ?
                   29409:                 $ret['developer'] = $this->_packageInfo['developer'] :null;
                   29410:             (isset($this->_packageInfo['contributor'])) ?
                   29411:                 $ret['contributor'] = $this->_packageInfo['contributor'] :null;
                   29412:             (isset($this->_packageInfo['helper'])) ?
                   29413:                 $ret['helper'] = $this->_packageInfo['helper'] :null;
                   29414:             return $ret;
                   29415:         } else {
                   29416:             $ret = array();
                   29417:             $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
                   29418:                 array($this->_packageInfo['lead']);
                   29419:             foreach ($leads as $lead) {
                   29420:                 $s = $lead;
                   29421:                 $s['handle'] = $s['user'];
                   29422:                 unset($s['user']);
                   29423:                 $s['role'] = 'lead';
                   29424:                 $ret[] = $s;
                   29425:             }
                   29426:             if (isset($this->_packageInfo['developer'])) {
                   29427:                 $leads = isset($this->_packageInfo['developer'][0]) ?
                   29428:                     $this->_packageInfo['developer'] :
                   29429:                     array($this->_packageInfo['developer']);
                   29430:                 foreach ($leads as $maintainer) {
                   29431:                     $s = $maintainer;
                   29432:                     $s['handle'] = $s['user'];
                   29433:                     unset($s['user']);
                   29434:                     $s['role'] = 'developer';
                   29435:                     $ret[] = $s;
                   29436:                 }
                   29437:             }
                   29438:             if (isset($this->_packageInfo['contributor'])) {
                   29439:                 $leads = isset($this->_packageInfo['contributor'][0]) ?
                   29440:                     $this->_packageInfo['contributor'] :
                   29441:                     array($this->_packageInfo['contributor']);
                   29442:                 foreach ($leads as $maintainer) {
                   29443:                     $s = $maintainer;
                   29444:                     $s['handle'] = $s['user'];
                   29445:                     unset($s['user']);
                   29446:                     $s['role'] = 'contributor';
                   29447:                     $ret[] = $s;
                   29448:                 }
                   29449:             }
                   29450:             if (isset($this->_packageInfo['helper'])) {
                   29451:                 $leads = isset($this->_packageInfo['helper'][0]) ?
                   29452:                     $this->_packageInfo['helper'] :
                   29453:                     array($this->_packageInfo['helper']);
                   29454:                 foreach ($leads as $maintainer) {
                   29455:                     $s = $maintainer;
                   29456:                     $s['handle'] = $s['user'];
                   29457:                     unset($s['user']);
                   29458:                     $s['role'] = 'helper';
                   29459:                     $ret[] = $s;
                   29460:                 }
                   29461:             }
                   29462:             return $ret;
                   29463:         }
                   29464:         return false;
                   29465:     }
                   29466: 
                   29467:     function getLeads()
                   29468:     {
                   29469:         if (isset($this->_packageInfo['lead'])) {
                   29470:             return $this->_packageInfo['lead'];
                   29471:         }
                   29472:         return false;
                   29473:     }
                   29474: 
                   29475:     function getDevelopers()
                   29476:     {
                   29477:         if (isset($this->_packageInfo['developer'])) {
                   29478:             return $this->_packageInfo['developer'];
                   29479:         }
                   29480:         return false;
                   29481:     }
                   29482: 
                   29483:     function getContributors()
                   29484:     {
                   29485:         if (isset($this->_packageInfo['contributor'])) {
                   29486:             return $this->_packageInfo['contributor'];
                   29487:         }
                   29488:         return false;
                   29489:     }
                   29490: 
                   29491:     function getHelpers()
                   29492:     {
                   29493:         if (isset($this->_packageInfo['helper'])) {
                   29494:             return $this->_packageInfo['helper'];
                   29495:         }
                   29496:         return false;
                   29497:     }
                   29498: 
                   29499:     function setDate($date)
                   29500:     {
                   29501:         if (!isset($this->_packageInfo['date'])) {
                   29502:             // ensure that the extends tag is set up in the right location
                   29503:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   29504:                 array('time', 'version',
                   29505:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   29506:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   29507:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   29508:                     'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
                   29509:         }
                   29510:         $this->_packageInfo['date'] = $date;
                   29511:         $this->_isValid = 0;
                   29512:     }
                   29513: 
                   29514:     function setTime($time)
                   29515:     {
                   29516:         $this->_isValid = 0;
                   29517:         if (!isset($this->_packageInfo['time'])) {
                   29518:             // ensure that the time tag is set up in the right location
                   29519:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   29520:                     array('version',
                   29521:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   29522:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   29523:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   29524:                     'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
                   29525:         }
                   29526:         $this->_packageInfo['time'] = $time;
                   29527:     }
                   29528: 
                   29529:     function getDate()
                   29530:     {
                   29531:         if (isset($this->_packageInfo['date'])) {
                   29532:             return $this->_packageInfo['date'];
                   29533:         }
                   29534:         return false;
                   29535:     }
                   29536: 
                   29537:     function getTime()
                   29538:     {
                   29539:         if (isset($this->_packageInfo['time'])) {
                   29540:             return $this->_packageInfo['time'];
                   29541:         }
                   29542:         return false;
                   29543:     }
                   29544: 
                   29545:     /**
                   29546:      * @param package|api version category to return
                   29547:      */
                   29548:     function getVersion($key = 'release')
                   29549:     {
                   29550:         if (isset($this->_packageInfo['version'][$key])) {
                   29551:             return $this->_packageInfo['version'][$key];
                   29552:         }
                   29553:         return false;
                   29554:     }
                   29555: 
                   29556:     function getStability()
                   29557:     {
                   29558:         if (isset($this->_packageInfo['stability'])) {
                   29559:             return $this->_packageInfo['stability'];
                   29560:         }
                   29561:         return false;
                   29562:     }
                   29563: 
                   29564:     function getState($key = 'release')
                   29565:     {
                   29566:         if (isset($this->_packageInfo['stability'][$key])) {
                   29567:             return $this->_packageInfo['stability'][$key];
                   29568:         }
                   29569:         return false;
                   29570:     }
                   29571: 
                   29572:     function getLicense($raw = false)
                   29573:     {
                   29574:         if (isset($this->_packageInfo['license'])) {
                   29575:             if ($raw) {
                   29576:                 return $this->_packageInfo['license'];
                   29577:             }
                   29578:             if (is_array($this->_packageInfo['license'])) {
                   29579:                 return $this->_packageInfo['license']['_content'];
                   29580:             } else {
                   29581:                 return $this->_packageInfo['license'];
                   29582:             }
                   29583:         }
                   29584:         return false;
                   29585:     }
                   29586: 
                   29587:     function getLicenseLocation()
                   29588:     {
                   29589:         if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
                   29590:             return false;
                   29591:         }
                   29592:         return $this->_packageInfo['license']['attribs'];
                   29593:     }
                   29594: 
                   29595:     function getNotes()
                   29596:     {
                   29597:         if (isset($this->_packageInfo['notes'])) {
                   29598:             return $this->_packageInfo['notes'];
                   29599:         }
                   29600:         return false;
                   29601:     }
                   29602: 
                   29603:     /**
                   29604:      * Return the <usesrole> tag contents, if any
                   29605:      * @return array|false
                   29606:      */
                   29607:     function getUsesrole()
                   29608:     {
                   29609:         if (isset($this->_packageInfo['usesrole'])) {
                   29610:             return $this->_packageInfo['usesrole'];
                   29611:         }
                   29612:         return false;
                   29613:     }
                   29614: 
                   29615:     /**
                   29616:      * Return the <usestask> tag contents, if any
                   29617:      * @return array|false
                   29618:      */
                   29619:     function getUsestask()
                   29620:     {
                   29621:         if (isset($this->_packageInfo['usestask'])) {
                   29622:             return $this->_packageInfo['usestask'];
                   29623:         }
                   29624:         return false;
                   29625:     }
                   29626: 
                   29627:     /**
                   29628:      * This should only be used to retrieve filenames and install attributes
                   29629:      */
                   29630:     function getFilelist($preserve = false)
                   29631:     {
                   29632:         if (isset($this->_packageInfo['filelist']) && !$preserve) {
                   29633:             return $this->_packageInfo['filelist'];
                   29634:         }
                   29635:         $this->flattenFilelist();
                   29636:         if ($contents = $this->getContents()) {
                   29637:             $ret = array();
                   29638:             if (!isset($contents['dir'])) {
                   29639:                 return false;
                   29640:             }
                   29641:             if (!isset($contents['dir']['file'][0])) {
                   29642:                 $contents['dir']['file'] = array($contents['dir']['file']);
                   29643:             }
                   29644:             foreach ($contents['dir']['file'] as $file) {
                   29645:                 $name = $file['attribs']['name'];
                   29646:                 if (!$preserve) {
                   29647:                     $file = $file['attribs'];
                   29648:                 }
                   29649:                 $ret[$name] = $file;
                   29650:             }
                   29651:             if (!$preserve) {
                   29652:                 $this->_packageInfo['filelist'] = $ret;
                   29653:             }
                   29654:             return $ret;
                   29655:         }
                   29656:         return false;
                   29657:     }
                   29658: 
                   29659:     /**
                   29660:      * Return configure options array, if any
                   29661:      *
                   29662:      * @return array|false
                   29663:      */
                   29664:     function getConfigureOptions()
                   29665:     {
                   29666:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   29667:             return false;
                   29668:         }
                   29669: 
                   29670:         $releases = $this->getReleases();
                   29671:         if (isset($releases[0])) {
                   29672:             $releases = $releases[0];
                   29673:         }
                   29674: 
                   29675:         if (isset($releases['configureoption'])) {
                   29676:             if (!isset($releases['configureoption'][0])) {
                   29677:                 $releases['configureoption'] = array($releases['configureoption']);
                   29678:             }
                   29679: 
                   29680:             for ($i = 0; $i < count($releases['configureoption']); $i++) {
                   29681:                 $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
                   29682:             }
                   29683: 
                   29684:             return $releases['configureoption'];
                   29685:         }
                   29686: 
                   29687:         return false;
                   29688:     }
                   29689: 
                   29690:     /**
                   29691:      * This is only used at install-time, after all serialization
                   29692:      * is over.
                   29693:      */
                   29694:     function resetFilelist()
                   29695:     {
                   29696:         $this->_packageInfo['filelist'] = array();
                   29697:     }
                   29698: 
                   29699:     /**
                   29700:      * Retrieve a list of files that should be installed on this computer
                   29701:      * @return array
                   29702:      */
                   29703:     function getInstallationFilelist($forfilecheck = false)
                   29704:     {
                   29705:         $contents = $this->getFilelist(true);
                   29706:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
                   29707:             $base = $contents['dir']['attribs']['baseinstalldir'];
                   29708:         }
                   29709:         if (isset($this->_packageInfo['bundle'])) {
                   29710:             return PEAR::raiseError(
                   29711:                 'Exception: bundles should be handled in download code only');
                   29712:         }
                   29713:         $release = $this->getReleases();
                   29714:         if ($release) {
                   29715:             if (!isset($release[0])) {
                   29716:                 if (!isset($release['installconditions']) && !isset($release['filelist'])) {
                   29717:                     if ($forfilecheck) {
                   29718:                         return $this->getFilelist();
                   29719:                     }
                   29720:                     return $contents;
                   29721:                 }
                   29722:                 $release = array($release);
                   29723:             }
                   29724:             $depchecker = &$this->getPEARDependency2($this->_config, array(),
                   29725:                 array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
                   29726:                 PEAR_VALIDATE_INSTALLING);
                   29727:             foreach ($release as $instance) {
                   29728:                 if (isset($instance['installconditions'])) {
                   29729:                     $installconditions = $instance['installconditions'];
                   29730:                     if (is_array($installconditions)) {
                   29731:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   29732:                         foreach ($installconditions as $type => $conditions) {
                   29733:                             if (!isset($conditions[0])) {
                   29734:                                 $conditions = array($conditions);
                   29735:                             }
                   29736:                             foreach ($conditions as $condition) {
                   29737:                                 $ret = $depchecker->{"validate{$type}Dependency"}($condition);
                   29738:                                 if (PEAR::isError($ret)) {
                   29739:                                     PEAR::popErrorHandling();
                   29740:                                     continue 3; // skip this release
                   29741:                                 }
                   29742:                             }
                   29743:                         }
                   29744:                         PEAR::popErrorHandling();
                   29745:                     }
                   29746:                 }
                   29747:                 // this is the release to use
                   29748:                 if (isset($instance['filelist'])) {
                   29749:                     // ignore files
                   29750:                     if (isset($instance['filelist']['ignore'])) {
                   29751:                         $ignore = isset($instance['filelist']['ignore'][0]) ?
                   29752:                             $instance['filelist']['ignore'] :
                   29753:                             array($instance['filelist']['ignore']);
                   29754:                         foreach ($ignore as $ig) {
                   29755:                             unset ($contents[$ig['attribs']['name']]);
                   29756:                         }
                   29757:                     }
                   29758:                     // install files as this name
                   29759:                     if (isset($instance['filelist']['install'])) {
                   29760:                         $installas = isset($instance['filelist']['install'][0]) ?
                   29761:                             $instance['filelist']['install'] :
                   29762:                             array($instance['filelist']['install']);
                   29763:                         foreach ($installas as $as) {
                   29764:                             $contents[$as['attribs']['name']]['attribs']['install-as'] =
                   29765:                                 $as['attribs']['as'];
                   29766:                         }
                   29767:                     }
                   29768:                 }
                   29769:                 if ($forfilecheck) {
                   29770:                     foreach ($contents as $file => $attrs) {
                   29771:                         $contents[$file] = $attrs['attribs'];
                   29772:                     }
                   29773:                 }
                   29774:                 return $contents;
                   29775:             }
                   29776:         } else { // simple release - no installconditions or install-as
                   29777:             if ($forfilecheck) {
                   29778:                 return $this->getFilelist();
                   29779:             }
                   29780:             return $contents;
                   29781:         }
                   29782:         // no releases matched
                   29783:         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
                   29784:             'system, extensions installed, or architecture, cannot install');
                   29785:     }
                   29786: 
                   29787:     /**
                   29788:      * This is only used at install-time, after all serialization
                   29789:      * is over.
                   29790:      * @param string file name
                   29791:      * @param string installed path
                   29792:      */
                   29793:     function setInstalledAs($file, $path)
                   29794:     {
                   29795:         if ($path) {
                   29796:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   29797:         }
                   29798:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   29799:     }
                   29800: 
                   29801:     function getInstalledLocation($file)
                   29802:     {
                   29803:         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
                   29804:             return $this->_packageInfo['filelist'][$file]['installed_as'];
                   29805:         }
                   29806:         return false;
                   29807:     }
                   29808: 
                   29809:     /**
                   29810:      * This is only used at install-time, after all serialization
                   29811:      * is over.
                   29812:      */
                   29813:     function installedFile($file, $atts)
                   29814:     {
                   29815:         if (isset($this->_packageInfo['filelist'][$file])) {
                   29816:             $this->_packageInfo['filelist'][$file] =
                   29817:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
                   29818:         } else {
                   29819:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
                   29820:         }
                   29821:     }
                   29822: 
                   29823:     /**
                   29824:      * Retrieve the contents tag
                   29825:      */
                   29826:     function getContents()
                   29827:     {
                   29828:         if (isset($this->_packageInfo['contents'])) {
                   29829:             return $this->_packageInfo['contents'];
                   29830:         }
                   29831:         return false;
                   29832:     }
                   29833: 
                   29834:     /**
                   29835:      * @param string full path to file
                   29836:      * @param string attribute name
                   29837:      * @param string attribute value
                   29838:      * @param int risky but fast - use this to choose a file based on its position in the list
                   29839:      *            of files.  Index is zero-based like PHP arrays.
                   29840:      * @return bool success of operation
                   29841:      */
                   29842:     function setFileAttribute($filename, $attr, $value, $index = false)
                   29843:     {
                   29844:         $this->_isValid = 0;
                   29845:         if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
                   29846:             $this->_filesValid = false;
                   29847:         }
                   29848:         if ($index !== false &&
                   29849:               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
                   29850:             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
                   29851:             return true;
                   29852:         }
                   29853:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
                   29854:             return false;
                   29855:         }
                   29856:         $files = $this->_packageInfo['contents']['dir']['file'];
                   29857:         if (!isset($files[0])) {
                   29858:             $files = array($files);
                   29859:             $ind = false;
                   29860:         } else {
                   29861:             $ind = true;
                   29862:         }
                   29863:         foreach ($files as $i => $file) {
                   29864:             if (isset($file['attribs'])) {
                   29865:                 if ($file['attribs']['name'] == $filename) {
                   29866:                     if ($ind) {
                   29867:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
                   29868:                     } else {
                   29869:                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
                   29870:                     }
                   29871:                     return true;
                   29872:                 }
                   29873:             }
                   29874:         }
                   29875:         return false;
                   29876:     }
                   29877: 
                   29878:     function setDirtree($path)
                   29879:     {
                   29880:         if (!isset($this->_packageInfo['dirtree'])) {
                   29881:             $this->_packageInfo['dirtree'] = array();
                   29882:         }
                   29883:         $this->_packageInfo['dirtree'][$path] = true;
                   29884:     }
                   29885: 
                   29886:     function getDirtree()
                   29887:     {
                   29888:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   29889:             return $this->_packageInfo['dirtree'];
                   29890:         }
                   29891:         return false;
                   29892:     }
                   29893: 
                   29894:     function resetDirtree()
                   29895:     {
                   29896:         unset($this->_packageInfo['dirtree']);
                   29897:     }
                   29898: 
                   29899:     /**
                   29900:      * Determines whether this package claims it is compatible with the version of
                   29901:      * the package that has a recommended version dependency
                   29902:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
                   29903:      * @return boolean
                   29904:      */
                   29905:     function isCompatible($pf)
                   29906:     {
                   29907:         if (!isset($this->_packageInfo['compatible'])) {
                   29908:             return false;
                   29909:         }
                   29910:         if (!isset($this->_packageInfo['channel'])) {
                   29911:             return false;
                   29912:         }
                   29913:         $me = $pf->getVersion();
                   29914:         $compatible = $this->_packageInfo['compatible'];
                   29915:         if (!isset($compatible[0])) {
                   29916:             $compatible = array($compatible);
                   29917:         }
                   29918:         $found = false;
                   29919:         foreach ($compatible as $info) {
                   29920:             if (strtolower($info['name']) == strtolower($pf->getPackage())) {
                   29921:                 if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
                   29922:                     $found = true;
                   29923:                     break;
                   29924:                 }
                   29925:             }
                   29926:         }
                   29927:         if (!$found) {
                   29928:             return false;
                   29929:         }
                   29930:         if (isset($info['exclude'])) {
                   29931:             if (!isset($info['exclude'][0])) {
                   29932:                 $info['exclude'] = array($info['exclude']);
                   29933:             }
                   29934:             foreach ($info['exclude'] as $exclude) {
                   29935:                 if (version_compare($me, $exclude, '==')) {
                   29936:                     return false;
                   29937:                 }
                   29938:             }
                   29939:         }
                   29940:         if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
                   29941:             return true;
                   29942:         }
                   29943:         return false;
                   29944:     }
                   29945: 
                   29946:     /**
                   29947:      * @return array|false
                   29948:      */
                   29949:     function getCompatible()
                   29950:     {
                   29951:         if (isset($this->_packageInfo['compatible'])) {
                   29952:             return $this->_packageInfo['compatible'];
                   29953:         }
                   29954:         return false;
                   29955:     }
                   29956: 
                   29957:     function getDependencies()
                   29958:     {
                   29959:         if (isset($this->_packageInfo['dependencies'])) {
                   29960:             return $this->_packageInfo['dependencies'];
                   29961:         }
                   29962:         return false;
                   29963:     }
                   29964: 
                   29965:     function isSubpackageOf($p)
                   29966:     {
                   29967:         return $p->isSubpackage($this);
                   29968:     }
                   29969: 
                   29970:     /**
                   29971:      * Determines whether the passed in package is a subpackage of this package.
                   29972:      *
                   29973:      * No version checking is done, only name verification.
                   29974:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   29975:      * @return bool
                   29976:      */
                   29977:     function isSubpackage($p)
                   29978:     {
                   29979:         $sub = array();
                   29980:         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
                   29981:             $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
                   29982:             if (!isset($sub[0])) {
                   29983:                 $sub = array($sub);
                   29984:             }
                   29985:         }
                   29986:         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
                   29987:             $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
                   29988:             if (!isset($sub1[0])) {
                   29989:                 $sub1 = array($sub1);
                   29990:             }
                   29991:             $sub = array_merge($sub, $sub1);
                   29992:         }
                   29993:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   29994:             $group = $this->_packageInfo['dependencies']['group'];
                   29995:             if (!isset($group[0])) {
                   29996:                 $group = array($group);
                   29997:             }
                   29998:             foreach ($group as $deps) {
                   29999:                 if (isset($deps['subpackage'])) {
                   30000:                     $sub2 = $deps['subpackage'];
                   30001:                     if (!isset($sub2[0])) {
                   30002:                         $sub2 = array($sub2);
                   30003:                     }
                   30004:                     $sub = array_merge($sub, $sub2);
                   30005:                 }
                   30006:             }
                   30007:         }
                   30008:         foreach ($sub as $dep) {
                   30009:             if (strtolower($dep['name']) == strtolower($p->getPackage())) {
                   30010:                 if (isset($dep['channel'])) {
                   30011:                     if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
                   30012:                         return true;
                   30013:                     }
                   30014:                 } else {
                   30015:                     if ($dep['uri'] == $p->getURI()) {
                   30016:                         return true;
                   30017:                     }
                   30018:                 }
                   30019:             }
                   30020:         }
                   30021:         return false;
                   30022:     }
                   30023: 
                   30024:     function dependsOn($package, $channel)
                   30025:     {
                   30026:         if (!($deps = $this->getDependencies())) {
                   30027:             return false;
                   30028:         }
                   30029:         foreach (array('package', 'subpackage') as $type) {
                   30030:             foreach (array('required', 'optional') as $needed) {
                   30031:                 if (isset($deps[$needed][$type])) {
                   30032:                     if (!isset($deps[$needed][$type][0])) {
                   30033:                         $deps[$needed][$type] = array($deps[$needed][$type]);
                   30034:                     }
                   30035:                     foreach ($deps[$needed][$type] as $dep) {
                   30036:                         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   30037:                         if (strtolower($dep['name']) == strtolower($package) &&
                   30038:                               $depchannel == $channel) {
                   30039:                             return true;
                   30040:                         }
                   30041:                     }
                   30042:                 }
                   30043:             }
                   30044:             if (isset($deps['group'])) {
                   30045:                 if (!isset($deps['group'][0])) {
                   30046:                     $dep['group'] = array($deps['group']);
                   30047:                 }
                   30048:                 foreach ($deps['group'] as $group) {
                   30049:                     if (isset($group[$type])) {
                   30050:                         if (!is_array($group[$type])) {
                   30051:                             $group[$type] = array($group[$type]);
                   30052:                         }
                   30053:                         foreach ($group[$type] as $dep) {
                   30054:                             $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   30055:                             if (strtolower($dep['name']) == strtolower($package) &&
                   30056:                                   $depchannel == $channel) {
                   30057:                                 return true;
                   30058:                             }
                   30059:                         }
                   30060:                     }
                   30061:                 }
                   30062:             }
                   30063:         }
                   30064:         return false;
                   30065:     }
                   30066: 
                   30067:     /**
                   30068:      * Get the contents of a dependency group
                   30069:      * @param string
                   30070:      * @return array|false
                   30071:      */
                   30072:     function getDependencyGroup($name)
                   30073:     {
                   30074:         $name = strtolower($name);
                   30075:         if (!isset($this->_packageInfo['dependencies']['group'])) {
                   30076:             return false;
                   30077:         }
                   30078:         $groups = $this->_packageInfo['dependencies']['group'];
                   30079:         if (!isset($groups[0])) {
                   30080:             $groups = array($groups);
                   30081:         }
                   30082:         foreach ($groups as $group) {
                   30083:             if (strtolower($group['attribs']['name']) == $name) {
                   30084:                 return $group;
                   30085:             }
                   30086:         }
                   30087:         return false;
                   30088:     }
                   30089: 
                   30090:     /**
                   30091:      * Retrieve a partial package.xml 1.0 representation of dependencies
                   30092:      *
                   30093:      * a very limited representation of dependencies is returned by this method.
                   30094:      * The <exclude> tag for excluding certain versions of a dependency is
                   30095:      * completely ignored.  In addition, dependency groups are ignored, with the
                   30096:      * assumption that all dependencies in dependency groups are also listed in
                   30097:      * the optional group that work with all dependency groups
                   30098:      * @param boolean return package.xml 2.0 <dependencies> tag
                   30099:      * @return array|false
                   30100:      */
                   30101:     function getDeps($raw = false, $nopearinstaller = false)
                   30102:     {
                   30103:         if (isset($this->_packageInfo['dependencies'])) {
                   30104:             if ($raw) {
                   30105:                 return $this->_packageInfo['dependencies'];
                   30106:             }
                   30107:             $ret = array();
                   30108:             $map = array(
                   30109:                 'php' => 'php',
                   30110:                 'package' => 'pkg',
                   30111:                 'subpackage' => 'pkg',
                   30112:                 'extension' => 'ext',
                   30113:                 'os' => 'os',
                   30114:                 'pearinstaller' => 'pkg',
                   30115:                 );
                   30116:             foreach (array('required', 'optional') as $type) {
                   30117:                 $optional = ($type == 'optional') ? 'yes' : 'no';
                   30118:                 if (!isset($this->_packageInfo['dependencies'][$type])
                   30119:                     || empty($this->_packageInfo['dependencies'][$type])) {
                   30120:                     continue;
                   30121:                 }
                   30122:                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
                   30123:                     if ($dtype == 'pearinstaller' && $nopearinstaller) {
                   30124:                         continue;
                   30125:                     }
                   30126:                     if (!isset($deps[0])) {
                   30127:                         $deps = array($deps);
                   30128:                     }
                   30129:                     foreach ($deps as $dep) {
                   30130:                         if (!isset($map[$dtype])) {
                   30131:                             // no support for arch type
                   30132:                             continue;
                   30133:                         }
                   30134:                         if ($dtype == 'pearinstaller') {
                   30135:                             $dep['name'] = 'PEAR';
                   30136:                             $dep['channel'] = 'pear.php.net';
                   30137:                         }
                   30138:                         $s = array('type' => $map[$dtype]);
                   30139:                         if (isset($dep['channel'])) {
                   30140:                             $s['channel'] = $dep['channel'];
                   30141:                         }
                   30142:                         if (isset($dep['uri'])) {
                   30143:                             $s['uri'] = $dep['uri'];
                   30144:                         }
                   30145:                         if (isset($dep['name'])) {
                   30146:                             $s['name'] = $dep['name'];
                   30147:                         }
                   30148:                         if (isset($dep['conflicts'])) {
                   30149:                             $s['rel'] = 'not';
                   30150:                         } else {
                   30151:                             if (!isset($dep['min']) &&
                   30152:                                   !isset($dep['max'])) {
                   30153:                                 $s['rel'] = 'has';
                   30154:                                 $s['optional'] = $optional;
                   30155:                             } elseif (isset($dep['min']) &&
                   30156:                                   isset($dep['max'])) {
                   30157:                                 $s['rel'] = 'ge';
                   30158:                                 $s1 = $s;
                   30159:                                 $s1['rel'] = 'le';
                   30160:                                 $s['version'] = $dep['min'];
                   30161:                                 $s1['version'] = $dep['max'];
                   30162:                                 if (isset($dep['channel'])) {
                   30163:                                     $s1['channel'] = $dep['channel'];
                   30164:                                 }
                   30165:                                 if ($dtype != 'php') {
                   30166:                                     $s['name'] = $dep['name'];
                   30167:                                     $s1['name'] = $dep['name'];
                   30168:                                 }
                   30169:                                 $s['optional'] = $optional;
                   30170:                                 $s1['optional'] = $optional;
                   30171:                                 $ret[] = $s1;
                   30172:                             } elseif (isset($dep['min'])) {
                   30173:                                 if (isset($dep['exclude']) &&
                   30174:                                       $dep['exclude'] == $dep['min']) {
                   30175:                                     $s['rel'] = 'gt';
                   30176:                                 } else {
                   30177:                                     $s['rel'] = 'ge';
                   30178:                                 }
                   30179:                                 $s['version'] = $dep['min'];
                   30180:                                 $s['optional'] = $optional;
                   30181:                                 if ($dtype != 'php') {
                   30182:                                     $s['name'] = $dep['name'];
                   30183:                                 }
                   30184:                             } elseif (isset($dep['max'])) {
                   30185:                                 if (isset($dep['exclude']) &&
                   30186:                                       $dep['exclude'] == $dep['max']) {
                   30187:                                     $s['rel'] = 'lt';
                   30188:                                 } else {
                   30189:                                     $s['rel'] = 'le';
                   30190:                                 }
                   30191:                                 $s['version'] = $dep['max'];
                   30192:                                 $s['optional'] = $optional;
                   30193:                                 if ($dtype != 'php') {
                   30194:                                     $s['name'] = $dep['name'];
                   30195:                                 }
                   30196:                             }
                   30197:                         }
                   30198:                         $ret[] = $s;
                   30199:                     }
                   30200:                 }
                   30201:             }
                   30202:             if (count($ret)) {
                   30203:                 return $ret;
                   30204:             }
                   30205:         }
                   30206:         return false;
                   30207:     }
                   30208: 
                   30209:     /**
                   30210:      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
                   30211:      */
                   30212:     function getPackageType()
                   30213:     {
                   30214:         if (isset($this->_packageInfo['phprelease'])) {
                   30215:             return 'php';
                   30216:         }
                   30217:         if (isset($this->_packageInfo['extsrcrelease'])) {
                   30218:             return 'extsrc';
                   30219:         }
                   30220:         if (isset($this->_packageInfo['extbinrelease'])) {
                   30221:             return 'extbin';
                   30222:         }
                   30223:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   30224:             return 'zendextsrc';
                   30225:         }
                   30226:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   30227:             return 'zendextbin';
                   30228:         }
                   30229:         if (isset($this->_packageInfo['bundle'])) {
                   30230:             return 'bundle';
                   30231:         }
                   30232:         return false;
                   30233:     }
                   30234: 
                   30235:     /**
                   30236:      * @return array|false
                   30237:      */
                   30238:     function getReleases()
                   30239:     {
                   30240:         $type = $this->getPackageType();
                   30241:         if ($type != 'bundle') {
                   30242:             $type .= 'release';
                   30243:         }
                   30244:         if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
                   30245:             return $this->_packageInfo[$type];
                   30246:         }
                   30247:         return false;
                   30248:     }
                   30249: 
                   30250:     /**
                   30251:      * @return array
                   30252:      */
                   30253:     function getChangelog()
                   30254:     {
                   30255:         if (isset($this->_packageInfo['changelog'])) {
                   30256:             return $this->_packageInfo['changelog'];
                   30257:         }
                   30258:         return false;
                   30259:     }
                   30260: 
                   30261:     function hasDeps()
                   30262:     {
                   30263:         return isset($this->_packageInfo['dependencies']);
                   30264:     }
                   30265: 
                   30266:     function getPackagexmlVersion()
                   30267:     {
                   30268:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   30269:             return '2.1';
                   30270:         }
                   30271:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   30272:             return '2.1';
                   30273:         }
                   30274:         return '2.0';
                   30275:     }
                   30276: 
                   30277:     /**
                   30278:      * @return array|false
                   30279:      */
                   30280:     function getSourcePackage()
                   30281:     {
                   30282:         if (isset($this->_packageInfo['extbinrelease']) ||
                   30283:               isset($this->_packageInfo['zendextbinrelease'])) {
                   30284:             return array('channel' => $this->_packageInfo['srcchannel'],
                   30285:                          'package' => $this->_packageInfo['srcpackage']);
                   30286:         }
                   30287:         return false;
                   30288:     }
                   30289: 
                   30290:     function getBundledPackages()
                   30291:     {
                   30292:         if (isset($this->_packageInfo['bundle'])) {
                   30293:             return $this->_packageInfo['contents']['bundledpackage'];
                   30294:         }
                   30295:         return false;
                   30296:     }
                   30297: 
                   30298:     function getLastModified()
                   30299:     {
                   30300:         if (isset($this->_packageInfo['_lastmodified'])) {
                   30301:             return $this->_packageInfo['_lastmodified'];
                   30302:         }
                   30303:         return false;
                   30304:     }
                   30305: 
                   30306:     /**
                   30307:      * Get the contents of a file listed within the package.xml
                   30308:      * @param string
                   30309:      * @return string
                   30310:      */
                   30311:     function getFileContents($file)
                   30312:     {
                   30313:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   30314:             $dir = dirname($this->_packageFile);
                   30315:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   30316:             $file = str_replace(array('/', '\\'),
                   30317:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   30318:             if (file_exists($file) && is_readable($file)) {
                   30319:                 return implode('', file($file));
                   30320:             }
                   30321:         } else { // tgz
                   30322:             $tar = &new Archive_Tar($this->_archiveFile);
                   30323:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   30324:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   30325:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   30326:             }
                   30327:             $file = $tar->extractInString($file);
                   30328:             $tar->popErrorHandling();
                   30329:             if (PEAR::isError($file)) {
                   30330:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   30331:             }
                   30332:             return $file;
                   30333:         }
                   30334:     }
                   30335: 
                   30336:     function &getRW()
                   30337:     {
                   30338:         if (!class_exists('PEAR_PackageFile_v2_rw')) {
                   30339:             require_once 'PEAR/PackageFile/v2/rw.php';
                   30340:         }
                   30341:         $a = new PEAR_PackageFile_v2_rw;
                   30342:         foreach (get_object_vars($this) as $name => $unused) {
                   30343:             if (!isset($this->$name)) {
                   30344:                 continue;
                   30345:             }
                   30346:             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
                   30347:                   $name == '_stack') {
                   30348:                 $a->$name = &$this->$name;
                   30349:             } else {
                   30350:                 $a->$name = $this->$name;
                   30351:             }
                   30352:         }
                   30353:         return $a;
                   30354:     }
                   30355: 
                   30356:     function &getDefaultGenerator()
                   30357:     {
                   30358:         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
                   30359:             require_once 'PEAR/PackageFile/Generator/v2.php';
                   30360:         }
                   30361:         $a = &new PEAR_PackageFile_Generator_v2($this);
                   30362:         return $a;
                   30363:     }
                   30364: 
                   30365:     function analyzeSourceCode($file, $string = false)
                   30366:     {
                   30367:         if (!isset($this->_v2Validator) ||
                   30368:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   30369:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   30370:                 require_once 'PEAR/PackageFile/v2/Validator.php';
                   30371:             }
                   30372:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   30373:         }
                   30374:         return $this->_v2Validator->analyzeSourceCode($file, $string);
                   30375:     }
                   30376: 
                   30377:     function validate($state = PEAR_VALIDATE_NORMAL)
                   30378:     {
                   30379:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   30380:             return false;
                   30381:         }
                   30382:         if (!isset($this->_v2Validator) ||
                   30383:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   30384:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   30385:                 require_once 'PEAR/PackageFile/v2/Validator.php';
                   30386:             }
                   30387:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   30388:         }
                   30389:         if (isset($this->_packageInfo['xsdversion'])) {
                   30390:             unset($this->_packageInfo['xsdversion']);
                   30391:         }
                   30392:         return $this->_v2Validator->validate($this, $state);
                   30393:     }
                   30394: 
                   30395:     function getTasksNs()
                   30396:     {
                   30397:         if (!isset($this->_tasksNs)) {
                   30398:             if (isset($this->_packageInfo['attribs'])) {
                   30399:                 foreach ($this->_packageInfo['attribs'] as $name => $value) {
                   30400:                     if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
                   30401:                         $this->_tasksNs = str_replace('xmlns:', '', $name);
                   30402:                         break;
                   30403:                     }
                   30404:                 }
                   30405:             }
                   30406:         }
                   30407:         return $this->_tasksNs;
                   30408:     }
                   30409: 
                   30410:     /**
                   30411:      * Determine whether a task name is a valid task.  Custom tasks may be defined
                   30412:      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
                   30413:      *
                   30414:      * Note that this method will auto-load the task class file and test for the existence
                   30415:      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
                   30416:      * PEAR_Task_mycustom_task
                   30417:      * @param string
                   30418:      * @return boolean
                   30419:      */
                   30420:     function getTask($task)
                   30421:     {
                   30422:         $this->getTasksNs();
                   30423:         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
                   30424:         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
                   30425:         $taskfile = str_replace(' ', '/', ucwords($task));
                   30426:         $task = str_replace(array(' ', '/'), '_', ucwords($task));
                   30427:         if (class_exists("PEAR_Task_$task")) {
                   30428:             return "PEAR_Task_$task";
                   30429:         }
                   30430:         $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
                   30431:         if ($fp) {
                   30432:             fclose($fp);
                   30433:             require_once "PEAR/Task/$taskfile.php";
                   30434:             return "PEAR_Task_$task";
                   30435:         }
                   30436:         return false;
                   30437:     }
                   30438: 
                   30439:     /**
                   30440:      * Key-friendly array_splice
                   30441:      * @param tagname to splice a value in before
                   30442:      * @param mixed the value to splice in
                   30443:      * @param string the new tag name
                   30444:      */
                   30445:     function _ksplice($array, $key, $value, $newkey)
                   30446:     {
                   30447:         $offset = array_search($key, array_keys($array));
                   30448:         $after = array_slice($array, $offset);
                   30449:         $before = array_slice($array, 0, $offset);
                   30450:         $before[$newkey] = $value;
                   30451:         return array_merge($before, $after);
                   30452:     }
                   30453: 
                   30454:     /**
                   30455:      * @param array a list of possible keys, in the order they may occur
                   30456:      * @param mixed contents of the new package.xml tag
                   30457:      * @param string tag name
                   30458:      * @access private
                   30459:      */
                   30460:     function _insertBefore($array, $keys, $contents, $newkey)
                   30461:     {
                   30462:         foreach ($keys as $key) {
                   30463:             if (isset($array[$key])) {
                   30464:                 return $array = $this->_ksplice($array, $key, $contents, $newkey);
                   30465:             }
                   30466:         }
                   30467:         $array[$newkey] = $contents;
                   30468:         return $array;
                   30469:     }
                   30470: 
                   30471:     /**
                   30472:      * @param subsection of {@link $_packageInfo}
                   30473:      * @param array|string tag contents
                   30474:      * @param array format:
                   30475:      * <pre>
                   30476:      * array(
                   30477:      *   tagname => array(list of tag names that follow this one),
                   30478:      *   childtagname => array(list of child tag names that follow this one),
                   30479:      * )
                   30480:      * </pre>
                   30481:      *
                   30482:      * This allows construction of nested tags
                   30483:      * @access private
                   30484:      */
                   30485:     function _mergeTag($manip, $contents, $order)
                   30486:     {
                   30487:         if (count($order)) {
                   30488:             foreach ($order as $tag => $curorder) {
                   30489:                 if (!isset($manip[$tag])) {
                   30490:                     // ensure that the tag is set up
                   30491:                     $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
                   30492:                 }
                   30493:                 if (count($order) > 1) {
                   30494:                     $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
                   30495:                     return $manip;
                   30496:                 }
                   30497:             }
                   30498:         } else {
                   30499:             return $manip;
                   30500:         }
                   30501:         if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
                   30502:             $manip[$tag][] = $contents;
                   30503:         } else {
                   30504:             if (!count($manip[$tag])) {
                   30505:                 $manip[$tag] = $contents;
                   30506:             } else {
                   30507:                 $manip[$tag] = array($manip[$tag]);
                   30508:                 $manip[$tag][] = $contents;
                   30509:             }
                   30510:         }
                   30511:         return $manip;
                   30512:     }
                   30513: }
                   30514: ?>
                   30515: PEAR-1.9.4/PEAR/REST/10.php0000644000076500000240000007772411605156760013514 0ustar  helgistaff<?php
                   30516: /**
                   30517:  * PEAR_REST_10
                   30518:  *
                   30519:  * PHP versions 4 and 5
                   30520:  *
                   30521:  * @category   pear
                   30522:  * @package    PEAR
                   30523:  * @author     Greg Beaver <cellog@php.net>
                   30524:  * @copyright  1997-2009 The Authors
                   30525:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   30526:  * @version    CVS: $Id: 10.php 313023 2011-07-06 19:17:11Z dufuz $
                   30527:  * @link       http://pear.php.net/package/PEAR
                   30528:  * @since      File available since Release 1.4.0a12
                   30529:  */
                   30530: 
                   30531: /**
                   30532:  * For downloading REST xml/txt files
                   30533:  */
                   30534: require_once 'PEAR/REST.php';
                   30535: 
                   30536: /**
                   30537:  * Implement REST 1.0
                   30538:  *
                   30539:  * @category   pear
                   30540:  * @package    PEAR
                   30541:  * @author     Greg Beaver <cellog@php.net>
                   30542:  * @copyright  1997-2009 The Authors
                   30543:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   30544:  * @version    Release: 1.9.4
                   30545:  * @link       http://pear.php.net/package/PEAR
                   30546:  * @since      Class available since Release 1.4.0a12
                   30547:  */
                   30548: class PEAR_REST_10
                   30549: {
                   30550:     /**
                   30551:      * @var PEAR_REST
                   30552:      */
                   30553:     var $_rest;
                   30554:     function PEAR_REST_10($config, $options = array())
                   30555:     {
                   30556:         $this->_rest = &new PEAR_REST($config, $options);
                   30557:     }
                   30558: 
                   30559:     /**
                   30560:      * Retrieve information about a remote package to be downloaded from a REST server
                   30561:      *
                   30562:      * @param string $base The uri to prepend to all REST calls
                   30563:      * @param array $packageinfo an array of format:
                   30564:      * <pre>
                   30565:      *  array(
                   30566:      *   'package' => 'packagename',
                   30567:      *   'channel' => 'channelname',
                   30568:      *  ['state' => 'alpha' (or valid state),]
                   30569:      *  -or-
                   30570:      *  ['version' => '1.whatever']
                   30571:      * </pre>
                   30572:      * @param string $prefstate Current preferred_state config variable value
                   30573:      * @param bool $installed the installed version of this package to compare against
                   30574:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   30575:      */
                   30576:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   30577:     {
                   30578:         $states = $this->betterStates($prefstate, true);
                   30579:         if (!$states) {
                   30580:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   30581:         }
                   30582: 
                   30583:         $channel  = $packageinfo['channel'];
                   30584:         $package  = $packageinfo['package'];
                   30585:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   30586:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
                   30587:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   30588: 
                   30589:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   30590:         if (PEAR::isError($info)) {
                   30591:             return PEAR::raiseError('No releases available for package "' .
                   30592:                 $channel . '/' . $package . '"');
                   30593:         }
                   30594: 
                   30595:         if (!isset($info['r'])) {
                   30596:             return false;
                   30597:         }
                   30598: 
                   30599:         $release = $found = false;
                   30600:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   30601:             $info['r'] = array($info['r']);
                   30602:         }
                   30603: 
                   30604:         foreach ($info['r'] as $release) {
                   30605:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   30606:                   version_compare($release['v'], $installed, '<'))) {
                   30607:                 continue;
                   30608:             }
                   30609: 
                   30610:             if (isset($state)) {
                   30611:                 // try our preferred state first
                   30612:                 if ($release['s'] == $state) {
                   30613:                     $found = true;
                   30614:                     break;
                   30615:                 }
                   30616:                 // see if there is something newer and more stable
                   30617:                 // bug #7221
                   30618:                 if (in_array($release['s'], $this->betterStates($state), true)) {
                   30619:                     $found = true;
                   30620:                     break;
                   30621:                 }
                   30622:             } elseif (isset($version)) {
                   30623:                 if ($release['v'] == $version) {
                   30624:                     $found = true;
                   30625:                     break;
                   30626:                 }
                   30627:             } else {
                   30628:                 if (in_array($release['s'], $states)) {
                   30629:                     $found = true;
                   30630:                     break;
                   30631:                 }
                   30632:             }
                   30633:         }
                   30634: 
                   30635:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   30636:     }
                   30637: 
                   30638:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   30639:                                $prefstate = 'stable', $installed = false, $channel = false)
                   30640:     {
                   30641:         $states = $this->betterStates($prefstate, true);
                   30642:         if (!$states) {
                   30643:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   30644:         }
                   30645: 
                   30646:         $channel  = $dependency['channel'];
                   30647:         $package  = $dependency['name'];
                   30648:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   30649:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
                   30650:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   30651: 
                   30652:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   30653:         if (PEAR::isError($info)) {
                   30654:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   30655:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   30656:         }
                   30657: 
                   30658:         if (!is_array($info) || !isset($info['r'])) {
                   30659:             return false;
                   30660:         }
                   30661: 
                   30662:         $exclude = array();
                   30663:         $min = $max = $recommended = false;
                   30664:         if ($xsdversion == '1.0') {
                   30665:             switch ($dependency['rel']) {
                   30666:                 case 'ge' :
                   30667:                     $min = $dependency['version'];
                   30668:                 break;
                   30669:                 case 'gt' :
                   30670:                     $min = $dependency['version'];
                   30671:                     $exclude = array($dependency['version']);
                   30672:                 break;
                   30673:                 case 'eq' :
                   30674:                     $recommended = $dependency['version'];
                   30675:                 break;
                   30676:                 case 'lt' :
                   30677:                     $max = $dependency['version'];
                   30678:                     $exclude = array($dependency['version']);
                   30679:                 break;
                   30680:                 case 'le' :
                   30681:                     $max = $dependency['version'];
                   30682:                 break;
                   30683:                 case 'ne' :
                   30684:                     $exclude = array($dependency['version']);
                   30685:                 break;
                   30686:             }
                   30687:         } else {
                   30688:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   30689:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   30690:             $recommended = isset($dependency['recommended']) ?
                   30691:                 $dependency['recommended'] : false;
                   30692:             if (isset($dependency['exclude'])) {
                   30693:                 if (!isset($dependency['exclude'][0])) {
                   30694:                     $exclude = array($dependency['exclude']);
                   30695:                 }
                   30696:             }
                   30697:         }
                   30698:         $release = $found = false;
                   30699:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   30700:             $info['r'] = array($info['r']);
                   30701:         }
                   30702:         foreach ($info['r'] as $release) {
                   30703:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   30704:                   version_compare($release['v'], $installed, '<'))) {
                   30705:                 continue;
                   30706:             }
                   30707:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   30708:                 continue;
                   30709:             }
                   30710:             // allow newer releases to say "I'm OK with the dependent package"
                   30711:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   30712:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   30713:                     $release['co'] = array($release['co']);
                   30714:                 }
                   30715:                 foreach ($release['co'] as $entry) {
                   30716:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   30717:                         $entry['x'] = array($entry['x']);
                   30718:                     } elseif (!isset($entry['x'])) {
                   30719:                         $entry['x'] = array();
                   30720:                     }
                   30721:                     if ($entry['c'] == $deppackage['channel'] &&
                   30722:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   30723:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   30724:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   30725:                           !in_array($release['v'], $entry['x'])) {
                   30726:                         $recommended = $release['v'];
                   30727:                         break;
                   30728:                     }
                   30729:                 }
                   30730:             }
                   30731:             if ($recommended) {
                   30732:                 if ($release['v'] != $recommended) { // if we want a specific
                   30733:                     // version, then skip all others
                   30734:                     continue;
                   30735:                 } else {
                   30736:                     if (!in_array($release['s'], $states)) {
                   30737:                         // the stability is too low, but we must return the
                   30738:                         // recommended version if possible
                   30739:                         return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                   30740:                     }
                   30741:                 }
                   30742:             }
                   30743:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   30744:                 continue;
                   30745:             }
                   30746:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   30747:                 continue;
                   30748:             }
                   30749:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   30750:                 continue;
                   30751:             }
                   30752:             if (in_array($release['s'], $states)) { // if in the preferred state...
                   30753:                 $found = true; // ... then use it
                   30754:                 break;
                   30755:             }
                   30756:         }
                   30757:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   30758:     }
                   30759: 
                   30760:     /**
                   30761:      * Take raw data and return the array needed for processing a download URL
                   30762:      *
                   30763:      * @param string $base REST base uri
                   30764:      * @param string $package Package name
                   30765:      * @param array $release an array of format array('v' => version, 's' => state)
                   30766:      *                       describing the release to download
                   30767:      * @param array $info list of all releases as defined by allreleases.xml
                   30768:      * @param bool|null $found determines whether the release was found or this is the next
                   30769:      *                    best alternative.  If null, then versions were skipped because
                   30770:      *                    of PHP dependency
                   30771:      * @return array|PEAR_Error
                   30772:      * @access private
                   30773:      */
                   30774:     function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
                   30775:     {
                   30776:         if (!$found) {
                   30777:             $release = $info['r'][0];
                   30778:         }
                   30779: 
                   30780:         $packageLower = strtolower($package);
                   30781:         $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
                   30782:             'info.xml', false, false, $channel);
                   30783:         if (PEAR::isError($pinfo)) {
                   30784:             return PEAR::raiseError('Package "' . $package .
                   30785:                 '" does not have REST info xml available');
                   30786:         }
                   30787: 
                   30788:         $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   30789:             $release['v'] . '.xml', false, false, $channel);
                   30790:         if (PEAR::isError($releaseinfo)) {
                   30791:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   30792:                 '" does not have REST xml available');
                   30793:         }
                   30794: 
                   30795:         $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   30796:             'deps.' . $release['v'] . '.txt', false, true, $channel);
                   30797:         if (PEAR::isError($packagexml)) {
                   30798:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   30799:                 '" does not have REST dependency information available');
                   30800:         }
                   30801: 
                   30802:         $packagexml = unserialize($packagexml);
                   30803:         if (!$packagexml) {
                   30804:             $packagexml = array();
                   30805:         }
                   30806: 
                   30807:         $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
                   30808:             '/allreleases.xml', false, false, $channel);
                   30809:         if (PEAR::isError($allinfo)) {
                   30810:             return $allinfo;
                   30811:         }
                   30812: 
                   30813:         if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
                   30814:             $allinfo['r'] = array($allinfo['r']);
                   30815:         }
                   30816: 
                   30817:         $compatible = false;
                   30818:         foreach ($allinfo['r'] as $release) {
                   30819:             if ($release['v'] != $releaseinfo['v']) {
                   30820:                 continue;
                   30821:             }
                   30822: 
                   30823:             if (!isset($release['co'])) {
                   30824:                 break;
                   30825:             }
                   30826: 
                   30827:             $compatible = array();
                   30828:             if (!is_array($release['co']) || !isset($release['co'][0])) {
                   30829:                 $release['co'] = array($release['co']);
                   30830:             }
                   30831: 
                   30832:             foreach ($release['co'] as $entry) {
                   30833:                 $comp = array();
                   30834:                 $comp['name']    = $entry['p'];
                   30835:                 $comp['channel'] = $entry['c'];
                   30836:                 $comp['min']     = $entry['min'];
                   30837:                 $comp['max']     = $entry['max'];
                   30838:                 if (isset($entry['x']) && !is_array($entry['x'])) {
                   30839:                     $comp['exclude'] = $entry['x'];
                   30840:                 }
                   30841: 
                   30842:                 $compatible[] = $comp;
                   30843:             }
                   30844: 
                   30845:             if (count($compatible) == 1) {
                   30846:                 $compatible = $compatible[0];
                   30847:             }
                   30848: 
                   30849:             break;
                   30850:         }
                   30851: 
                   30852:         $deprecated = false;
                   30853:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   30854:             if (is_array($pinfo['dp'])) {
                   30855:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   30856:                                     'package' => trim($pinfo['dp']['_content']));
                   30857:             } else {
                   30858:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   30859:                                     'package' => trim($pinfo['dp']));
                   30860:             }
                   30861:         }
                   30862: 
                   30863:         $return = array(
                   30864:             'version'    => $releaseinfo['v'],
                   30865:             'info'       => $packagexml,
                   30866:             'package'    => $releaseinfo['p']['_content'],
                   30867:             'stability'  => $releaseinfo['st'],
                   30868:             'compatible' => $compatible,
                   30869:             'deprecated' => $deprecated,
                   30870:         );
                   30871: 
                   30872:         if ($found) {
                   30873:             $return['url'] = $releaseinfo['g'];
                   30874:             return $return;
                   30875:         }
                   30876: 
                   30877:         $return['php'] = $phpversion;
                   30878:         return $return;
                   30879:     }
                   30880: 
                   30881:     function listPackages($base, $channel = false)
                   30882:     {
                   30883:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   30884:         if (PEAR::isError($packagelist)) {
                   30885:             return $packagelist;
                   30886:         }
                   30887: 
                   30888:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   30889:             return array();
                   30890:         }
                   30891: 
                   30892:         if (!is_array($packagelist['p'])) {
                   30893:             $packagelist['p'] = array($packagelist['p']);
                   30894:         }
                   30895: 
                   30896:         return $packagelist['p'];
                   30897:     }
                   30898: 
                   30899:     /**
                   30900:      * List all categories of a REST server
                   30901:      *
                   30902:      * @param string $base base URL of the server
                   30903:      * @return array of categorynames
                   30904:      */
                   30905:     function listCategories($base, $channel = false)
                   30906:     {
                   30907:         $categories = array();
                   30908: 
                   30909:         // c/categories.xml does not exist;
                   30910:         // check for every package its category manually
                   30911:         // This is SLOOOWWWW : ///
                   30912:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   30913:         if (PEAR::isError($packagelist)) {
                   30914:             return $packagelist;
                   30915:         }
                   30916: 
                   30917:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   30918:             $ret = array();
                   30919:             return $ret;
                   30920:         }
                   30921: 
                   30922:         if (!is_array($packagelist['p'])) {
                   30923:             $packagelist['p'] = array($packagelist['p']);
                   30924:         }
                   30925: 
                   30926:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   30927:         foreach ($packagelist['p'] as $package) {
                   30928:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   30929:                 if (PEAR::isError($inf)) {
                   30930:                     PEAR::popErrorHandling();
                   30931:                     return $inf;
                   30932:                 }
                   30933:                 $cat = $inf['ca']['_content'];
                   30934:                 if (!isset($categories[$cat])) {
                   30935:                     $categories[$cat] = $inf['ca'];
                   30936:                 }
                   30937:         }
                   30938: 
                   30939:         return array_values($categories);
                   30940:     }
                   30941: 
                   30942:     /**
                   30943:      * List a category of a REST server
                   30944:      *
                   30945:      * @param string $base base URL of the server
                   30946:      * @param string $category name of the category
                   30947:      * @param boolean $info also download full package info
                   30948:      * @return array of packagenames
                   30949:      */
                   30950:     function listCategory($base, $category, $info = false, $channel = false)
                   30951:     {
                   30952:         // gives '404 Not Found' error when category doesn't exist
                   30953:         $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
                   30954:         if (PEAR::isError($packagelist)) {
                   30955:             return $packagelist;
                   30956:         }
                   30957: 
                   30958:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   30959:             return array();
                   30960:         }
                   30961: 
                   30962:         if (!is_array($packagelist['p']) ||
                   30963:             !isset($packagelist['p'][0])) { // only 1 pkg
                   30964:             $packagelist = array($packagelist['p']);
                   30965:         } else {
                   30966:             $packagelist = $packagelist['p'];
                   30967:         }
                   30968: 
                   30969:         if ($info == true) {
                   30970:             // get individual package info
                   30971:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   30972:             foreach ($packagelist as $i => $packageitem) {
                   30973:                 $url = sprintf('%s'.'r/%s/latest.txt',
                   30974:                         $base,
                   30975:                         strtolower($packageitem['_content']));
                   30976:                 $version = $this->_rest->retrieveData($url, false, false, $channel);
                   30977:                 if (PEAR::isError($version)) {
                   30978:                     break; // skipit
                   30979:                 }
                   30980:                 $url = sprintf('%s'.'r/%s/%s.xml',
                   30981:                         $base,
                   30982:                         strtolower($packageitem['_content']),
                   30983:                         $version);
                   30984:                 $info = $this->_rest->retrieveData($url, false, false, $channel);
                   30985:                 if (PEAR::isError($info)) {
                   30986:                     break; // skipit
                   30987:                 }
                   30988:                 $packagelist[$i]['info'] = $info;
                   30989:             }
                   30990:             PEAR::popErrorHandling();
                   30991:         }
                   30992: 
                   30993:         return $packagelist;
                   30994:     }
                   30995: 
                   30996: 
                   30997:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
                   30998:     {
                   30999:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31000:         if (PEAR::isError($packagelist)) {
                   31001:             return $packagelist;
                   31002:         }
                   31003:         if ($this->_rest->config->get('verbose') > 0) {
                   31004:             $ui = &PEAR_Frontend::singleton();
                   31005:             $ui->log('Retrieving data...0%', true);
                   31006:         }
                   31007:         $ret = array();
                   31008:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31009:             return $ret;
                   31010:         }
                   31011:         if (!is_array($packagelist['p'])) {
                   31012:             $packagelist['p'] = array($packagelist['p']);
                   31013:         }
                   31014: 
                   31015:         // only search-packagename = quicksearch !
                   31016:         if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
                   31017:             $newpackagelist = array();
                   31018:             foreach ($packagelist['p'] as $package) {
                   31019:                 if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
                   31020:                     $newpackagelist[] = $package;
                   31021:                 }
                   31022:             }
                   31023:             $packagelist['p'] = $newpackagelist;
                   31024:         }
                   31025:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31026:         $next = .1;
                   31027:         foreach ($packagelist['p'] as $progress => $package) {
                   31028:             if ($this->_rest->config->get('verbose') > 0) {
                   31029:                 if ($progress / count($packagelist['p']) >= $next) {
                   31030:                     if ($next == .5) {
                   31031:                         $ui->log('50%', false);
                   31032:                     } else {
                   31033:                         $ui->log('.', false);
                   31034:                     }
                   31035:                     $next += .1;
                   31036:                 }
                   31037:             }
                   31038: 
                   31039:             if ($basic) { // remote-list command
                   31040:                 if ($dostable) {
                   31041:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31042:                         '/stable.txt', false, false, $channel);
                   31043:                 } else {
                   31044:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31045:                         '/latest.txt', false, false, $channel);
                   31046:                 }
                   31047:                 if (PEAR::isError($latest)) {
                   31048:                     $latest = false;
                   31049:                 }
                   31050:                 $info = array('stable' => $latest);
                   31051:             } else { // list-all command
                   31052:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   31053:                 if (PEAR::isError($inf)) {
                   31054:                     PEAR::popErrorHandling();
                   31055:                     return $inf;
                   31056:                 }
                   31057:                 if ($searchpackage) {
                   31058:                     $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
                   31059:                     if (!$found && !(isset($searchsummary) && !empty($searchsummary)
                   31060:                         && (stristr($inf['s'], $searchsummary) !== false
                   31061:                             || stristr($inf['d'], $searchsummary) !== false)))
                   31062:                     {
                   31063:                         continue;
                   31064:                     };
                   31065:                 }
                   31066:                 $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31067:                     '/allreleases.xml', false, false, $channel);
                   31068:                 if (PEAR::isError($releases)) {
                   31069:                     continue;
                   31070:                 }
                   31071:                 if (!isset($releases['r'][0])) {
                   31072:                     $releases['r'] = array($releases['r']);
                   31073:                 }
                   31074:                 unset($latest);
                   31075:                 unset($unstable);
                   31076:                 unset($stable);
                   31077:                 unset($state);
                   31078:                 foreach ($releases['r'] as $release) {
                   31079:                     if (!isset($latest)) {
                   31080:                         if ($dostable && $release['s'] == 'stable') {
                   31081:                             $latest = $release['v'];
                   31082:                             $state = 'stable';
                   31083:                         }
                   31084:                         if (!$dostable) {
                   31085:                             $latest = $release['v'];
                   31086:                             $state = $release['s'];
                   31087:                         }
                   31088:                     }
                   31089:                     if (!isset($stable) && $release['s'] == 'stable') {
                   31090:                         $stable = $release['v'];
                   31091:                         if (!isset($unstable)) {
                   31092:                             $unstable = $stable;
                   31093:                         }
                   31094:                     }
                   31095:                     if (!isset($unstable) && $release['s'] != 'stable') {
                   31096:                         $latest = $unstable = $release['v'];
                   31097:                         $state = $release['s'];
                   31098:                     }
                   31099:                     if (isset($latest) && !isset($state)) {
                   31100:                         $state = $release['s'];
                   31101:                     }
                   31102:                     if (isset($latest) && isset($stable) && isset($unstable)) {
                   31103:                         break;
                   31104:                     }
                   31105:                 }
                   31106:                 $deps = array();
                   31107:                 if (!isset($unstable)) {
                   31108:                     $unstable = false;
                   31109:                     $state = 'stable';
                   31110:                     if (isset($stable)) {
                   31111:                         $latest = $unstable = $stable;
                   31112:                     }
                   31113:                 } else {
                   31114:                     $latest = $unstable;
                   31115:                 }
                   31116:                 if (!isset($latest)) {
                   31117:                     $latest = false;
                   31118:                 }
                   31119:                 if ($latest) {
                   31120:                     $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   31121:                         $latest . '.txt', false, false, $channel);
                   31122:                     if (!PEAR::isError($d)) {
                   31123:                         $d = unserialize($d);
                   31124:                         if ($d) {
                   31125:                             if (isset($d['required'])) {
                   31126:                                 if (!class_exists('PEAR_PackageFile_v2')) {
                   31127:                                     require_once 'PEAR/PackageFile/v2.php';
                   31128:                                 }
                   31129:                                 if (!isset($pf)) {
                   31130:                                     $pf = new PEAR_PackageFile_v2;
                   31131:                                 }
                   31132:                                 $pf->setDeps($d);
                   31133:                                 $tdeps = $pf->getDeps();
                   31134:                             } else {
                   31135:                                 $tdeps = $d;
                   31136:                             }
                   31137:                             foreach ($tdeps as $dep) {
                   31138:                                 if ($dep['type'] !== 'pkg') {
                   31139:                                     continue;
                   31140:                                 }
                   31141:                                 $deps[] = $dep;
                   31142:                             }
                   31143:                         }
                   31144:                     }
                   31145:                 }
                   31146:                 if (!isset($stable)) {
                   31147:                     $stable = '-n/a-';
                   31148:                 }
                   31149:                 if (!$searchpackage) {
                   31150:                     $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
                   31151:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   31152:                         'unstable' => $unstable, 'state' => $state);
                   31153:                 } else {
                   31154:                     $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
                   31155:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   31156:                         'unstable' => $unstable, 'state' => $state);
                   31157:                 }
                   31158:             }
                   31159:             $ret[$package] = $info;
                   31160:         }
                   31161:         PEAR::popErrorHandling();
                   31162:         return $ret;
                   31163:     }
                   31164: 
                   31165:     function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
                   31166:     {
                   31167:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31168:         if (PEAR::isError($packagelist)) {
                   31169:             return $packagelist;
                   31170:         }
                   31171: 
                   31172:         $ret = array();
                   31173:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31174:             return $ret;
                   31175:         }
                   31176: 
                   31177:         if (!is_array($packagelist['p'])) {
                   31178:             $packagelist['p'] = array($packagelist['p']);
                   31179:         }
                   31180: 
                   31181:         foreach ($packagelist['p'] as $package) {
                   31182:             if (!isset($installed[strtolower($package)])) {
                   31183:                 continue;
                   31184:             }
                   31185: 
                   31186:             $inst_version = $reg->packageInfo($package, 'version', $channel);
                   31187:             $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                   31188:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31189:             $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31190:                 '/allreleases.xml', false, false, $channel);
                   31191:             PEAR::popErrorHandling();
                   31192:             if (PEAR::isError($info)) {
                   31193:                 continue; // no remote releases
                   31194:             }
                   31195: 
                   31196:             if (!isset($info['r'])) {
                   31197:                 continue;
                   31198:             }
                   31199: 
                   31200:             $release = $found = false;
                   31201:             if (!is_array($info['r']) || !isset($info['r'][0])) {
                   31202:                 $info['r'] = array($info['r']);
                   31203:             }
                   31204: 
                   31205:             // $info['r'] is sorted by version number
                   31206:             usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
                   31207:             foreach ($info['r'] as $release) {
                   31208:                 if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
                   31209:                     // not newer than the one installed
                   31210:                     break;
                   31211:                 }
                   31212: 
                   31213:                 // new version > installed version
                   31214:                 if (!$pref_state) {
                   31215:                     // every state is a good state
                   31216:                     $found = true;
                   31217:                     break;
                   31218:                 } else {
                   31219:                     $new_state = $release['s'];
                   31220:                     // if new state >= installed state: go
                   31221:                     if (in_array($new_state, $this->betterStates($inst_state, true))) {
                   31222:                         $found = true;
                   31223:                         break;
                   31224:                     } else {
                   31225:                         // only allow to lower the state of package,
                   31226:                         // if new state >= preferred state: go
                   31227:                         if (in_array($new_state, $this->betterStates($pref_state, true))) {
                   31228:                             $found = true;
                   31229:                             break;
                   31230:                         }
                   31231:                     }
                   31232:                 }
                   31233:             }
                   31234: 
                   31235:             if (!$found) {
                   31236:                 continue;
                   31237:             }
                   31238: 
                   31239:             $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
                   31240:                 $release['v'] . '.xml', false, false, $channel);
                   31241:             if (PEAR::isError($relinfo)) {
                   31242:                 return $relinfo;
                   31243:             }
                   31244: 
                   31245:             $ret[$package] = array(
                   31246:                 'version'  => $release['v'],
                   31247:                 'state'    => $release['s'],
                   31248:                 'filesize' => $relinfo['f'],
                   31249:             );
                   31250:         }
                   31251: 
                   31252:         return $ret;
                   31253:     }
                   31254: 
                   31255:     function packageInfo($base, $package, $channel = false)
                   31256:     {
                   31257:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31258:         $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   31259:         if (PEAR::isError($pinfo)) {
                   31260:             PEAR::popErrorHandling();
                   31261:             return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
                   31262:                 $pinfo->getMessage());
                   31263:         }
                   31264: 
                   31265:         $releases = array();
                   31266:         $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31267:             '/allreleases.xml', false, false, $channel);
                   31268:         if (!PEAR::isError($allreleases)) {
                   31269:             if (!class_exists('PEAR_PackageFile_v2')) {
                   31270:                 require_once 'PEAR/PackageFile/v2.php';
                   31271:             }
                   31272: 
                   31273:             if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
                   31274:                 $allreleases['r'] = array($allreleases['r']);
                   31275:             }
                   31276: 
                   31277:             $pf = new PEAR_PackageFile_v2;
                   31278:             foreach ($allreleases['r'] as $release) {
                   31279:                 $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   31280:                     $release['v'] . '.txt', false, false, $channel);
                   31281:                 if (PEAR::isError($ds)) {
                   31282:                     continue;
                   31283:                 }
                   31284: 
                   31285:                 if (!isset($latest)) {
                   31286:                     $latest = $release['v'];
                   31287:                 }
                   31288: 
                   31289:                 $pf->setDeps(unserialize($ds));
                   31290:                 $ds = $pf->getDeps();
                   31291:                 $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
                   31292:                     . '/' . $release['v'] . '.xml', false, false, $channel);
                   31293: 
                   31294:                 if (PEAR::isError($info)) {
                   31295:                     continue;
                   31296:                 }
                   31297: 
                   31298:                 $releases[$release['v']] = array(
                   31299:                     'doneby' => $info['m'],
                   31300:                     'license' => $info['l'],
                   31301:                     'summary' => $info['s'],
                   31302:                     'description' => $info['d'],
                   31303:                     'releasedate' => $info['da'],
                   31304:                     'releasenotes' => $info['n'],
                   31305:                     'state' => $release['s'],
                   31306:                     'deps' => $ds ? $ds : array(),
                   31307:                 );
                   31308:             }
                   31309:         } else {
                   31310:             $latest = '';
                   31311:         }
                   31312: 
                   31313:         PEAR::popErrorHandling();
                   31314:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   31315:             if (is_array($pinfo['dp'])) {
                   31316:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31317:                                     'package' => trim($pinfo['dp']['_content']));
                   31318:             } else {
                   31319:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31320:                                     'package' => trim($pinfo['dp']));
                   31321:             }
                   31322:         } else {
                   31323:             $deprecated = false;
                   31324:         }
                   31325: 
                   31326:         if (!isset($latest)) {
                   31327:             $latest = '';
                   31328:         }
                   31329: 
                   31330:         return array(
                   31331:             'name' => $pinfo['n'],
                   31332:             'channel' => $pinfo['c'],
                   31333:             'category' => $pinfo['ca']['_content'],
                   31334:             'stable' => $latest,
                   31335:             'license' => $pinfo['l'],
                   31336:             'summary' => $pinfo['s'],
                   31337:             'description' => $pinfo['d'],
                   31338:             'releases' => $releases,
                   31339:             'deprecated' => $deprecated,
                   31340:             );
                   31341:     }
                   31342: 
                   31343:     /**
                   31344:      * Return an array containing all of the states that are more stable than
                   31345:      * or equal to the passed in state
                   31346:      *
                   31347:      * @param string Release state
                   31348:      * @param boolean Determines whether to include $state in the list
                   31349:      * @return false|array False if $state is not a valid release state
                   31350:      */
                   31351:     function betterStates($state, $include = false)
                   31352:     {
                   31353:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   31354:         $i = array_search($state, $states);
                   31355:         if ($i === false) {
                   31356:             return false;
                   31357:         }
                   31358: 
                   31359:         if ($include) {
                   31360:             $i--;
                   31361:         }
                   31362: 
                   31363:         return array_slice($states, $i + 1);
                   31364:     }
                   31365: 
                   31366:     /**
                   31367:      * Sort releases by version number
                   31368:      *
                   31369:      * @access private
                   31370:      */
                   31371:     function _sortReleasesByVersionNumber($a, $b)
                   31372:     {
                   31373:         if (version_compare($a['v'], $b['v'], '=')) {
                   31374:             return 0;
                   31375:         }
                   31376: 
                   31377:         if (version_compare($a['v'], $b['v'], '>')) {
                   31378:             return -1;
                   31379:         }
                   31380: 
                   31381:         if (version_compare($a['v'], $b['v'], '<')) {
                   31382:             return 1;
                   31383:         }
                   31384:     }
                   31385: }PEAR-1.9.4/PEAR/REST/11.php0000644000076500000240000002605411605156760013503 0ustar  helgistaff<?php
                   31386: /**
                   31387:  * PEAR_REST_11 - implement faster list-all/remote-list command
                   31388:  *
                   31389:  * PHP versions 4 and 5
                   31390:  *
                   31391:  * @category   pear
                   31392:  * @package    PEAR
                   31393:  * @author     Greg Beaver <cellog@php.net>
                   31394:  * @copyright  1997-2009 The Authors
                   31395:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31396:  * @version    CVS: $Id: 11.php 313023 2011-07-06 19:17:11Z dufuz $
                   31397:  * @link       http://pear.php.net/package/PEAR
                   31398:  * @since      File available since Release 1.4.3
                   31399:  */
                   31400: 
                   31401: /**
                   31402:  * For downloading REST xml/txt files
                   31403:  */
                   31404: require_once 'PEAR/REST.php';
                   31405: 
                   31406: /**
                   31407:  * Implement REST 1.1
                   31408:  *
                   31409:  * @category   pear
                   31410:  * @package    PEAR
                   31411:  * @author     Greg Beaver <cellog@php.net>
                   31412:  * @copyright  1997-2009 The Authors
                   31413:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31414:  * @version    Release: 1.9.4
                   31415:  * @link       http://pear.php.net/package/PEAR
                   31416:  * @since      Class available since Release 1.4.3
                   31417:  */
                   31418: class PEAR_REST_11
                   31419: {
                   31420:     /**
                   31421:      * @var PEAR_REST
                   31422:      */
                   31423:     var $_rest;
                   31424: 
                   31425:     function PEAR_REST_11($config, $options = array())
                   31426:     {
                   31427:         $this->_rest = &new PEAR_REST($config, $options);
                   31428:     }
                   31429: 
                   31430:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
                   31431:     {
                   31432:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
                   31433:         if (PEAR::isError($categorylist)) {
                   31434:             return $categorylist;
                   31435:         }
                   31436: 
                   31437:         $ret = array();
                   31438:         if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
                   31439:             $categorylist['c'] = array($categorylist['c']);
                   31440:         }
                   31441: 
                   31442:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31443: 
                   31444:         foreach ($categorylist['c'] as $progress => $category) {
                   31445:             $category = $category['_content'];
                   31446:             $packagesinfo = $this->_rest->retrieveData($base .
                   31447:                 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
                   31448: 
                   31449:             if (PEAR::isError($packagesinfo)) {
                   31450:                 continue;
                   31451:             }
                   31452: 
                   31453:             if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
                   31454:                 continue;
                   31455:             }
                   31456: 
                   31457:             if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
                   31458:                 $packagesinfo['pi'] = array($packagesinfo['pi']);
                   31459:             }
                   31460: 
                   31461:             foreach ($packagesinfo['pi'] as $packageinfo) {
                   31462:                 if (empty($packageinfo)) {
                   31463:                     continue;
                   31464:                 }
                   31465: 
                   31466:                 $info     = $packageinfo['p'];
                   31467:                 $package  = $info['n'];
                   31468:                 $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
                   31469:                 unset($latest);
                   31470:                 unset($unstable);
                   31471:                 unset($stable);
                   31472:                 unset($state);
                   31473: 
                   31474:                 if ($releases) {
                   31475:                     if (!isset($releases['r'][0])) {
                   31476:                         $releases['r'] = array($releases['r']);
                   31477:                     }
                   31478: 
                   31479:                     foreach ($releases['r'] as $release) {
                   31480:                         if (!isset($latest)) {
                   31481:                             if ($dostable && $release['s'] == 'stable') {
                   31482:                                 $latest = $release['v'];
                   31483:                                 $state = 'stable';
                   31484:                             }
                   31485:                             if (!$dostable) {
                   31486:                                 $latest = $release['v'];
                   31487:                                 $state = $release['s'];
                   31488:                             }
                   31489:                         }
                   31490: 
                   31491:                         if (!isset($stable) && $release['s'] == 'stable') {
                   31492:                             $stable = $release['v'];
                   31493:                             if (!isset($unstable)) {
                   31494:                                 $unstable = $stable;
                   31495:                             }
                   31496:                         }
                   31497: 
                   31498:                         if (!isset($unstable) && $release['s'] != 'stable') {
                   31499:                             $unstable = $release['v'];
                   31500:                             $state = $release['s'];
                   31501:                         }
                   31502: 
                   31503:                         if (isset($latest) && !isset($state)) {
                   31504:                             $state = $release['s'];
                   31505:                         }
                   31506: 
                   31507:                         if (isset($latest) && isset($stable) && isset($unstable)) {
                   31508:                             break;
                   31509:                         }
                   31510:                     }
                   31511:                 }
                   31512: 
                   31513:                 if ($basic) { // remote-list command
                   31514:                     if (!isset($latest)) {
                   31515:                         $latest = false;
                   31516:                     }
                   31517: 
                   31518:                     if ($dostable) {
                   31519:                         // $state is not set if there are no releases
                   31520:                         if (isset($state) && $state == 'stable') {
                   31521:                             $ret[$package] = array('stable' => $latest);
                   31522:                         } else {
                   31523:                             $ret[$package] = array('stable' => '-n/a-');
                   31524:                         }
                   31525:                     } else {
                   31526:                         $ret[$package] = array('stable' => $latest);
                   31527:                     }
                   31528: 
                   31529:                     continue;
                   31530:                 }
                   31531: 
                   31532:                 // list-all command
                   31533:                 if (!isset($unstable)) {
                   31534:                     $unstable = false;
                   31535:                     $state = 'stable';
                   31536:                     if (isset($stable)) {
                   31537:                         $latest = $unstable = $stable;
                   31538:                     }
                   31539:                 } else {
                   31540:                     $latest = $unstable;
                   31541:                 }
                   31542: 
                   31543:                 if (!isset($latest)) {
                   31544:                     $latest = false;
                   31545:                 }
                   31546: 
                   31547:                 $deps = array();
                   31548:                 if ($latest && isset($packageinfo['deps'])) {
                   31549:                     if (!is_array($packageinfo['deps']) ||
                   31550:                           !isset($packageinfo['deps'][0])
                   31551:                     ) {
                   31552:                         $packageinfo['deps'] = array($packageinfo['deps']);
                   31553:                     }
                   31554: 
                   31555:                     $d = false;
                   31556:                     foreach ($packageinfo['deps'] as $dep) {
                   31557:                         if ($dep['v'] == $latest) {
                   31558:                             $d = unserialize($dep['d']);
                   31559:                         }
                   31560:                     }
                   31561: 
                   31562:                     if ($d) {
                   31563:                         if (isset($d['required'])) {
                   31564:                             if (!class_exists('PEAR_PackageFile_v2')) {
                   31565:                                 require_once 'PEAR/PackageFile/v2.php';
                   31566:                             }
                   31567: 
                   31568:                             if (!isset($pf)) {
                   31569:                                 $pf = new PEAR_PackageFile_v2;
                   31570:                             }
                   31571: 
                   31572:                             $pf->setDeps($d);
                   31573:                             $tdeps = $pf->getDeps();
                   31574:                         } else {
                   31575:                             $tdeps = $d;
                   31576:                         }
                   31577: 
                   31578:                         foreach ($tdeps as $dep) {
                   31579:                             if ($dep['type'] !== 'pkg') {
                   31580:                                 continue;
                   31581:                             }
                   31582: 
                   31583:                             $deps[] = $dep;
                   31584:                         }
                   31585:                     }
                   31586:                 }
                   31587: 
                   31588:                 $info = array(
                   31589:                     'stable'      => $latest,
                   31590:                     'summary'     => $info['s'],
                   31591:                     'description' => $info['d'],
                   31592:                     'deps'        => $deps,
                   31593:                     'category'    => $info['ca']['_content'],
                   31594:                     'unstable'    => $unstable,
                   31595:                     'state'       => $state
                   31596:                 );
                   31597:                 $ret[$package] = $info;
                   31598:             }
                   31599:         }
                   31600: 
                   31601:         PEAR::popErrorHandling();
                   31602:         return $ret;
                   31603:     }
                   31604: 
                   31605:     /**
                   31606:      * List all categories of a REST server
                   31607:      *
                   31608:      * @param string $base base URL of the server
                   31609:      * @return array of categorynames
                   31610:      */
                   31611:     function listCategories($base, $channel = false)
                   31612:     {
                   31613:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
                   31614:         if (PEAR::isError($categorylist)) {
                   31615:             return $categorylist;
                   31616:         }
                   31617: 
                   31618:         if (!is_array($categorylist) || !isset($categorylist['c'])) {
                   31619:             return array();
                   31620:         }
                   31621: 
                   31622:         if (isset($categorylist['c']['_content'])) {
                   31623:             // only 1 category
                   31624:             $categorylist['c'] = array($categorylist['c']);
                   31625:         }
                   31626: 
                   31627:         return $categorylist['c'];
                   31628:     }
                   31629: 
                   31630:     /**
                   31631:      * List packages in a category of a REST server
                   31632:      *
                   31633:      * @param string $base base URL of the server
                   31634:      * @param string $category name of the category
                   31635:      * @param boolean $info also download full package info
                   31636:      * @return array of packagenames
                   31637:      */
                   31638:     function listCategory($base, $category, $info = false, $channel = false)
                   31639:     {
                   31640:         if ($info == false) {
                   31641:             $url = '%s'.'c/%s/packages.xml';
                   31642:         } else {
                   31643:             $url = '%s'.'c/%s/packagesinfo.xml';
                   31644:         }
                   31645:         $url = sprintf($url,
                   31646:                     $base,
                   31647:                     urlencode($category));
                   31648: 
                   31649:         // gives '404 Not Found' error when category doesn't exist
                   31650:         $packagelist = $this->_rest->retrieveData($url, false, false, $channel);
                   31651:         if (PEAR::isError($packagelist)) {
                   31652:             return $packagelist;
                   31653:         }
                   31654:         if (!is_array($packagelist)) {
                   31655:             return array();
                   31656:         }
                   31657: 
                   31658:         if ($info == false) {
                   31659:             if (!isset($packagelist['p'])) {
                   31660:                 return array();
                   31661:             }
                   31662:             if (!is_array($packagelist['p']) ||
                   31663:                 !isset($packagelist['p'][0])) { // only 1 pkg
                   31664:                 $packagelist = array($packagelist['p']);
                   31665:             } else {
                   31666:                 $packagelist = $packagelist['p'];
                   31667:             }
                   31668:             return $packagelist;
                   31669:         }
                   31670: 
                   31671:         // info == true
                   31672:         if (!isset($packagelist['pi'])) {
                   31673:             return array();
                   31674:         }
                   31675: 
                   31676:         if (!is_array($packagelist['pi']) ||
                   31677:             !isset($packagelist['pi'][0])) { // only 1 pkg
                   31678:             $packagelist_pre = array($packagelist['pi']);
                   31679:         } else {
                   31680:             $packagelist_pre = $packagelist['pi'];
                   31681:         }
                   31682: 
                   31683:         $packagelist = array();
                   31684:         foreach ($packagelist_pre as $i => $item) {
                   31685:             // compatibility with r/<latest.txt>.xml
                   31686:             if (isset($item['a']['r'][0])) {
                   31687:                 // multiple releases
                   31688:                 $item['p']['v'] = $item['a']['r'][0]['v'];
                   31689:                 $item['p']['st'] = $item['a']['r'][0]['s'];
                   31690:             } elseif (isset($item['a'])) {
                   31691:                 // first and only release
                   31692:                 $item['p']['v'] = $item['a']['r']['v'];
                   31693:                 $item['p']['st'] = $item['a']['r']['s'];
                   31694:             }
                   31695: 
                   31696:             $packagelist[$i] = array('attribs' => $item['p']['r'],
                   31697:                                      '_content' => $item['p']['n'],
                   31698:                                      'info' => $item['p']);
                   31699:         }
                   31700: 
                   31701:         return $packagelist;
                   31702:     }
                   31703: 
                   31704:     /**
                   31705:      * Return an array containing all of the states that are more stable than
                   31706:      * or equal to the passed in state
                   31707:      *
                   31708:      * @param string Release state
                   31709:      * @param boolean Determines whether to include $state in the list
                   31710:      * @return false|array False if $state is not a valid release state
                   31711:      */
                   31712:     function betterStates($state, $include = false)
                   31713:     {
                   31714:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   31715:         $i = array_search($state, $states);
                   31716:         if ($i === false) {
                   31717:             return false;
                   31718:         }
                   31719:         if ($include) {
                   31720:             $i--;
                   31721:         }
                   31722:         return array_slice($states, $i + 1);
                   31723:     }
                   31724: }
                   31725: ?>PEAR-1.9.4/PEAR/REST/13.php0000644000076500000240000002654411605156760013511 0ustar  helgistaff<?php
                   31726: /**
                   31727:  * PEAR_REST_13
                   31728:  *
                   31729:  * PHP versions 4 and 5
                   31730:  *
                   31731:  * @category   pear
                   31732:  * @package    PEAR
                   31733:  * @author     Greg Beaver <cellog@php.net>
                   31734:  * @copyright  1997-2009 The Authors
                   31735:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31736:  * @version    CVS: $Id: 13.php 313023 2011-07-06 19:17:11Z dufuz $
                   31737:  * @link       http://pear.php.net/package/PEAR
                   31738:  * @since      File available since Release 1.4.0a12
                   31739:  */
                   31740: 
                   31741: /**
                   31742:  * For downloading REST xml/txt files
                   31743:  */
                   31744: require_once 'PEAR/REST.php';
                   31745: require_once 'PEAR/REST/10.php';
                   31746: 
                   31747: /**
                   31748:  * Implement REST 1.3
                   31749:  *
                   31750:  * @category   pear
                   31751:  * @package    PEAR
                   31752:  * @author     Greg Beaver <cellog@php.net>
                   31753:  * @copyright  1997-2009 The Authors
                   31754:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31755:  * @version    Release: 1.9.4
                   31756:  * @link       http://pear.php.net/package/PEAR
                   31757:  * @since      Class available since Release 1.4.0a12
                   31758:  */
                   31759: class PEAR_REST_13 extends PEAR_REST_10
                   31760: {
                   31761:     /**
                   31762:      * Retrieve information about a remote package to be downloaded from a REST server
                   31763:      *
                   31764:      * This is smart enough to resolve the minimum PHP version dependency prior to download
                   31765:      * @param string $base The uri to prepend to all REST calls
                   31766:      * @param array $packageinfo an array of format:
                   31767:      * <pre>
                   31768:      *  array(
                   31769:      *   'package' => 'packagename',
                   31770:      *   'channel' => 'channelname',
                   31771:      *  ['state' => 'alpha' (or valid state),]
                   31772:      *  -or-
                   31773:      *  ['version' => '1.whatever']
                   31774:      * </pre>
                   31775:      * @param string $prefstate Current preferred_state config variable value
                   31776:      * @param bool $installed the installed version of this package to compare against
                   31777:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   31778:      */
                   31779:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   31780:     {
                   31781:         $states = $this->betterStates($prefstate, true);
                   31782:         if (!$states) {
                   31783:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   31784:         }
                   31785: 
                   31786:         $channel  = $packageinfo['channel'];
                   31787:         $package  = $packageinfo['package'];
                   31788:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   31789:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
                   31790:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
                   31791: 
                   31792:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   31793:         if (PEAR::isError($info)) {
                   31794:             return PEAR::raiseError('No releases available for package "' .
                   31795:                 $channel . '/' . $package . '"');
                   31796:         }
                   31797: 
                   31798:         if (!isset($info['r'])) {
                   31799:             return false;
                   31800:         }
                   31801: 
                   31802:         $release = $found = false;
                   31803:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   31804:             $info['r'] = array($info['r']);
                   31805:         }
                   31806: 
                   31807:         $skippedphp = false;
                   31808:         foreach ($info['r'] as $release) {
                   31809:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   31810:                   version_compare($release['v'], $installed, '<'))) {
                   31811:                 continue;
                   31812:             }
                   31813: 
                   31814:             if (isset($state)) {
                   31815:                 // try our preferred state first
                   31816:                 if ($release['s'] == $state) {
                   31817:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                   31818:                         // skip releases that require a PHP version newer than our PHP version
                   31819:                         $skippedphp = $release;
                   31820:                         continue;
                   31821:                     }
                   31822:                     $found = true;
                   31823:                     break;
                   31824:                 }
                   31825: 
                   31826:                 // see if there is something newer and more stable
                   31827:                 // bug #7221
                   31828:                 if (in_array($release['s'], $this->betterStates($state), true)) {
                   31829:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                   31830:                         // skip releases that require a PHP version newer than our PHP version
                   31831:                         $skippedphp = $release;
                   31832:                         continue;
                   31833:                     }
                   31834:                     $found = true;
                   31835:                     break;
                   31836:                 }
                   31837:             } elseif (isset($version)) {
                   31838:                 if ($release['v'] == $version) {
                   31839:                     if (!isset($this->_rest->_options['force']) &&
                   31840:                           !isset($version) &&
                   31841:                           version_compare($release['m'], phpversion(), '>')) {
                   31842:                         // skip releases that require a PHP version newer than our PHP version
                   31843:                         $skippedphp = $release;
                   31844:                         continue;
                   31845:                     }
                   31846:                     $found = true;
                   31847:                     break;
                   31848:                 }
                   31849:             } else {
                   31850:                 if (in_array($release['s'], $states)) {
                   31851:                     if (version_compare($release['m'], phpversion(), '>')) {
                   31852:                         // skip releases that require a PHP version newer than our PHP version
                   31853:                         $skippedphp = $release;
                   31854:                         continue;
                   31855:                     }
                   31856:                     $found = true;
                   31857:                     break;
                   31858:                 }
                   31859:             }
                   31860:         }
                   31861: 
                   31862:         if (!$found && $skippedphp) {
                   31863:             $found = null;
                   31864:         }
                   31865: 
                   31866:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
                   31867:     }
                   31868: 
                   31869:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   31870:                                $prefstate = 'stable', $installed = false, $channel = false)
                   31871:     {
                   31872:         $states = $this->betterStates($prefstate, true);
                   31873:         if (!$states) {
                   31874:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   31875:         }
                   31876: 
                   31877:         $channel  = $dependency['channel'];
                   31878:         $package  = $dependency['name'];
                   31879:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   31880:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
                   31881:         $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
                   31882: 
                   31883:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   31884:         if (PEAR::isError($info)) {
                   31885:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   31886:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   31887:         }
                   31888: 
                   31889:         if (!is_array($info) || !isset($info['r'])) {
                   31890:             return false;
                   31891:         }
                   31892: 
                   31893:         $exclude = array();
                   31894:         $min = $max = $recommended = false;
                   31895:         if ($xsdversion == '1.0') {
                   31896:             $pinfo['package'] = $dependency['name'];
                   31897:             $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
                   31898:             switch ($dependency['rel']) {
                   31899:                 case 'ge' :
                   31900:                     $min = $dependency['version'];
                   31901:                 break;
                   31902:                 case 'gt' :
                   31903:                     $min = $dependency['version'];
                   31904:                     $exclude = array($dependency['version']);
                   31905:                 break;
                   31906:                 case 'eq' :
                   31907:                     $recommended = $dependency['version'];
                   31908:                 break;
                   31909:                 case 'lt' :
                   31910:                     $max = $dependency['version'];
                   31911:                     $exclude = array($dependency['version']);
                   31912:                 break;
                   31913:                 case 'le' :
                   31914:                     $max = $dependency['version'];
                   31915:                 break;
                   31916:                 case 'ne' :
                   31917:                     $exclude = array($dependency['version']);
                   31918:                 break;
                   31919:             }
                   31920:         } else {
                   31921:             $pinfo['package'] = $dependency['name'];
                   31922:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   31923:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   31924:             $recommended = isset($dependency['recommended']) ?
                   31925:                 $dependency['recommended'] : false;
                   31926:             if (isset($dependency['exclude'])) {
                   31927:                 if (!isset($dependency['exclude'][0])) {
                   31928:                     $exclude = array($dependency['exclude']);
                   31929:                 }
                   31930:             }
                   31931:         }
                   31932: 
                   31933:         $skippedphp = $found = $release = false;
                   31934:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   31935:             $info['r'] = array($info['r']);
                   31936:         }
                   31937: 
                   31938:         foreach ($info['r'] as $release) {
                   31939:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   31940:                   version_compare($release['v'], $installed, '<'))) {
                   31941:                 continue;
                   31942:             }
                   31943: 
                   31944:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   31945:                 continue;
                   31946:             }
                   31947: 
                   31948:             // allow newer releases to say "I'm OK with the dependent package"
                   31949:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   31950:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   31951:                     $release['co'] = array($release['co']);
                   31952:                 }
                   31953: 
                   31954:                 foreach ($release['co'] as $entry) {
                   31955:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   31956:                         $entry['x'] = array($entry['x']);
                   31957:                     } elseif (!isset($entry['x'])) {
                   31958:                         $entry['x'] = array();
                   31959:                     }
                   31960: 
                   31961:                     if ($entry['c'] == $deppackage['channel'] &&
                   31962:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   31963:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   31964:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   31965:                           !in_array($release['v'], $entry['x'])) {
                   31966:                         if (version_compare($release['m'], phpversion(), '>')) {
                   31967:                             // skip dependency releases that require a PHP version
                   31968:                             // newer than our PHP version
                   31969:                             $skippedphp = $release;
                   31970:                             continue;
                   31971:                         }
                   31972: 
                   31973:                         $recommended = $release['v'];
                   31974:                         break;
                   31975:                     }
                   31976:                 }
                   31977:             }
                   31978: 
                   31979:             if ($recommended) {
                   31980:                 if ($release['v'] != $recommended) { // if we want a specific
                   31981:                     // version, then skip all others
                   31982:                     continue;
                   31983:                 }
                   31984: 
                   31985:                 if (!in_array($release['s'], $states)) {
                   31986:                     // the stability is too low, but we must return the
                   31987:                     // recommended version if possible
                   31988:                     return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                   31989:                 }
                   31990:             }
                   31991: 
                   31992:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   31993:                 continue;
                   31994:             }
                   31995: 
                   31996:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   31997:                 continue;
                   31998:             }
                   31999: 
                   32000:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   32001:                 continue;
                   32002:             }
                   32003: 
                   32004:             if (in_array($release['s'], $states)) { // if in the preferred state...
                   32005:                 if (version_compare($release['m'], phpversion(), '>')) {
                   32006:                     // skip dependency releases that require a PHP version
                   32007:                     // newer than our PHP version
                   32008:                     $skippedphp = $release;
                   32009:                     continue;
                   32010:                 }
                   32011: 
                   32012:                 $found = true; // ... then use it
                   32013:                 break;
                   32014:             }
                   32015:         }
                   32016: 
                   32017:         if (!$found && $skippedphp) {
                   32018:             $found = null;
                   32019:         }
                   32020: 
                   32021:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
                   32022:     }
                   32023: }PEAR-1.9.4/PEAR/Task/Postinstallscript/rw.php0000644000076500000240000001331111605156760017570 0ustar  helgistaff<?php
                   32024: /**
                   32025:  * <tasks:postinstallscript> - read/write version
                   32026:  *
                   32027:  * PHP versions 4 and 5
                   32028:  *
                   32029:  * @category   pear
                   32030:  * @package    PEAR
                   32031:  * @author     Greg Beaver <cellog@php.net>
                   32032:  * @copyright  1997-2009 The Authors
                   32033:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32034:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32035:  * @link       http://pear.php.net/package/PEAR
                   32036:  * @since      File available since Release 1.4.0a10
                   32037:  */
                   32038: /**
                   32039:  * Base class
                   32040:  */
                   32041: require_once 'PEAR/Task/Postinstallscript.php';
                   32042: /**
                   32043:  * Abstracts the postinstallscript file task xml.
                   32044:  * @category   pear
                   32045:  * @package    PEAR
                   32046:  * @author     Greg Beaver <cellog@php.net>
                   32047:  * @copyright  1997-2009 The Authors
                   32048:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32049:  * @version    Release: 1.9.4
                   32050:  * @link       http://pear.php.net/package/PEAR
                   32051:  * @since      Class available since Release 1.4.0a10
                   32052:  */
                   32053: class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
                   32054: {
                   32055:     /**
                   32056:      * parent package file object
                   32057:      *
                   32058:      * @var PEAR_PackageFile_v2_rw
                   32059:      */
                   32060:     var $_pkg;
                   32061:     /**
                   32062:      * Enter description here...
                   32063:      *
                   32064:      * @param PEAR_PackageFile_v2_rw $pkg
                   32065:      * @param PEAR_Config $config
                   32066:      * @param PEAR_Frontend $logger
                   32067:      * @param array $fileXml
                   32068:      * @return PEAR_Task_Postinstallscript_rw
                   32069:      */
                   32070:     function PEAR_Task_Postinstallscript_rw(&$pkg, &$config, &$logger, $fileXml)
                   32071:     {
                   32072:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32073:         $this->_contents = $fileXml;
                   32074:         $this->_pkg = &$pkg;
                   32075:         $this->_params = array();
                   32076:     }
                   32077: 
                   32078:     function validate()
                   32079:     {
                   32080:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   32081:     }
                   32082: 
                   32083:     function getName()
                   32084:     {
                   32085:         return 'postinstallscript';
                   32086:     }
                   32087: 
                   32088:     /**
                   32089:      * add a simple <paramgroup> to the post-install script
                   32090:      *
                   32091:      * Order is significant, so call this method in the same
                   32092:      * sequence the users should see the paramgroups.  The $params
                   32093:      * parameter should either be the result of a call to {@link getParam()}
                   32094:      * or an array of calls to getParam().
                   32095:      *
                   32096:      * Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
                   32097:      * a <conditiontype> tag
                   32098:      * @param string $id <paramgroup> id as seen by the script
                   32099:      * @param array|false $params array of getParam() calls, or false for no params
                   32100:      * @param string|false $instructions
                   32101:      */
                   32102:     function addParamGroup($id, $params = false, $instructions = false)
                   32103:     {
                   32104:         if ($params && isset($params[0]) && !isset($params[1])) {
                   32105:             $params = $params[0];
                   32106:         }
                   32107:         $stuff =
                   32108:             array(
                   32109:                 $this->_pkg->getTasksNs() . ':id' => $id,
                   32110:             );
                   32111:         if ($instructions) {
                   32112:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   32113:         }
                   32114:         if ($params) {
                   32115:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   32116:         }
                   32117:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   32118:     }
                   32119: 
                   32120:     /**
                   32121:      * add a complex <paramgroup> to the post-install script with conditions
                   32122:      *
                   32123:      * This inserts a <paramgroup> with
                   32124:      *
                   32125:      * Order is significant, so call this method in the same
                   32126:      * sequence the users should see the paramgroups.  The $params
                   32127:      * parameter should either be the result of a call to {@link getParam()}
                   32128:      * or an array of calls to getParam().
                   32129:      *
                   32130:      * Use {@link addParamGroup()} to add a simple <paramgroup>
                   32131:      *
                   32132:      * @param string $id <paramgroup> id as seen by the script
                   32133:      * @param string $oldgroup <paramgroup> id of the section referenced by
                   32134:      *                         <conditiontype>
                   32135:      * @param string $param name of the <param> from the older section referenced
                   32136:      *                      by <contitiontype>
                   32137:      * @param string $value value to match of the parameter
                   32138:      * @param string $conditiontype one of '=', '!=', 'preg_match'
                   32139:      * @param array|false $params array of getParam() calls, or false for no params
                   32140:      * @param string|false $instructions
                   32141:      */
                   32142:     function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=',
                   32143:                                    $params = false, $instructions = false)
                   32144:     {
                   32145:         if ($params && isset($params[0]) && !isset($params[1])) {
                   32146:             $params = $params[0];
                   32147:         }
                   32148:         $stuff = array(
                   32149:             $this->_pkg->getTasksNs() . ':id' => $id,
                   32150:         );
                   32151:         if ($instructions) {
                   32152:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   32153:         }
                   32154:         $stuff[$this->_pkg->getTasksNs() . ':name'] = $oldgroup . '::' . $param;
                   32155:         $stuff[$this->_pkg->getTasksNs() . ':conditiontype'] = $conditiontype;
                   32156:         $stuff[$this->_pkg->getTasksNs() . ':value'] = $value;
                   32157:         if ($params) {
                   32158:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   32159:         }
                   32160:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   32161:     }
                   32162: 
                   32163:     function getXml()
                   32164:     {
                   32165:         return $this->_params;
                   32166:     }
                   32167: 
                   32168:     /**
                   32169:      * Use to set up a param tag for use in creating a paramgroup
                   32170:      * @static
                   32171:      */
                   32172:     function getParam($name, $prompt, $type = 'string', $default = null)
                   32173:     {
                   32174:         if ($default !== null) {
                   32175:             return
                   32176:             array(
                   32177:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   32178:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   32179:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   32180:                 $this->_pkg->getTasksNs() . ':default' => $default
                   32181:             );
                   32182:         }
                   32183:         return
                   32184:             array(
                   32185:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   32186:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   32187:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   32188:             );
                   32189:     }
                   32190: }
                   32191: ?>PEAR-1.9.4/PEAR/Task/Replace/rw.php0000644000076500000240000000311511605156760015403 0ustar  helgistaff<?php
                   32192: /**
                   32193:  * <tasks:replace> - read/write version
                   32194:  *
                   32195:  * PHP versions 4 and 5
                   32196:  *
                   32197:  * @category   pear
                   32198:  * @package    PEAR
                   32199:  * @author     Greg Beaver <cellog@php.net>
                   32200:  * @copyright  1997-2009 The Authors
                   32201:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32202:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32203:  * @link       http://pear.php.net/package/PEAR
                   32204:  * @since      File available since Release 1.4.0a10
                   32205:  */
                   32206: /**
                   32207:  * Base class
                   32208:  */
                   32209: require_once 'PEAR/Task/Replace.php';
                   32210: /**
                   32211:  * Abstracts the replace task xml.
                   32212:  * @category   pear
                   32213:  * @package    PEAR
                   32214:  * @author     Greg Beaver <cellog@php.net>
                   32215:  * @copyright  1997-2009 The Authors
                   32216:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32217:  * @version    Release: 1.9.4
                   32218:  * @link       http://pear.php.net/package/PEAR
                   32219:  * @since      Class available since Release 1.4.0a10
                   32220:  */
                   32221: class PEAR_Task_Replace_rw extends PEAR_Task_Replace
                   32222: {
                   32223:     function PEAR_Task_Replace_rw(&$pkg, &$config, &$logger, $fileXml)
                   32224:     {
                   32225:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32226:         $this->_contents = $fileXml;
                   32227:         $this->_pkg = &$pkg;
                   32228:         $this->_params = array();
                   32229:     }
                   32230: 
                   32231:     function validate()
                   32232:     {
                   32233:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   32234:     }
                   32235: 
                   32236:     function setInfo($from, $to, $type)
                   32237:     {
                   32238:         $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
                   32239:     }
                   32240: 
                   32241:     function getName()
                   32242:     {
                   32243:         return 'replace';
                   32244:     }
                   32245: 
                   32246:     function getXml()
                   32247:     {
                   32248:         return $this->_params;
                   32249:     }
                   32250: }
                   32251: ?>PEAR-1.9.4/PEAR/Task/Unixeol/rw.php0000644000076500000240000000253511605156760015460 0ustar  helgistaff<?php
                   32252: /**
                   32253:  * <tasks:unixeol> - read/write version
                   32254:  *
                   32255:  * PHP versions 4 and 5
                   32256:  *
                   32257:  * @category   pear
                   32258:  * @package    PEAR
                   32259:  * @author     Greg Beaver <cellog@php.net>
                   32260:  * @copyright  1997-2009 The Authors
                   32261:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32262:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32263:  * @link       http://pear.php.net/package/PEAR
                   32264:  * @since      File available since Release 1.4.0a10
                   32265:  */
                   32266: /**
                   32267:  * Base class
                   32268:  */
                   32269: require_once 'PEAR/Task/Unixeol.php';
                   32270: /**
                   32271:  * Abstracts the unixeol task xml.
                   32272:  * @category   pear
                   32273:  * @package    PEAR
                   32274:  * @author     Greg Beaver <cellog@php.net>
                   32275:  * @copyright  1997-2009 The Authors
                   32276:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32277:  * @version    Release: 1.9.4
                   32278:  * @link       http://pear.php.net/package/PEAR
                   32279:  * @since      Class available since Release 1.4.0a10
                   32280:  */
                   32281: class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
                   32282: {
                   32283:     function PEAR_Task_Unixeol_rw(&$pkg, &$config, &$logger, $fileXml)
                   32284:     {
                   32285:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32286:         $this->_contents = $fileXml;
                   32287:         $this->_pkg = &$pkg;
                   32288:         $this->_params = array();
                   32289:     }
                   32290: 
                   32291:     function validate()
                   32292:     {
                   32293:         return true;
                   32294:     }
                   32295: 
                   32296:     function getName()
                   32297:     {
                   32298:         return 'unixeol';
                   32299:     }
                   32300: 
                   32301:     function getXml()
                   32302:     {
                   32303:         return '';
                   32304:     }
                   32305: }
                   32306: ?>PEAR-1.9.4/PEAR/Task/Windowseol/rw.php0000644000076500000240000000256211605156760016167 0ustar  helgistaff<?php
                   32307: /**
                   32308:  * <tasks:windowseol> - read/write version
                   32309:  *
                   32310:  * PHP versions 4 and 5
                   32311:  *
                   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    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32318:  * @link       http://pear.php.net/package/PEAR
                   32319:  * @since      File available since Release 1.4.0a10
                   32320:  */
                   32321: /**
                   32322:  * Base class
                   32323:  */
                   32324: require_once 'PEAR/Task/Windowseol.php';
                   32325: /**
                   32326:  * Abstracts the windowseol task xml.
                   32327:  * @category   pear
                   32328:  * @package    PEAR
                   32329:  * @author     Greg Beaver <cellog@php.net>
                   32330:  * @copyright  1997-2009 The Authors
                   32331:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32332:  * @version    Release: 1.9.4
                   32333:  * @link       http://pear.php.net/package/PEAR
                   32334:  * @since      Class available since Release 1.4.0a10
                   32335:  */
                   32336: class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
                   32337: {
                   32338:     function PEAR_Task_Windowseol_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 true;
                   32349:     }
                   32350: 
                   32351:     function getName()
                   32352:     {
                   32353:         return 'windowseol';
                   32354:     }
                   32355: 
                   32356:     function getXml()
                   32357:     {
                   32358:         return '';
                   32359:     }
                   32360: }
                   32361: ?>PEAR-1.9.4/PEAR/Task/Common.php0000644000076500000240000001373611605156760014642 0ustar  helgistaff<?php
                   32362: /**
                   32363:  * PEAR_Task_Common, base class for installer tasks
                   32364:  *
                   32365:  * PHP versions 4 and 5
                   32366:  *
                   32367:  * @category   pear
                   32368:  * @package    PEAR
                   32369:  * @author     Greg Beaver <cellog@php.net>
                   32370:  * @copyright  1997-2009 The Authors
                   32371:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32372:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   32373:  * @link       http://pear.php.net/package/PEAR
                   32374:  * @since      File available since Release 1.4.0a1
                   32375:  */
                   32376: /**#@+
                   32377:  * Error codes for task validation routines
                   32378:  */
                   32379: define('PEAR_TASK_ERROR_NOATTRIBS', 1);
                   32380: define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
                   32381: define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
                   32382: define('PEAR_TASK_ERROR_INVALID', 4);
                   32383: /**#@-*/
                   32384: define('PEAR_TASK_PACKAGE', 1);
                   32385: define('PEAR_TASK_INSTALL', 2);
                   32386: define('PEAR_TASK_PACKAGEANDINSTALL', 3);
                   32387: /**
                   32388:  * A task is an operation that manipulates the contents of a file.
                   32389:  *
                   32390:  * Simple tasks operate on 1 file.  Multiple tasks are executed after all files have been
                   32391:  * processed and installed, and are designed to operate on all files containing the task.
                   32392:  * The Post-install script task simply takes advantage of the fact that it will be run
                   32393:  * after installation, replace is a simple task.
                   32394:  *
                   32395:  * Combining tasks is possible, but ordering is significant.
                   32396:  *
                   32397:  * <file name="test.php" role="php">
                   32398:  *  <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
                   32399:  *  <tasks:postinstallscript/>
                   32400:  * </file>
                   32401:  *
                   32402:  * This will first replace any instance of @data-dir@ in the test.php file
                   32403:  * with the path to the current data directory.  Then, it will include the
                   32404:  * test.php file and run the script it contains to configure the package post-installation.
                   32405:  * @category   pear
                   32406:  * @package    PEAR
                   32407:  * @author     Greg Beaver <cellog@php.net>
                   32408:  * @copyright  1997-2009 The Authors
                   32409:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32410:  * @version    Release: 1.9.4
                   32411:  * @link       http://pear.php.net/package/PEAR
                   32412:  * @since      Class available since Release 1.4.0a1
                   32413:  * @abstract
                   32414:  */
                   32415: class PEAR_Task_Common
                   32416: {
                   32417:     /**
                   32418:      * Valid types for this version are 'simple' and 'multiple'
                   32419:      *
                   32420:      * - simple tasks operate on the contents of a file and write out changes to disk
                   32421:      * - multiple tasks operate on the contents of many files and write out the
                   32422:      *   changes directly to disk
                   32423:      *
                   32424:      * Child task classes must override this property.
                   32425:      * @access protected
                   32426:      */
                   32427:     var $type = 'simple';
                   32428:     /**
                   32429:      * Determines which install phase this task is executed under
                   32430:      */
                   32431:     var $phase = PEAR_TASK_INSTALL;
                   32432:     /**
                   32433:      * @access protected
                   32434:      */
                   32435:     var $config;
                   32436:     /**
                   32437:      * @access protected
                   32438:      */
                   32439:     var $registry;
                   32440:     /**
                   32441:      * @access protected
                   32442:      */
                   32443:     var $logger;
                   32444:     /**
                   32445:      * @access protected
                   32446:      */
                   32447:     var $installphase;
                   32448:     /**
                   32449:      * @param PEAR_Config
                   32450:      * @param PEAR_Common
                   32451:      */
                   32452:     function PEAR_Task_Common(&$config, &$logger, $phase)
                   32453:     {
                   32454:         $this->config = &$config;
                   32455:         $this->registry = &$config->getRegistry();
                   32456:         $this->logger = &$logger;
                   32457:         $this->installphase = $phase;
                   32458:         if ($this->type == 'multiple') {
                   32459:             $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
                   32460:         }
                   32461:     }
                   32462: 
                   32463:     /**
                   32464:      * Validate the basic contents of a task tag.
                   32465:      * @param PEAR_PackageFile_v2
                   32466:      * @param array
                   32467:      * @param PEAR_Config
                   32468:      * @param array the entire parsed <file> tag
                   32469:      * @return true|array On error, return an array in format:
                   32470:      *    array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
                   32471:      *
                   32472:      *    For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
                   32473:      *    For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and an array
                   32474:      *    of legal values in
                   32475:      * @static
                   32476:      * @abstract
                   32477:      */
                   32478:     function validateXml($pkg, $xml, $config, $fileXml)
                   32479:     {
                   32480:     }
                   32481: 
                   32482:     /**
                   32483:      * Initialize a task instance with the parameters
                   32484:      * @param array raw, parsed xml
                   32485:      * @param array attributes from the <file> tag containing this task
                   32486:      * @param string|null last installed version of this package
                   32487:      * @abstract
                   32488:      */
                   32489:     function init($xml, $fileAttributes, $lastVersion)
                   32490:     {
                   32491:     }
                   32492: 
                   32493:     /**
                   32494:      * Begin a task processing session.  All multiple tasks will be processed after each file
                   32495:      * has been successfully installed, all simple tasks should perform their task here and
                   32496:      * return any errors using the custom throwError() method to allow forward compatibility
                   32497:      *
                   32498:      * This method MUST NOT write out any changes to disk
                   32499:      * @param PEAR_PackageFile_v2
                   32500:      * @param string file contents
                   32501:      * @param string the eventual final file location (informational only)
                   32502:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   32503:      *         (use $this->throwError), otherwise return the new contents
                   32504:      * @abstract
                   32505:      */
                   32506:     function startSession($pkg, $contents, $dest)
                   32507:     {
                   32508:     }
                   32509: 
                   32510:     /**
                   32511:      * This method is used to process each of the tasks for a particular multiple class
                   32512:      * type.  Simple tasks need not implement this method.
                   32513:      * @param array an array of tasks
                   32514:      * @access protected
                   32515:      * @static
                   32516:      * @abstract
                   32517:      */
                   32518:     function run($tasks)
                   32519:     {
                   32520:     }
                   32521: 
                   32522:     /**
                   32523:      * @static
                   32524:      * @final
                   32525:      */
                   32526:     function hasPostinstallTasks()
                   32527:     {
                   32528:         return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   32529:     }
                   32530: 
                   32531:     /**
                   32532:      * @static
                   32533:      * @final
                   32534:      */
                   32535:      function runPostinstallTasks()
                   32536:      {
                   32537:          foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
                   32538:              $err = call_user_func(array($class, 'run'),
                   32539:                   $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]);
                   32540:              if ($err) {
                   32541:                  return PEAR_Task_Common::throwError($err);
                   32542:              }
                   32543:          }
                   32544:          unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   32545:     }
                   32546: 
                   32547:     /**
                   32548:      * Determines whether a role is a script
                   32549:      * @return bool
                   32550:      */
                   32551:     function isScript()
                   32552:     {
                   32553:         return $this->type == 'script';
                   32554:     }
                   32555: 
                   32556:     function throwError($msg, $code = -1)
                   32557:     {
                   32558:         include_once 'PEAR.php';
                   32559:         return PEAR::raiseError($msg, $code);
                   32560:     }
                   32561: }
                   32562: ?>PEAR-1.9.4/PEAR/Task/Postinstallscript.php0000644000076500000240000003412211605156760017143 0ustar  helgistaff<?php
                   32563: /**
                   32564:  * <tasks:postinstallscript>
                   32565:  *
                   32566:  * PHP versions 4 and 5
                   32567:  *
                   32568:  * @category   pear
                   32569:  * @package    PEAR
                   32570:  * @author     Greg Beaver <cellog@php.net>
                   32571:  * @copyright  1997-2009 The Authors
                   32572:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32573:  * @version    CVS: $Id: Postinstallscript.php 313023 2011-07-06 19:17:11Z dufuz $
                   32574:  * @link       http://pear.php.net/package/PEAR
                   32575:  * @since      File available since Release 1.4.0a1
                   32576:  */
                   32577: /**
                   32578:  * Base class
                   32579:  */
                   32580: require_once 'PEAR/Task/Common.php';
                   32581: /**
                   32582:  * Implements the postinstallscript file task.
                   32583:  *
                   32584:  * Note that post-install scripts are handled separately from installation, by the
                   32585:  * "pear run-scripts" command
                   32586:  * @category   pear
                   32587:  * @package    PEAR
                   32588:  * @author     Greg Beaver <cellog@php.net>
                   32589:  * @copyright  1997-2009 The Authors
                   32590:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32591:  * @version    Release: 1.9.4
                   32592:  * @link       http://pear.php.net/package/PEAR
                   32593:  * @since      Class available since Release 1.4.0a1
                   32594:  */
                   32595: class PEAR_Task_Postinstallscript extends PEAR_Task_Common
                   32596: {
                   32597:     var $type = 'script';
                   32598:     var $_class;
                   32599:     var $_params;
                   32600:     var $_obj;
                   32601:     /**
                   32602:      *
                   32603:      * @var PEAR_PackageFile_v2
                   32604:      */
                   32605:     var $_pkg;
                   32606:     var $_contents;
                   32607:     var $phase = PEAR_TASK_INSTALL;
                   32608: 
                   32609:     /**
                   32610:      * Validate the raw xml at parsing-time.
                   32611:      *
                   32612:      * This also attempts to validate the script to make sure it meets the criteria
                   32613:      * for a post-install script
                   32614:      * @param PEAR_PackageFile_v2
                   32615:      * @param array The XML contents of the <postinstallscript> tag
                   32616:      * @param PEAR_Config
                   32617:      * @param array the entire parsed <file> tag
                   32618:      * @static
                   32619:      */
                   32620:     function validateXml($pkg, $xml, $config, $fileXml)
                   32621:     {
                   32622:         if ($fileXml['role'] != 'php') {
                   32623:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32624:             $fileXml['name'] . '" must be role="php"');
                   32625:         }
                   32626:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   32627:         $file = $pkg->getFileContents($fileXml['name']);
                   32628:         if (PEAR::isError($file)) {
                   32629:             PEAR::popErrorHandling();
                   32630:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32631:                 $fileXml['name'] . '" is not valid: ' .
                   32632:                 $file->getMessage());
                   32633:         } elseif ($file === null) {
                   32634:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32635:                 $fileXml['name'] . '" could not be retrieved for processing!');
                   32636:         } else {
                   32637:             $analysis = $pkg->analyzeSourceCode($file, true);
                   32638:             if (!$analysis) {
                   32639:                 PEAR::popErrorHandling();
                   32640:                 $warnings = '';
                   32641:                 foreach ($pkg->getValidationWarnings() as $warn) {
                   32642:                     $warnings .= $warn['message'] . "\n";
                   32643:                 }
                   32644:                 return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' .
                   32645:                     $fileXml['name'] . '" failed: ' . $warnings);
                   32646:             }
                   32647:             if (count($analysis['declared_classes']) != 1) {
                   32648:                 PEAR::popErrorHandling();
                   32649:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32650:                     $fileXml['name'] . '" must declare exactly 1 class');
                   32651:             }
                   32652:             $class = $analysis['declared_classes'][0];
                   32653:             if ($class != str_replace(array('/', '.php'), array('_', ''),
                   32654:                   $fileXml['name']) . '_postinstall') {
                   32655:                 PEAR::popErrorHandling();
                   32656:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32657:                     $fileXml['name'] . '" class "' . $class . '" must be named "' .
                   32658:                     str_replace(array('/', '.php'), array('_', ''),
                   32659:                     $fileXml['name']) . '_postinstall"');
                   32660:             }
                   32661:             if (!isset($analysis['declared_methods'][$class])) {
                   32662:                 PEAR::popErrorHandling();
                   32663:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32664:                     $fileXml['name'] . '" must declare methods init() and run()');
                   32665:             }
                   32666:             $methods = array('init' => 0, 'run' => 1);
                   32667:             foreach ($analysis['declared_methods'][$class] as $method) {
                   32668:                 if (isset($methods[$method])) {
                   32669:                     unset($methods[$method]);
                   32670:                 }
                   32671:             }
                   32672:             if (count($methods)) {
                   32673:                 PEAR::popErrorHandling();
                   32674:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32675:                     $fileXml['name'] . '" must declare methods init() and run()');
                   32676:             }
                   32677:         }
                   32678:         PEAR::popErrorHandling();
                   32679:         $definedparams = array();
                   32680:         $tasksNamespace = $pkg->getTasksNs() . ':';
                   32681:         if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) {
                   32682:             // in order to support the older betas, which did not expect internal tags
                   32683:             // to also use the namespace
                   32684:             $tasksNamespace = '';
                   32685:         }
                   32686:         if (isset($xml[$tasksNamespace . 'paramgroup'])) {
                   32687:             $params = $xml[$tasksNamespace . 'paramgroup'];
                   32688:             if (!is_array($params) || !isset($params[0])) {
                   32689:                 $params = array($params);
                   32690:             }
                   32691:             foreach ($params as $param) {
                   32692:                 if (!isset($param[$tasksNamespace . 'id'])) {
                   32693:                     return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32694:                         $fileXml['name'] . '" <paramgroup> must have ' .
                   32695:                         'an ' . $tasksNamespace . 'id> tag');
                   32696:                 }
                   32697:                 if (isset($param[$tasksNamespace . 'name'])) {
                   32698:                     if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) {
                   32699:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32700:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32701:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32702:                             '" parameter "' . $param[$tasksNamespace . 'name'] .
                   32703:                             '" has not been previously defined');
                   32704:                     }
                   32705:                     if (!isset($param[$tasksNamespace . 'conditiontype'])) {
                   32706:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32707:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32708:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32709:                             '" must have a ' . $tasksNamespace .
                   32710:                             'conditiontype> tag containing either "=", ' .
                   32711:                             '"!=", or "preg_match"');
                   32712:                     }
                   32713:                     if (!in_array($param[$tasksNamespace . 'conditiontype'],
                   32714:                           array('=', '!=', 'preg_match'))) {
                   32715:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32716:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32717:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32718:                             '" must have a ' . $tasksNamespace .
                   32719:                             'conditiontype> tag containing either "=", ' .
                   32720:                             '"!=", or "preg_match"');
                   32721:                     }
                   32722:                     if (!isset($param[$tasksNamespace . 'value'])) {
                   32723:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32724:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32725:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32726:                             '" must have a ' . $tasksNamespace .
                   32727:                             'value> tag containing expected parameter value');
                   32728:                     }
                   32729:                 }
                   32730:                 if (isset($param[$tasksNamespace . 'instructions'])) {
                   32731:                     if (!is_string($param[$tasksNamespace . 'instructions'])) {
                   32732:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32733:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32734:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32735:                             '" ' . $tasksNamespace . 'instructions> must be simple text');
                   32736:                     }
                   32737:                 }
                   32738:                 if (!isset($param[$tasksNamespace . 'param'])) {
                   32739:                     continue; // <param> is no longer required
                   32740:                 }
                   32741:                 $subparams = $param[$tasksNamespace . 'param'];
                   32742:                 if (!is_array($subparams) || !isset($subparams[0])) {
                   32743:                     $subparams = array($subparams);
                   32744:                 }
                   32745:                 foreach ($subparams as $subparam) {
                   32746:                     if (!isset($subparam[$tasksNamespace . 'name'])) {
                   32747:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32748:                             $fileXml['name'] . '" parameter for ' .
                   32749:                             $tasksNamespace . 'paramgroup> id "' .
                   32750:                             $param[$tasksNamespace . 'id'] . '" must have ' .
                   32751:                             'a ' . $tasksNamespace . 'name> tag');
                   32752:                     }
                   32753:                     if (!preg_match('/[a-zA-Z0-9]+/',
                   32754:                           $subparam[$tasksNamespace . 'name'])) {
                   32755:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32756:                             $fileXml['name'] . '" parameter "' .
                   32757:                             $subparam[$tasksNamespace . 'name'] .
                   32758:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   32759:                             $param[$tasksNamespace . 'id'] .
                   32760:                             '" is not a valid name.  Must contain only alphanumeric characters');
                   32761:                     }
                   32762:                     if (!isset($subparam[$tasksNamespace . 'prompt'])) {
                   32763:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32764:                             $fileXml['name'] . '" parameter "' .
                   32765:                             $subparam[$tasksNamespace . 'name'] .
                   32766:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   32767:                             $param[$tasksNamespace . 'id'] .
                   32768:                             '" must have a ' . $tasksNamespace . 'prompt> tag');
                   32769:                     }
                   32770:                     if (!isset($subparam[$tasksNamespace . 'type'])) {
                   32771:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32772:                             $fileXml['name'] . '" parameter "' .
                   32773:                             $subparam[$tasksNamespace . 'name'] .
                   32774:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   32775:                             $param[$tasksNamespace . 'id'] .
                   32776:                             '" must have a ' . $tasksNamespace . 'type> tag');
                   32777:                     }
                   32778:                     $definedparams[] = $param[$tasksNamespace . 'id'] . '::' .
                   32779:                     $subparam[$tasksNamespace . 'name'];
                   32780:                 }
                   32781:             }
                   32782:         }
                   32783:         return true;
                   32784:     }
                   32785: 
                   32786:     /**
                   32787:      * Initialize a task instance with the parameters
                   32788:      * @param array raw, parsed xml
                   32789:      * @param array attributes from the <file> tag containing this task
                   32790:      * @param string|null last installed version of this package, if any (useful for upgrades)
                   32791:      */
                   32792:     function init($xml, $fileattribs, $lastversion)
                   32793:     {
                   32794:         $this->_class = str_replace('/', '_', $fileattribs['name']);
                   32795:         $this->_filename = $fileattribs['name'];
                   32796:         $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall';
                   32797:         $this->_params = $xml;
                   32798:         $this->_lastversion = $lastversion;
                   32799:     }
                   32800: 
                   32801:     /**
                   32802:      * Strip the tasks: namespace from internal params
                   32803:      *
                   32804:      * @access private
                   32805:      */
                   32806:     function _stripNamespace($params = null)
                   32807:     {
                   32808:         if ($params === null) {
                   32809:             $params = array();
                   32810:             if (!is_array($this->_params)) {
                   32811:                 return;
                   32812:             }
                   32813:             foreach ($this->_params as $i => $param) {
                   32814:                 if (is_array($param)) {
                   32815:                     $param = $this->_stripNamespace($param);
                   32816:                 }
                   32817:                 $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   32818:             }
                   32819:             $this->_params = $params;
                   32820:         } else {
                   32821:             $newparams = array();
                   32822:             foreach ($params as $i => $param) {
                   32823:                 if (is_array($param)) {
                   32824:                     $param = $this->_stripNamespace($param);
                   32825:                 }
                   32826:                 $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   32827:             }
                   32828:             return $newparams;
                   32829:         }
                   32830:     }
                   32831: 
                   32832:     /**
                   32833:      * Unlike other tasks, the installed file name is passed in instead of the file contents,
                   32834:      * because this task is handled post-installation
                   32835:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   32836:      * @param string file name
                   32837:      * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
                   32838:      *         (use $this->throwError)
                   32839:      */
                   32840:     function startSession($pkg, $contents)
                   32841:     {
                   32842:         if ($this->installphase != PEAR_TASK_INSTALL) {
                   32843:             return false;
                   32844:         }
                   32845:         // remove the tasks: namespace if present
                   32846:         $this->_pkg = $pkg;
                   32847:         $this->_stripNamespace();
                   32848:         $this->logger->log(0, 'Including external post-installation script "' .
                   32849:             $contents . '" - any errors are in this script');
                   32850:         include_once $contents;
                   32851:         if (class_exists($this->_class)) {
                   32852:             $this->logger->log(0, 'Inclusion succeeded');
                   32853:         } else {
                   32854:             return $this->throwError('init of post-install script class "' . $this->_class
                   32855:                 . '" failed');
                   32856:         }
                   32857:         $this->_obj = new $this->_class;
                   32858:         $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"');
                   32859:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   32860:         $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
                   32861:         PEAR::popErrorHandling();
                   32862:         if ($res) {
                   32863:             $this->logger->log(0, 'init succeeded');
                   32864:         } else {
                   32865:             return $this->throwError('init of post-install script "' . $this->_class .
                   32866:                 '->init()" failed');
                   32867:         }
                   32868:         $this->_contents = $contents;
                   32869:         return true;
                   32870:     }
                   32871: 
                   32872:     /**
                   32873:      * No longer used
                   32874:      * @see PEAR_PackageFile_v2::runPostinstallScripts()
                   32875:      * @param array an array of tasks
                   32876:      * @param string install or upgrade
                   32877:      * @access protected
                   32878:      * @static
                   32879:      */
                   32880:     function run()
                   32881:     {
                   32882:     }
                   32883: }
                   32884: ?>PEAR-1.9.4/PEAR/Task/Replace.php0000644000076500000240000001523211605156760014756 0ustar  helgistaff<?php
                   32885: /**
                   32886:  * <tasks:replace>
                   32887:  *
                   32888:  * PHP versions 4 and 5
                   32889:  *
                   32890:  * @category   pear
                   32891:  * @package    PEAR
                   32892:  * @author     Greg Beaver <cellog@php.net>
                   32893:  * @copyright  1997-2009 The Authors
                   32894:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32895:  * @version    CVS: $Id: Replace.php 313023 2011-07-06 19:17:11Z dufuz $
                   32896:  * @link       http://pear.php.net/package/PEAR
                   32897:  * @since      File available since Release 1.4.0a1
                   32898:  */
                   32899: /**
                   32900:  * Base class
                   32901:  */
                   32902: require_once 'PEAR/Task/Common.php';
                   32903: /**
                   32904:  * Implements the replace file task.
                   32905:  * @category   pear
                   32906:  * @package    PEAR
                   32907:  * @author     Greg Beaver <cellog@php.net>
                   32908:  * @copyright  1997-2009 The Authors
                   32909:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32910:  * @version    Release: 1.9.4
                   32911:  * @link       http://pear.php.net/package/PEAR
                   32912:  * @since      Class available since Release 1.4.0a1
                   32913:  */
                   32914: class PEAR_Task_Replace extends PEAR_Task_Common
                   32915: {
                   32916:     var $type = 'simple';
                   32917:     var $phase = PEAR_TASK_PACKAGEANDINSTALL;
                   32918:     var $_replacements;
                   32919: 
                   32920:     /**
                   32921:      * Validate the raw xml at parsing-time.
                   32922:      * @param PEAR_PackageFile_v2
                   32923:      * @param array raw, parsed xml
                   32924:      * @param PEAR_Config
                   32925:      * @static
                   32926:      */
                   32927:     function validateXml($pkg, $xml, $config, $fileXml)
                   32928:     {
                   32929:         if (!isset($xml['attribs'])) {
                   32930:             return array(PEAR_TASK_ERROR_NOATTRIBS);
                   32931:         }
                   32932:         if (!isset($xml['attribs']['type'])) {
                   32933:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
                   32934:         }
                   32935:         if (!isset($xml['attribs']['to'])) {
                   32936:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
                   32937:         }
                   32938:         if (!isset($xml['attribs']['from'])) {
                   32939:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
                   32940:         }
                   32941:         if ($xml['attribs']['type'] == 'pear-config') {
                   32942:             if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                   32943:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   32944:                     $config->getKeys());
                   32945:             }
                   32946:         } elseif ($xml['attribs']['type'] == 'php-const') {
                   32947:             if (defined($xml['attribs']['to'])) {
                   32948:                 return true;
                   32949:             } else {
                   32950:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   32951:                     array('valid PHP constant'));
                   32952:             }
                   32953:         } elseif ($xml['attribs']['type'] == 'package-info') {
                   32954:             if (in_array($xml['attribs']['to'],
                   32955:                 array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   32956:                     'release_notes', 'license', 'release-license', 'license-uri',
                   32957:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   32958:                     'date', 'time'))) {
                   32959:                 return true;
                   32960:             } else {
                   32961:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   32962:                     array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   32963:                     'release_notes', 'license', 'release-license', 'license-uri',
                   32964:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   32965:                     'date', 'time'));
                   32966:             }
                   32967:         } else {
                   32968:             return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                   32969:                 array('pear-config', 'package-info', 'php-const'));
                   32970:         }
                   32971:         return true;
                   32972:     }
                   32973: 
                   32974:     /**
                   32975:      * Initialize a task instance with the parameters
                   32976:      * @param array raw, parsed xml
                   32977:      * @param unused
                   32978:      */
                   32979:     function init($xml, $attribs)
                   32980:     {
                   32981:         $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
                   32982:     }
                   32983: 
                   32984:     /**
                   32985:      * Do a package.xml 1.0 replacement, with additional package-info fields available
                   32986:      *
                   32987:      * See validateXml() source for the complete list of allowed fields
                   32988:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   32989:      * @param string file contents
                   32990:      * @param string the eventual final file location (informational only)
                   32991:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   32992:      *         (use $this->throwError), otherwise return the new contents
                   32993:      */
                   32994:     function startSession($pkg, $contents, $dest)
                   32995:     {
                   32996:         $subst_from = $subst_to = array();
                   32997:         foreach ($this->_replacements as $a) {
                   32998:             $a = $a['attribs'];
                   32999:             $to = '';
                   33000:             if ($a['type'] == 'pear-config') {
                   33001:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   33002:                     return false;
                   33003:                 }
                   33004:                 if ($a['to'] == 'master_server') {
                   33005:                     $chan = $this->registry->getChannel($pkg->getChannel());
                   33006:                     if (!PEAR::isError($chan)) {
                   33007:                         $to = $chan->getServer();
                   33008:                     } else {
                   33009:                         $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   33010:                         return false;
                   33011:                     }
                   33012:                 } else {
                   33013:                     if ($this->config->isDefinedLayer('ftp')) {
                   33014:                         // try the remote config file first
                   33015:                         $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                   33016:                         if (is_null($to)) {
                   33017:                             // then default to local
                   33018:                             $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   33019:                         }
                   33020:                     } else {
                   33021:                         $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   33022:                     }
                   33023:                 }
                   33024:                 if (is_null($to)) {
                   33025:                     $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   33026:                     return false;
                   33027:                 }
                   33028:             } elseif ($a['type'] == 'php-const') {
                   33029:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   33030:                     return false;
                   33031:                 }
                   33032:                 if (defined($a['to'])) {
                   33033:                     $to = constant($a['to']);
                   33034:                 } else {
                   33035:                     $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
                   33036:                     return false;
                   33037:                 }
                   33038:             } else {
                   33039:                 if ($t = $pkg->packageInfo($a['to'])) {
                   33040:                     $to = $t;
                   33041:                 } else {
                   33042:                     $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
                   33043:                     return false;
                   33044:                 }
                   33045:             }
                   33046:             if (!is_null($to)) {
                   33047:                 $subst_from[] = $a['from'];
                   33048:                 $subst_to[] = $to;
                   33049:             }
                   33050:         }
                   33051:         $this->logger->log(3, "doing " . sizeof($subst_from) .
                   33052:             " substitution(s) for $dest");
                   33053:         if (sizeof($subst_from)) {
                   33054:             $contents = str_replace($subst_from, $subst_to, $contents);
                   33055:         }
                   33056:         return $contents;
                   33057:     }
                   33058: }
                   33059: ?>PEAR-1.9.4/PEAR/Task/Unixeol.php0000644000076500000240000000434111605156760015025 0ustar  helgistaff<?php
                   33060: /**
                   33061:  * <tasks:unixeol>
                   33062:  *
                   33063:  * PHP versions 4 and 5
                   33064:  *
                   33065:  * @category   pear
                   33066:  * @package    PEAR
                   33067:  * @author     Greg Beaver <cellog@php.net>
                   33068:  * @copyright  1997-2009 The Authors
                   33069:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33070:  * @version    CVS: $Id: Unixeol.php 313023 2011-07-06 19:17:11Z dufuz $
                   33071:  * @link       http://pear.php.net/package/PEAR
                   33072:  * @since      File available since Release 1.4.0a1
                   33073:  */
                   33074: /**
                   33075:  * Base class
                   33076:  */
                   33077: require_once 'PEAR/Task/Common.php';
                   33078: /**
                   33079:  * Implements the unix line endings file task.
                   33080:  * @category   pear
                   33081:  * @package    PEAR
                   33082:  * @author     Greg Beaver <cellog@php.net>
                   33083:  * @copyright  1997-2009 The Authors
                   33084:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33085:  * @version    Release: 1.9.4
                   33086:  * @link       http://pear.php.net/package/PEAR
                   33087:  * @since      Class available since Release 1.4.0a1
                   33088:  */
                   33089: class PEAR_Task_Unixeol extends PEAR_Task_Common
                   33090: {
                   33091:     var $type = 'simple';
                   33092:     var $phase = PEAR_TASK_PACKAGE;
                   33093:     var $_replacements;
                   33094: 
                   33095:     /**
                   33096:      * Validate the raw xml at parsing-time.
                   33097:      * @param PEAR_PackageFile_v2
                   33098:      * @param array raw, parsed xml
                   33099:      * @param PEAR_Config
                   33100:      * @static
                   33101:      */
                   33102:     function validateXml($pkg, $xml, $config, $fileXml)
                   33103:     {
                   33104:         if ($xml != '') {
                   33105:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   33106:         }
                   33107:         return true;
                   33108:     }
                   33109: 
                   33110:     /**
                   33111:      * Initialize a task instance with the parameters
                   33112:      * @param array raw, parsed xml
                   33113:      * @param unused
                   33114:      */
                   33115:     function init($xml, $attribs)
                   33116:     {
                   33117:     }
                   33118: 
                   33119:     /**
                   33120:      * Replace all line endings with line endings customized for the current OS
                   33121:      *
                   33122:      * See validateXml() source for the complete list of allowed fields
                   33123:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33124:      * @param string file contents
                   33125:      * @param string the eventual final file location (informational only)
                   33126:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   33127:      *         (use $this->throwError), otherwise return the new contents
                   33128:      */
                   33129:     function startSession($pkg, $contents, $dest)
                   33130:     {
                   33131:         $this->logger->log(3, "replacing all line endings with \\n in $dest");
                   33132:         return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
                   33133:     }
                   33134: }
                   33135: ?>PEAR-1.9.4/PEAR/Task/Windowseol.php0000644000076500000240000000433511605156760015537 0ustar  helgistaff<?php
                   33136: /**
                   33137:  * <tasks:windowseol>
                   33138:  *
                   33139:  * PHP versions 4 and 5
                   33140:  *
                   33141:  * @category   pear
                   33142:  * @package    PEAR
                   33143:  * @author     Greg Beaver <cellog@php.net>
                   33144:  * @copyright  1997-2009 The Authors
                   33145:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33146:  * @version    CVS: $Id: Windowseol.php 313023 2011-07-06 19:17:11Z dufuz $
                   33147:  * @link       http://pear.php.net/package/PEAR
                   33148:  * @since      File available since Release 1.4.0a1
                   33149:  */
                   33150: /**
                   33151:  * Base class
                   33152:  */
                   33153: require_once 'PEAR/Task/Common.php';
                   33154: /**
                   33155:  * Implements the windows line endsings file task.
                   33156:  * @category   pear
                   33157:  * @package    PEAR
                   33158:  * @author     Greg Beaver <cellog@php.net>
                   33159:  * @copyright  1997-2009 The Authors
                   33160:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33161:  * @version    Release: 1.9.4
                   33162:  * @link       http://pear.php.net/package/PEAR
                   33163:  * @since      Class available since Release 1.4.0a1
                   33164:  */
                   33165: class PEAR_Task_Windowseol extends PEAR_Task_Common
                   33166: {
                   33167:     var $type = 'simple';
                   33168:     var $phase = PEAR_TASK_PACKAGE;
                   33169:     var $_replacements;
                   33170: 
                   33171:     /**
                   33172:      * Validate the raw xml at parsing-time.
                   33173:      * @param PEAR_PackageFile_v2
                   33174:      * @param array raw, parsed xml
                   33175:      * @param PEAR_Config
                   33176:      * @static
                   33177:      */
                   33178:     function validateXml($pkg, $xml, $config, $fileXml)
                   33179:     {
                   33180:         if ($xml != '') {
                   33181:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   33182:         }
                   33183:         return true;
                   33184:     }
                   33185: 
                   33186:     /**
                   33187:      * Initialize a task instance with the parameters
                   33188:      * @param array raw, parsed xml
                   33189:      * @param unused
                   33190:      */
                   33191:     function init($xml, $attribs)
                   33192:     {
                   33193:     }
                   33194: 
                   33195:     /**
                   33196:      * Replace all line endings with windows line endings
                   33197:      *
                   33198:      * See validateXml() source for the complete list of allowed fields
                   33199:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33200:      * @param string file contents
                   33201:      * @param string the eventual final file location (informational only)
                   33202:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   33203:      *         (use $this->throwError), otherwise return the new contents
                   33204:      */
                   33205:     function startSession($pkg, $contents, $dest)
                   33206:     {
                   33207:         $this->logger->log(3, "replacing all line endings with \\r\\n in $dest");
                   33208:         return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
                   33209:     }
                   33210: }
                   33211: ?>PEAR-1.9.4/PEAR/Validator/PECL.php0000644000076500000240000000417511605156760015155 0ustar  helgistaff<?php
                   33212: /**
                   33213:  * Channel Validator for the pecl.php.net channel
                   33214:  *
                   33215:  * PHP 4 and PHP 5
                   33216:  *
                   33217:  * @category   pear
                   33218:  * @package    PEAR
                   33219:  * @author     Greg Beaver <cellog@php.net>
                   33220:  * @copyright  1997-2006 The PHP Group
                   33221:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33222:  * @version    CVS: $Id: PECL.php 313023 2011-07-06 19:17:11Z dufuz $
                   33223:  * @link       http://pear.php.net/package/PEAR
                   33224:  * @since      File available since Release 1.4.0a5
                   33225:  */
                   33226: /**
                   33227:  * This is the parent class for all validators
                   33228:  */
                   33229: require_once 'PEAR/Validate.php';
                   33230: /**
                   33231:  * Channel Validator for the pecl.php.net channel
                   33232:  * @category   pear
                   33233:  * @package    PEAR
                   33234:  * @author     Greg Beaver <cellog@php.net>
                   33235:  * @copyright  1997-2009 The Authors
                   33236:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33237:  * @version    Release: 1.9.4
                   33238:  * @link       http://pear.php.net/package/PEAR
                   33239:  * @since      Class available since Release 1.4.0a5
                   33240:  */
                   33241: class PEAR_Validator_PECL extends PEAR_Validate
                   33242: {
                   33243:     function validateVersion()
                   33244:     {
                   33245:         if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   33246:             $version = $this->_packagexml->getVersion();
                   33247:             $versioncomponents = explode('.', $version);
                   33248:             $last = array_pop($versioncomponents);
                   33249:             if (substr($last, 1, 2) == 'rc') {
                   33250:                 $this->_addFailure('version', 'Release Candidate versions must have ' .
                   33251:                 'upper-case RC, not lower-case rc');
                   33252:                 return false;
                   33253:             }
                   33254:         }
                   33255:         return true;
                   33256:     }
                   33257: 
                   33258:     function validatePackageName()
                   33259:     {
                   33260:         $ret = parent::validatePackageName();
                   33261:         if ($this->_packagexml->getPackageType() == 'extsrc' ||
                   33262:               $this->_packagexml->getPackageType() == 'zendextsrc') {
                   33263:             if (strtolower($this->_packagexml->getPackage()) !=
                   33264:                   strtolower($this->_packagexml->getProvidesExtension())) {
                   33265:                 $this->_addWarning('providesextension', 'package name "' .
                   33266:                     $this->_packagexml->getPackage() . '" is different from extension name "' .
                   33267:                     $this->_packagexml->getProvidesExtension() . '"');
                   33268:             }
                   33269:         }
                   33270:         return $ret;
                   33271:     }
                   33272: }
                   33273: ?>PEAR-1.9.4/PEAR/Autoloader.php0000644000076500000240000001464511605156760014607 0ustar  helgistaff<?php
                   33274: /**
                   33275:  * Class auto-loader
                   33276:  *
                   33277:  * PHP versions 4
                   33278: 
                   33279:  *
                   33280:  * @category   pear
                   33281:  * @package    PEAR
                   33282:  * @author     Stig Bakken <ssb@php.net>
                   33283:  * @copyright  1997-2009 The Authors
                   33284:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33285:  * @version    CVS: $Id: Autoloader.php 313023 2011-07-06 19:17:11Z dufuz $
                   33286:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
                   33287:  * @since      File available since Release 0.1
                   33288:  * @deprecated File deprecated in Release 1.4.0a1
                   33289:  */
                   33290: 
                   33291: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   33292: 
                   33293: if (!extension_loaded("overload")) {
                   33294:     // die hard without ext/overload
                   33295:     die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
                   33296: }
                   33297: 
                   33298: /**
                   33299:  * Include for PEAR_Error and PEAR classes
                   33300:  */
                   33301: require_once "PEAR.php";
                   33302: 
                   33303: /**
                   33304:  * This class is for objects where you want to separate the code for
                   33305:  * some methods into separate classes.  This is useful if you have a
                   33306:  * class with not-frequently-used methods that contain lots of code
                   33307:  * that you would like to avoid always parsing.
                   33308:  *
                   33309:  * The PEAR_Autoloader class provides autoloading and aggregation.
                   33310:  * The autoloading lets you set up in which classes the separated
                   33311:  * methods are found.  Aggregation is the technique used to import new
                   33312:  * methods, an instance of each class providing separated methods is
                   33313:  * stored and called every time the aggregated method is called.
                   33314:  *
                   33315:  * @category   pear
                   33316:  * @package    PEAR
                   33317:  * @author Stig Bakken <ssb@php.net>
                   33318:  * @copyright  1997-2009 The Authors
                   33319:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33320:  * @version    Release: 1.9.4
                   33321:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
                   33322:  * @since      File available since Release 0.1
                   33323:  * @deprecated File deprecated in Release 1.4.0a1
                   33324:  */
                   33325: class PEAR_Autoloader extends PEAR
                   33326: {
                   33327:     // {{{ properties
                   33328: 
                   33329:     /**
                   33330:      * Map of methods and classes where they are defined
                   33331:      *
                   33332:      * @var array
                   33333:      *
                   33334:      * @access private
                   33335:      */
                   33336:     var $_autoload_map = array();
                   33337: 
                   33338:     /**
                   33339:      * Map of methods and aggregate objects
                   33340:      *
                   33341:      * @var array
                   33342:      *
                   33343:      * @access private
                   33344:      */
                   33345:     var $_method_map = array();
                   33346: 
                   33347:     // }}}
                   33348:     // {{{ addAutoload()
                   33349: 
                   33350:     /**
                   33351:      * Add one or more autoload entries.
                   33352:      *
                   33353:      * @param string $method     which method to autoload
                   33354:      *
                   33355:      * @param string $classname  (optional) which class to find the method in.
                   33356:      *                           If the $method parameter is an array, this
                   33357:      *                           parameter may be omitted (and will be ignored
                   33358:      *                           if not), and the $method parameter will be
                   33359:      *                           treated as an associative array with method
                   33360:      *                           names as keys and class names as values.
                   33361:      *
                   33362:      * @return void
                   33363:      *
                   33364:      * @access public
                   33365:      */
                   33366:     function addAutoload($method, $classname = null)
                   33367:     {
                   33368:         if (is_array($method)) {
                   33369:             array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
                   33370:             $this->_autoload_map = array_merge($this->_autoload_map, $method);
                   33371:         } else {
                   33372:             $this->_autoload_map[strtolower($method)] = $classname;
                   33373:         }
                   33374:     }
                   33375: 
                   33376:     // }}}
                   33377:     // {{{ removeAutoload()
                   33378: 
                   33379:     /**
                   33380:      * Remove an autoload entry.
                   33381:      *
                   33382:      * @param string $method  which method to remove the autoload entry for
                   33383:      *
                   33384:      * @return bool TRUE if an entry was removed, FALSE if not
                   33385:      *
                   33386:      * @access public
                   33387:      */
                   33388:     function removeAutoload($method)
                   33389:     {
                   33390:         $method = strtolower($method);
                   33391:         $ok = isset($this->_autoload_map[$method]);
                   33392:         unset($this->_autoload_map[$method]);
                   33393:         return $ok;
                   33394:     }
                   33395: 
                   33396:     // }}}
                   33397:     // {{{ addAggregateObject()
                   33398: 
                   33399:     /**
                   33400:      * Add an aggregate object to this object.  If the specified class
                   33401:      * is not defined, loading it will be attempted following PEAR's
                   33402:      * file naming scheme.  All the methods in the class will be
                   33403:      * aggregated, except private ones (name starting with an
                   33404:      * underscore) and constructors.
                   33405:      *
                   33406:      * @param string $classname  what class to instantiate for the object.
                   33407:      *
                   33408:      * @return void
                   33409:      *
                   33410:      * @access public
                   33411:      */
                   33412:     function addAggregateObject($classname)
                   33413:     {
                   33414:         $classname = strtolower($classname);
                   33415:         if (!class_exists($classname)) {
                   33416:             $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
                   33417:             include_once $include_file;
                   33418:         }
                   33419:         $obj =& new $classname;
                   33420:         $methods = get_class_methods($classname);
                   33421:         foreach ($methods as $method) {
                   33422:             // don't import priviate methods and constructors
                   33423:             if ($method{0} != '_' && $method != $classname) {
                   33424:                 $this->_method_map[$method] = $obj;
                   33425:             }
                   33426:         }
                   33427:     }
                   33428: 
                   33429:     // }}}
                   33430:     // {{{ removeAggregateObject()
                   33431: 
                   33432:     /**
                   33433:      * Remove an aggregate object.
                   33434:      *
                   33435:      * @param string $classname  the class of the object to remove
                   33436:      *
                   33437:      * @return bool  TRUE if an object was removed, FALSE if not
                   33438:      *
                   33439:      * @access public
                   33440:      */
                   33441:     function removeAggregateObject($classname)
                   33442:     {
                   33443:         $ok = false;
                   33444:         $classname = strtolower($classname);
                   33445:         reset($this->_method_map);
                   33446:         while (list($method, $obj) = each($this->_method_map)) {
                   33447:             if (is_a($obj, $classname)) {
                   33448:                 unset($this->_method_map[$method]);
                   33449:                 $ok = true;
                   33450:             }
                   33451:         }
                   33452:         return $ok;
                   33453:     }
                   33454: 
                   33455:     // }}}
                   33456:     // {{{ __call()
                   33457: 
                   33458:     /**
                   33459:      * Overloaded object call handler, called each time an
                   33460:      * undefined/aggregated method is invoked.  This method repeats
                   33461:      * the call in the right aggregate object and passes on the return
                   33462:      * value.
                   33463:      *
                   33464:      * @param string $method  which method that was called
                   33465:      *
                   33466:      * @param string $args    An array of the parameters passed in the
                   33467:      *                        original call
                   33468:      *
                   33469:      * @return mixed  The return value from the aggregated method, or a PEAR
                   33470:      *                error if the called method was unknown.
                   33471:      */
                   33472:     function __call($method, $args, &$retval)
                   33473:     {
                   33474:         $method = strtolower($method);
                   33475:         if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
                   33476:             $this->addAggregateObject($this->_autoload_map[$method]);
                   33477:         }
                   33478:         if (isset($this->_method_map[$method])) {
                   33479:             $retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
                   33480:             return true;
                   33481:         }
                   33482:         return false;
                   33483:     }
                   33484: 
                   33485:     // }}}
                   33486: }
                   33487: 
                   33488: overload("PEAR_Autoloader");
                   33489: 
                   33490: ?>
                   33491: PEAR-1.9.4/PEAR/Builder.php0000644000076500000240000004065411605156760014075 0ustar  helgistaff<?php
                   33492: /**
                   33493:  * PEAR_Builder for building PHP extensions (PECL packages)
                   33494:  *
                   33495:  * PHP versions 4 and 5
                   33496:  *
                   33497:  * @category   pear
                   33498:  * @package    PEAR
                   33499:  * @author     Stig Bakken <ssb@php.net>
                   33500:  * @author     Greg Beaver <cellog@php.net>
                   33501:  * @copyright  1997-2009 The Authors
                   33502:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33503:  * @version    CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
                   33504:  * @link       http://pear.php.net/package/PEAR
                   33505:  * @since      File available since Release 0.1
                   33506:  *
                   33507:  * TODO: log output parameters in PECL command line
                   33508:  * TODO: msdev path in configuration
                   33509:  */
                   33510: 
                   33511: /**
                   33512:  * Needed for extending PEAR_Builder
                   33513:  */
                   33514: require_once 'PEAR/Common.php';
                   33515: require_once 'PEAR/PackageFile.php';
                   33516: 
                   33517: /**
                   33518:  * Class to handle building (compiling) extensions.
                   33519:  *
                   33520:  * @category   pear
                   33521:  * @package    PEAR
                   33522:  * @author     Stig Bakken <ssb@php.net>
                   33523:  * @author     Greg Beaver <cellog@php.net>
                   33524:  * @copyright  1997-2009 The Authors
                   33525:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33526:  * @version    Release: 1.9.4
                   33527:  * @link       http://pear.php.net/package/PEAR
                   33528:  * @since      Class available since PHP 4.0.2
                   33529:  * @see        http://pear.php.net/manual/en/core.ppm.pear-builder.php
                   33530:  */
                   33531: class PEAR_Builder extends PEAR_Common
                   33532: {
                   33533:     var $php_api_version = 0;
                   33534:     var $zend_module_api_no = 0;
                   33535:     var $zend_extension_api_no = 0;
                   33536: 
                   33537:     var $extensions_built = array();
                   33538: 
                   33539:     /**
                   33540:      * @var string Used for reporting when it is not possible to pass function
                   33541:      *             via extra parameter, e.g. log, msdevCallback
                   33542:      */
                   33543:     var $current_callback = null;
                   33544: 
                   33545:     // used for msdev builds
                   33546:     var $_lastline = null;
                   33547:     var $_firstline = null;
                   33548: 
                   33549:     /**
                   33550:      * PEAR_Builder constructor.
                   33551:      *
                   33552:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
                   33553:      *
                   33554:      * @access public
                   33555:      */
                   33556:     function PEAR_Builder(&$ui)
                   33557:     {
                   33558:         parent::PEAR_Common();
                   33559:         $this->setFrontendObject($ui);
                   33560:     }
                   33561: 
                   33562:     /**
                   33563:      * Build an extension from source on windows.
                   33564:      * requires msdev
                   33565:      */
                   33566:     function _build_win32($descfile, $callback = null)
                   33567:     {
                   33568:         if (is_object($descfile)) {
                   33569:             $pkg = $descfile;
                   33570:             $descfile = $pkg->getPackageFile();
                   33571:         } else {
                   33572:             $pf = &new PEAR_PackageFile($this->config, $this->debug);
                   33573:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   33574:             if (PEAR::isError($pkg)) {
                   33575:                 return $pkg;
                   33576:             }
                   33577:         }
                   33578:         $dir = dirname($descfile);
                   33579:         $old_cwd = getcwd();
                   33580: 
                   33581:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
                   33582:             return $this->raiseError("could not chdir to $dir");
                   33583:         }
                   33584: 
                   33585:         // packages that were in a .tar have the packagefile in this directory
                   33586:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
                   33587:         if (file_exists($dir) && is_dir($vdir)) {
                   33588:             if (!chdir($vdir)) {
                   33589:                 return $this->raiseError("could not chdir to " . realpath($vdir));
                   33590:             }
                   33591: 
                   33592:             $dir = getcwd();
                   33593:         }
                   33594: 
                   33595:         $this->log(2, "building in $dir");
                   33596: 
                   33597:         $dsp = $pkg->getPackage().'.dsp';
                   33598:         if (!file_exists("$dir/$dsp")) {
                   33599:             return $this->raiseError("The DSP $dsp does not exist.");
                   33600:         }
                   33601:         // XXX TODO: make release build type configurable
                   33602:         $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
                   33603: 
                   33604:         $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
                   33605:         if (PEAR::isError($err)) {
                   33606:             return $err;
                   33607:         }
                   33608: 
                   33609:         // figure out the build platform and type
                   33610:         $platform = 'Win32';
                   33611:         $buildtype = 'Release';
                   33612:         if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
                   33613:             $platform = $matches[1];
                   33614:             $buildtype = $matches[2];
                   33615:         }
                   33616: 
                   33617:         if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
                   33618:             if ($matches[2]) {
                   33619:                 // there were errors in the build
                   33620:                 return $this->raiseError("There were errors during compilation.");
                   33621:             }
                   33622:             $out = $matches[1];
                   33623:         } else {
                   33624:             return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
                   33625:         }
                   33626: 
                   33627:         // msdev doesn't tell us the output directory :/
                   33628:         // open the dsp, find /out and use that directory
                   33629:         $dsptext = join(file($dsp),'');
                   33630: 
                   33631:         // this regex depends on the build platform and type having been
                   33632:         // correctly identified above.
                   33633:         $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
                   33634:                     $pkg->getPackage().'\s-\s'.
                   33635:                     $platform.'\s'.
                   33636:                     $buildtype.'").*?'.
                   33637:                     '\/out:"(.*?)"/is';
                   33638: 
                   33639:         if ($dsptext && preg_match($regex, $dsptext, $matches)) {
                   33640:             // what we get back is a relative path to the output file itself.
                   33641:             $outfile = realpath($matches[2]);
                   33642:         } else {
                   33643:             return $this->raiseError("Could not retrieve output information from $dsp.");
                   33644:         }
                   33645:         // realpath returns false if the file doesn't exist
                   33646:         if ($outfile && copy($outfile, "$dir/$out")) {
                   33647:             $outfile = "$dir/$out";
                   33648:         }
                   33649: 
                   33650:         $built_files[] = array(
                   33651:             'file' => "$outfile",
                   33652:             'php_api' => $this->php_api_version,
                   33653:             'zend_mod_api' => $this->zend_module_api_no,
                   33654:             'zend_ext_api' => $this->zend_extension_api_no,
                   33655:             );
                   33656: 
                   33657:         return $built_files;
                   33658:     }
                   33659:     // }}}
                   33660: 
                   33661:     // {{{ msdevCallback()
                   33662:     function msdevCallback($what, $data)
                   33663:     {
                   33664:         if (!$this->_firstline)
                   33665:             $this->_firstline = $data;
                   33666:         $this->_lastline = $data;
                   33667:         call_user_func($this->current_callback, $what, $data);
                   33668:     }
                   33669: 
                   33670:     /**
                   33671:      * @param string
                   33672:      * @param string
                   33673:      * @param array
                   33674:      * @access private
                   33675:      */
                   33676:     function _harvestInstDir($dest_prefix, $dirname, &$built_files)
                   33677:     {
                   33678:         $d = opendir($dirname);
                   33679:         if (!$d)
                   33680:             return false;
                   33681: 
                   33682:         $ret = true;
                   33683:         while (($ent = readdir($d)) !== false) {
                   33684:             if ($ent{0} == '.')
                   33685:                 continue;
                   33686: 
                   33687:             $full = $dirname . DIRECTORY_SEPARATOR . $ent;
                   33688:             if (is_dir($full)) {
                   33689:                 if (!$this->_harvestInstDir(
                   33690:                         $dest_prefix . DIRECTORY_SEPARATOR . $ent,
                   33691:                         $full, $built_files)) {
                   33692:                     $ret = false;
                   33693:                     break;
                   33694:                 }
                   33695:             } else {
                   33696:                 $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
                   33697:                 $built_files[] = array(
                   33698:                         'file' => $full,
                   33699:                         'dest' => $dest,
                   33700:                         'php_api' => $this->php_api_version,
                   33701:                         'zend_mod_api' => $this->zend_module_api_no,
                   33702:                         'zend_ext_api' => $this->zend_extension_api_no,
                   33703:                         );
                   33704:             }
                   33705:         }
                   33706:         closedir($d);
                   33707:         return $ret;
                   33708:     }
                   33709: 
                   33710:     /**
                   33711:      * Build an extension from source.  Runs "phpize" in the source
                   33712:      * directory, but compiles in a temporary directory
                   33713:      * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
                   33714:      *
                   33715:      * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
                   33716:      *               a PEAR_PackageFile object
                   33717:      *
                   33718:      * @param mixed $callback callback function used to report output,
                   33719:      * see PEAR_Builder::_runCommand for details
                   33720:      *
                   33721:      * @return array an array of associative arrays with built files,
                   33722:      * format:
                   33723:      * array( array( 'file' => '/path/to/ext.so',
                   33724:      *               'php_api' => YYYYMMDD,
                   33725:      *               'zend_mod_api' => YYYYMMDD,
                   33726:      *               'zend_ext_api' => YYYYMMDD ),
                   33727:      *        ... )
                   33728:      *
                   33729:      * @access public
                   33730:      *
                   33731:      * @see PEAR_Builder::_runCommand
                   33732:      */
                   33733:     function build($descfile, $callback = null)
                   33734:     {
                   33735:         if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
                   33736:                        $this->config->get('php_bin'), $matches)) {
                   33737:             if (isset($matches[2]) && strlen($matches[2]) &&
                   33738:                 trim($matches[2]) != trim($this->config->get('php_prefix'))) {
                   33739:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                   33740:                            ' appears to have a prefix ' . $matches[2] . ', but' .
                   33741:                            ' config variable php_prefix does not match');
                   33742:             }
                   33743: 
                   33744:             if (isset($matches[3]) && strlen($matches[3]) &&
                   33745:                 trim($matches[3]) != trim($this->config->get('php_suffix'))) {
                   33746:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                   33747:                            ' appears to have a suffix ' . $matches[3] . ', but' .
                   33748:                            ' config variable php_suffix does not match');
                   33749:             }
                   33750:         }
                   33751: 
                   33752:         $this->current_callback = $callback;
                   33753:         if (PEAR_OS == "Windows") {
                   33754:             return $this->_build_win32($descfile, $callback);
                   33755:         }
                   33756: 
                   33757:         if (PEAR_OS != 'Unix') {
                   33758:             return $this->raiseError("building extensions not supported on this platform");
                   33759:         }
                   33760: 
                   33761:         if (is_object($descfile)) {
                   33762:             $pkg = $descfile;
                   33763:             $descfile = $pkg->getPackageFile();
                   33764:             if (is_a($pkg, 'PEAR_PackageFile_v1')) {
                   33765:                 $dir = dirname($descfile);
                   33766:             } else {
                   33767:                 $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
                   33768:                 // automatically delete at session end
                   33769:                 $this->addTempFile($dir);
                   33770:             }
                   33771:         } else {
                   33772:             $pf = &new PEAR_PackageFile($this->config);
                   33773:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   33774:             if (PEAR::isError($pkg)) {
                   33775:                 return $pkg;
                   33776:             }
                   33777:             $dir = dirname($descfile);
                   33778:         }
                   33779: 
                   33780:         // Find config. outside of normal path - e.g. config.m4
                   33781:         foreach (array_keys($pkg->getInstallationFileList()) as $item) {
                   33782:           if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
                   33783:             $dir .= DIRECTORY_SEPARATOR . dirname($item);
                   33784:             break;
                   33785:           }
                   33786:         }
                   33787: 
                   33788:         $old_cwd = getcwd();
                   33789:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
                   33790:             return $this->raiseError("could not chdir to $dir");
                   33791:         }
                   33792: 
                   33793:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
                   33794:         if (is_dir($vdir)) {
                   33795:             chdir($vdir);
                   33796:         }
                   33797: 
                   33798:         $dir = getcwd();
                   33799:         $this->log(2, "building in $dir");
                   33800:         putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
                   33801:         $err = $this->_runCommand($this->config->get('php_prefix')
                   33802:                                 . "phpize" .
                   33803:                                 $this->config->get('php_suffix'),
                   33804:                                 array(&$this, 'phpizeCallback'));
                   33805:         if (PEAR::isError($err)) {
                   33806:             return $err;
                   33807:         }
                   33808: 
                   33809:         if (!$err) {
                   33810:             return $this->raiseError("`phpize' failed");
                   33811:         }
                   33812: 
                   33813:         // {{{ start of interactive part
                   33814:         $configure_command = "$dir/configure";
                   33815:         $configure_options = $pkg->getConfigureOptions();
                   33816:         if ($configure_options) {
                   33817:             foreach ($configure_options as $o) {
                   33818:                 $default = array_key_exists('default', $o) ? $o['default'] : null;
                   33819:                 list($r) = $this->ui->userDialog('build',
                   33820:                                                  array($o['prompt']),
                   33821:                                                  array('text'),
                   33822:                                                  array($default));
                   33823:                 if (substr($o['name'], 0, 5) == 'with-' &&
                   33824:                     ($r == 'yes' || $r == 'autodetect')) {
                   33825:                     $configure_command .= " --$o[name]";
                   33826:                 } else {
                   33827:                     $configure_command .= " --$o[name]=".trim($r);
                   33828:                 }
                   33829:             }
                   33830:         }
                   33831:         // }}} end of interactive part
                   33832: 
                   33833:         // FIXME make configurable
                   33834:         if (!$user=getenv('USER')) {
                   33835:             $user='defaultuser';
                   33836:         }
                   33837: 
                   33838:         $tmpdir = $this->config->get('temp_dir');
                   33839:         $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
                   33840:         $build_dir = "$build_basedir/$vdir";
                   33841:         $inst_dir = "$build_basedir/install-$vdir";
                   33842:         $this->log(1, "building in $build_dir");
                   33843:         if (is_dir($build_dir)) {
                   33844:             System::rm(array('-rf', $build_dir));
                   33845:         }
                   33846: 
                   33847:         if (!System::mkDir(array('-p', $build_dir))) {
                   33848:             return $this->raiseError("could not create build dir: $build_dir");
                   33849:         }
                   33850: 
                   33851:         $this->addTempFile($build_dir);
                   33852:         if (!System::mkDir(array('-p', $inst_dir))) {
                   33853:             return $this->raiseError("could not create temporary install dir: $inst_dir");
                   33854:         }
                   33855:         $this->addTempFile($inst_dir);
                   33856: 
                   33857:         $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
                   33858: 
                   33859:         $to_run = array(
                   33860:             $configure_command,
                   33861:             $make_command,
                   33862:             "$make_command INSTALL_ROOT=\"$inst_dir\" install",
                   33863:             "find \"$inst_dir\" | xargs ls -dils"
                   33864:             );
                   33865:         if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
                   33866:             return $this->raiseError("could not chdir to $build_dir");
                   33867:         }
                   33868:         putenv('PHP_PEAR_VERSION=1.9.4');
                   33869:         foreach ($to_run as $cmd) {
                   33870:             $err = $this->_runCommand($cmd, $callback);
                   33871:             if (PEAR::isError($err)) {
                   33872:                 chdir($old_cwd);
                   33873:                 return $err;
                   33874:             }
                   33875:             if (!$err) {
                   33876:                 chdir($old_cwd);
                   33877:                 return $this->raiseError("`$cmd' failed");
                   33878:             }
                   33879:         }
                   33880:         if (!($dp = opendir("modules"))) {
                   33881:             chdir($old_cwd);
                   33882:             return $this->raiseError("no `modules' directory found");
                   33883:         }
                   33884:         $built_files = array();
                   33885:         $prefix = exec($this->config->get('php_prefix')
                   33886:                         . "php-config" .
                   33887:                        $this->config->get('php_suffix') . " --prefix");
                   33888:         $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
                   33889:         chdir($old_cwd);
                   33890:         return $built_files;
                   33891:     }
                   33892: 
                   33893:     /**
                   33894:      * Message callback function used when running the "phpize"
                   33895:      * program.  Extracts the API numbers used.  Ignores other message
                   33896:      * types than "cmdoutput".
                   33897:      *
                   33898:      * @param string $what the type of message
                   33899:      * @param mixed $data the message
                   33900:      *
                   33901:      * @return void
                   33902:      *
                   33903:      * @access public
                   33904:      */
                   33905:     function phpizeCallback($what, $data)
                   33906:     {
                   33907:         if ($what != 'cmdoutput') {
                   33908:             return;
                   33909:         }
                   33910:         $this->log(1, rtrim($data));
                   33911:         if (preg_match('/You should update your .aclocal.m4/', $data)) {
                   33912:             return;
                   33913:         }
                   33914:         $matches = array();
                   33915:         if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
                   33916:             $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
                   33917:             $apino = (int)$matches[2];
                   33918:             if (isset($this->$member)) {
                   33919:                 $this->$member = $apino;
                   33920:                 //$msg = sprintf("%-22s : %d", $matches[1], $apino);
                   33921:                 //$this->log(1, $msg);
                   33922:             }
                   33923:         }
                   33924:     }
                   33925: 
                   33926:     /**
                   33927:      * Run an external command, using a message callback to report
                   33928:      * output.  The command will be run through popen and output is
                   33929:      * reported for every line with a "cmdoutput" message with the
                   33930:      * line string, including newlines, as payload.
                   33931:      *
                   33932:      * @param string $command the command to run
                   33933:      *
                   33934:      * @param mixed $callback (optional) function to use as message
                   33935:      * callback
                   33936:      *
                   33937:      * @return bool whether the command was successful (exit code 0
                   33938:      * means success, any other means failure)
                   33939:      *
                   33940:      * @access private
                   33941:      */
                   33942:     function _runCommand($command, $callback = null)
                   33943:     {
                   33944:         $this->log(1, "running: $command");
                   33945:         $pp = popen("$command 2>&1", "r");
                   33946:         if (!$pp) {
                   33947:             return $this->raiseError("failed to run `$command'");
                   33948:         }
                   33949:         if ($callback && $callback[0]->debug == 1) {
                   33950:             $olddbg = $callback[0]->debug;
                   33951:             $callback[0]->debug = 2;
                   33952:         }
                   33953: 
                   33954:         while ($line = fgets($pp, 1024)) {
                   33955:             if ($callback) {
                   33956:                 call_user_func($callback, 'cmdoutput', $line);
                   33957:             } else {
                   33958:                 $this->log(2, rtrim($line));
                   33959:             }
                   33960:         }
                   33961:         if ($callback && isset($olddbg)) {
                   33962:             $callback[0]->debug = $olddbg;
                   33963:         }
                   33964: 
                   33965:         $exitcode = is_resource($pp) ? pclose($pp) : -1;
                   33966:         return ($exitcode == 0);
                   33967:     }
                   33968: 
                   33969:     function log($level, $msg)
                   33970:     {
                   33971:         if ($this->current_callback) {
                   33972:             if ($this->debug >= $level) {
                   33973:                 call_user_func($this->current_callback, 'output', $msg);
                   33974:             }
                   33975:             return;
                   33976:         }
                   33977:         return PEAR_Common::log($level, $msg);
                   33978:     }
                   33979: }PEAR-1.9.4/PEAR/ChannelFile.php0000644000076500000240000014335311605156760014657 0ustar  helgistaff<?php
                   33980: /**
                   33981:  * PEAR_ChannelFile, the channel handling class
                   33982:  *
                   33983:  * PHP versions 4 and 5
                   33984:  *
                   33985:  * @category   pear
                   33986:  * @package    PEAR
                   33987:  * @author     Greg Beaver <cellog@php.net>
                   33988:  * @copyright  1997-2009 The Authors
                   33989:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33990:  * @version    CVS: $Id: ChannelFile.php 313023 2011-07-06 19:17:11Z dufuz $
                   33991:  * @link       http://pear.php.net/package/PEAR
                   33992:  * @since      File available since Release 1.4.0a1
                   33993:  */
                   33994: 
                   33995: /**
                   33996:  * Needed for error handling
                   33997:  */
                   33998: require_once 'PEAR/ErrorStack.php';
                   33999: require_once 'PEAR/XMLParser.php';
                   34000: require_once 'PEAR/Common.php';
                   34001: 
                   34002: /**
                   34003:  * Error code if the channel.xml <channel> tag does not contain a valid version
                   34004:  */
                   34005: define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
                   34006: /**
                   34007:  * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
                   34008:  * currently
                   34009:  */
                   34010: define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
                   34011: 
                   34012: /**
                   34013:  * Error code if parsing is attempted with no xml extension
                   34014:  */
                   34015: define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
                   34016: 
                   34017: /**
                   34018:  * Error code if creating the xml parser resource fails
                   34019:  */
                   34020: define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
                   34021: 
                   34022: /**
                   34023:  * Error code used for all sax xml parsing errors
                   34024:  */
                   34025: define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
                   34026: 
                   34027: /**#@+
                   34028:  * Validation errors
                   34029:  */
                   34030: /**
                   34031:  * Error code when channel name is missing
                   34032:  */
                   34033: define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
                   34034: /**
                   34035:  * Error code when channel name is invalid
                   34036:  */
                   34037: define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
                   34038: /**
                   34039:  * Error code when channel summary is missing
                   34040:  */
                   34041: define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
                   34042: /**
                   34043:  * Error code when channel summary is multi-line
                   34044:  */
                   34045: define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
                   34046: /**
                   34047:  * Error code when channel server is missing for protocol
                   34048:  */
                   34049: define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
                   34050: /**
                   34051:  * Error code when channel server is invalid for protocol
                   34052:  */
                   34053: define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
                   34054: /**
                   34055:  * Error code when a mirror name is invalid
                   34056:  */
                   34057: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
                   34058: /**
                   34059:  * Error code when a mirror type is invalid
                   34060:  */
                   34061: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
                   34062: /**
                   34063:  * Error code when an attempt is made to generate xml, but the parsed content is invalid
                   34064:  */
                   34065: define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
                   34066: /**
                   34067:  * Error code when an empty package name validate regex is passed in
                   34068:  */
                   34069: define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
                   34070: /**
                   34071:  * Error code when a <function> tag has no version
                   34072:  */
                   34073: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
                   34074: /**
                   34075:  * Error code when a <function> tag has no name
                   34076:  */
                   34077: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
                   34078: /**
                   34079:  * Error code when a <validatepackage> tag has no name
                   34080:  */
                   34081: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
                   34082: /**
                   34083:  * Error code when a <validatepackage> tag has no version attribute
                   34084:  */
                   34085: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
                   34086: /**
                   34087:  * Error code when a mirror does not exist but is called for in one of the set*
                   34088:  * methods.
                   34089:  */
                   34090: define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
                   34091: /**
                   34092:  * Error code when a server port is not numeric
                   34093:  */
                   34094: define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
                   34095: /**
                   34096:  * Error code when <static> contains no version attribute
                   34097:  */
                   34098: define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
                   34099: /**
                   34100:  * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
                   34101:  */
                   34102: define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
                   34103: /**
                   34104:  * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
                   34105:  */
                   34106: define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
                   34107: /**
                   34108:  * Error code when ssl attribute is present and is not "yes"
                   34109:  */
                   34110: define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
                   34111: /**#@-*/
                   34112: 
                   34113: /**
                   34114:  * Mirror types allowed.  Currently only internet servers are recognized.
                   34115:  */
                   34116: $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
                   34117: 
                   34118: 
                   34119: /**
                   34120:  * The Channel handling class
                   34121:  *
                   34122:  * @category   pear
                   34123:  * @package    PEAR
                   34124:  * @author     Greg Beaver <cellog@php.net>
                   34125:  * @copyright  1997-2009 The Authors
                   34126:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   34127:  * @version    Release: 1.9.4
                   34128:  * @link       http://pear.php.net/package/PEAR
                   34129:  * @since      Class available since Release 1.4.0a1
                   34130:  */
                   34131: class PEAR_ChannelFile
                   34132: {
                   34133:     /**
                   34134:      * @access private
                   34135:      * @var PEAR_ErrorStack
                   34136:      * @access private
                   34137:      */
                   34138:     var $_stack;
                   34139: 
                   34140:     /**
                   34141:      * Supported channel.xml versions, for parsing
                   34142:      * @var array
                   34143:      * @access private
                   34144:      */
                   34145:     var $_supportedVersions = array('1.0');
                   34146: 
                   34147:     /**
                   34148:      * Parsed channel information
                   34149:      * @var array
                   34150:      * @access private
                   34151:      */
                   34152:     var $_channelInfo;
                   34153: 
                   34154:     /**
                   34155:      * index into the subchannels array, used for parsing xml
                   34156:      * @var int
                   34157:      * @access private
                   34158:      */
                   34159:     var $_subchannelIndex;
                   34160: 
                   34161:     /**
                   34162:      * index into the mirrors array, used for parsing xml
                   34163:      * @var int
                   34164:      * @access private
                   34165:      */
                   34166:     var $_mirrorIndex;
                   34167: 
                   34168:     /**
                   34169:      * Flag used to determine the validity of parsed content
                   34170:      * @var boolean
                   34171:      * @access private
                   34172:      */
                   34173:     var $_isValid = false;
                   34174: 
                   34175:     function PEAR_ChannelFile()
                   34176:     {
                   34177:         $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
                   34178:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   34179:         $this->_isValid = false;
                   34180:     }
                   34181: 
                   34182:     /**
                   34183:      * @return array
                   34184:      * @access protected
                   34185:      */
                   34186:     function _getErrorMessage()
                   34187:     {
                   34188:         return
                   34189:             array(
                   34190:                 PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
                   34191:                     'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
                   34192:                 PEAR_CHANNELFILE_ERROR_NO_VERSION =>
                   34193:                     'No version number found in <channel> tag',
                   34194:                 PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
                   34195:                     '%error%',
                   34196:                 PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
                   34197:                     'Unable to create XML parser',
                   34198:                 PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
                   34199:                     '%error%',
                   34200:                 PEAR_CHANNELFILE_ERROR_NO_NAME =>
                   34201:                     'Missing channel name',
                   34202:                 PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
                   34203:                     'Invalid channel %tag% "%name%"',
                   34204:                 PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
                   34205:                     'Missing channel summary',
                   34206:                 PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
                   34207:                     'Channel summary should be on one line, but is multi-line',
                   34208:                 PEAR_CHANNELFILE_ERROR_NO_HOST =>
                   34209:                     'Missing channel server for %type% server',
                   34210:                 PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
                   34211:                     'Server name "%server%" is invalid for %type% server',
                   34212:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
                   34213:                     'Invalid mirror name "%name%", mirror type %type%',
                   34214:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
                   34215:                     'Invalid mirror type "%type%"',
                   34216:                 PEAR_CHANNELFILE_ERROR_INVALID =>
                   34217:                     'Cannot generate xml, contents are invalid',
                   34218:                 PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
                   34219:                     'packagenameregex cannot be empty',
                   34220:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
                   34221:                     '%parent% %protocol% function has no version',
                   34222:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
                   34223:                     '%parent% %protocol% function has no name',
                   34224:                 PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
                   34225:                     '%parent% rest baseurl has no type',
                   34226:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
                   34227:                     'Validation package has no name in <validatepackage> tag',
                   34228:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
                   34229:                     'Validation package "%package%" has no version',
                   34230:                 PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
                   34231:                     'Mirror "%mirror%" does not exist',
                   34232:                 PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
                   34233:                     'Port "%port%" must be numeric',
                   34234:                 PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
                   34235:                     '<static> tag must contain version attribute',
                   34236:                 PEAR_CHANNELFILE_URI_CANT_MIRROR =>
                   34237:                     'The __uri pseudo-channel cannot have mirrors',
                   34238:                 PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
                   34239:                     '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
                   34240:             );
                   34241:     }
                   34242: 
                   34243:     /**
                   34244:      * @param string contents of package.xml file
                   34245:      * @return bool success of parsing
                   34246:      */
                   34247:     function fromXmlString($data)
                   34248:     {
                   34249:         if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
                   34250:             if (!in_array($channelversion[1], $this->_supportedVersions)) {
                   34251:                 $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
                   34252:                     array('version' => $channelversion[1]));
                   34253:                 return false;
                   34254:             }
                   34255:             $parser = new PEAR_XMLParser;
                   34256:             $result = $parser->parse($data);
                   34257:             if ($result !== true) {
                   34258:                 if ($result->getCode() == 1) {
                   34259:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
                   34260:                         array('error' => $result->getMessage()));
                   34261:                 } else {
                   34262:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
                   34263:                 }
                   34264:                 return false;
                   34265:             }
                   34266:             $this->_channelInfo = $parser->getData();
                   34267:             return true;
                   34268:         } else {
                   34269:             $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
                   34270:             return false;
                   34271:         }
                   34272:     }
                   34273: 
                   34274:     /**
                   34275:      * @return array
                   34276:      */
                   34277:     function toArray()
                   34278:     {
                   34279:         if (!$this->_isValid && !$this->validate()) {
                   34280:             return false;
                   34281:         }
                   34282:         return $this->_channelInfo;
                   34283:     }
                   34284: 
                   34285:     /**
                   34286:      * @param array
                   34287:      * @static
                   34288:      * @return PEAR_ChannelFile|false false if invalid
                   34289:      */
                   34290:     function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
                   34291:     {
                   34292:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   34293:         $a->_fromArray($data);
                   34294:         if (!$a->validate()) {
                   34295:             $a = false;
                   34296:             return $a;
                   34297:         }
                   34298:         return $a;
                   34299:     }
                   34300: 
                   34301:     /**
                   34302:      * Unlike {@link fromArray()} this does not do any validation
                   34303:      * @param array
                   34304:      * @static
                   34305:      * @return PEAR_ChannelFile
                   34306:      */
                   34307:     function &fromArrayWithErrors($data, $compatibility = false,
                   34308:                                   $stackClass = 'PEAR_ErrorStack')
                   34309:     {
                   34310:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   34311:         $a->_fromArray($data);
                   34312:         return $a;
                   34313:     }
                   34314: 
                   34315:     /**
                   34316:      * @param array
                   34317:      * @access private
                   34318:      */
                   34319:     function _fromArray($data)
                   34320:     {
                   34321:         $this->_channelInfo = $data;
                   34322:     }
                   34323: 
                   34324:     /**
                   34325:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   34326:      * @param boolean determines whether to purge the error stack after retrieving
                   34327:      * @return array
                   34328:      */
                   34329:     function getErrors($purge = false)
                   34330:     {
                   34331:         return $this->_stack->getErrors($purge);
                   34332:     }
                   34333: 
                   34334:     /**
                   34335:      * Unindent given string (?)
                   34336:      *
                   34337:      * @param string $str The string that has to be unindented.
                   34338:      * @return string
                   34339:      * @access private
                   34340:      */
                   34341:     function _unIndent($str)
                   34342:     {
                   34343:         // remove leading newlines
                   34344:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   34345:         // find whitespace at the beginning of the first line
                   34346:         $indent_len = strspn($str, " \t");
                   34347:         $indent = substr($str, 0, $indent_len);
                   34348:         $data = '';
                   34349:         // remove the same amount of whitespace from following lines
                   34350:         foreach (explode("\n", $str) as $line) {
                   34351:             if (substr($line, 0, $indent_len) == $indent) {
                   34352:                 $data .= substr($line, $indent_len) . "\n";
                   34353:             }
                   34354:         }
                   34355:         return $data;
                   34356:     }
                   34357: 
                   34358:     /**
                   34359:      * Parse a channel.xml file.  Expects the name of
                   34360:      * a channel xml file as input.
                   34361:      *
                   34362:      * @param string  $descfile  name of channel xml file
                   34363:      * @return bool success of parsing
                   34364:      */
                   34365:     function fromXmlFile($descfile)
                   34366:     {
                   34367:         if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
                   34368:              (!$fp = fopen($descfile, 'r'))) {
                   34369:             require_once 'PEAR.php';
                   34370:             return PEAR::raiseError("Unable to open $descfile");
                   34371:         }
                   34372: 
                   34373:         // read the whole thing so we only get one cdata callback
                   34374:         // for each block of cdata
                   34375:         fclose($fp);
                   34376:         $data = file_get_contents($descfile);
                   34377:         return $this->fromXmlString($data);
                   34378:     }
                   34379: 
                   34380:     /**
                   34381:      * Parse channel information from different sources
                   34382:      *
                   34383:      * This method is able to extract information about a channel
                   34384:      * from an .xml file or a string
                   34385:      *
                   34386:      * @access public
                   34387:      * @param  string Filename of the source or the source itself
                   34388:      * @return bool
                   34389:      */
                   34390:     function fromAny($info)
                   34391:     {
                   34392:         if (is_string($info) && file_exists($info) && strlen($info) < 255) {
                   34393:             $tmp = substr($info, -4);
                   34394:             if ($tmp == '.xml') {
                   34395:                 $info = $this->fromXmlFile($info);
                   34396:             } else {
                   34397:                 $fp = fopen($info, "r");
                   34398:                 $test = fread($fp, 5);
                   34399:                 fclose($fp);
                   34400:                 if ($test == "<?xml") {
                   34401:                     $info = $this->fromXmlFile($info);
                   34402:                 }
                   34403:             }
                   34404:             if (PEAR::isError($info)) {
                   34405:                 require_once 'PEAR.php';
                   34406:                 return PEAR::raiseError($info);
                   34407:             }
                   34408:         }
                   34409:         if (is_string($info)) {
                   34410:             $info = $this->fromXmlString($info);
                   34411:         }
                   34412:         return $info;
                   34413:     }
                   34414: 
                   34415:     /**
                   34416:      * Return an XML document based on previous parsing and modifications
                   34417:      *
                   34418:      * @return string XML data
                   34419:      *
                   34420:      * @access public
                   34421:      */
                   34422:     function toXml()
                   34423:     {
                   34424:         if (!$this->_isValid && !$this->validate()) {
                   34425:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
                   34426:             return false;
                   34427:         }
                   34428:         if (!isset($this->_channelInfo['attribs']['version'])) {
                   34429:             $this->_channelInfo['attribs']['version'] = '1.0';
                   34430:         }
                   34431:         $channelInfo = $this->_channelInfo;
                   34432:         $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
                   34433:         $ret .= "<channel version=\"" .
                   34434:             $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
                   34435:   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
                   34436:   xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
                   34437:             . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
                   34438:             $channelInfo['attribs']['version'] . ".xsd\">
                   34439:  <name>$channelInfo[name]</name>
                   34440:  <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
                   34441: ";
                   34442:         if (isset($channelInfo['suggestedalias'])) {
                   34443:             $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
                   34444:         }
                   34445:         if (isset($channelInfo['validatepackage'])) {
                   34446:             $ret .= ' <validatepackage version="' .
                   34447:                 $channelInfo['validatepackage']['attribs']['version']. '">' .
                   34448:                 htmlspecialchars($channelInfo['validatepackage']['_content']) .
                   34449:                 "</validatepackage>\n";
                   34450:         }
                   34451:         $ret .= " <servers>\n";
                   34452:         $ret .= '  <primary';
                   34453:         if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
                   34454:             $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
                   34455:         }
                   34456:         if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
                   34457:             $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
                   34458:         }
                   34459:         $ret .= ">\n";
                   34460:         if (isset($channelInfo['servers']['primary']['rest'])) {
                   34461:             $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
                   34462:         }
                   34463:         $ret .= "  </primary>\n";
                   34464:         if (isset($channelInfo['servers']['mirror'])) {
                   34465:             $ret .= $this->_makeMirrorsXml($channelInfo);
                   34466:         }
                   34467:         $ret .= " </servers>\n";
                   34468:         $ret .= "</channel>";
                   34469:         return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
                   34470:     }
                   34471: 
                   34472:     /**
                   34473:      * Generate the <rest> tag
                   34474:      * @access private
                   34475:      */
                   34476:     function _makeRestXml($info, $indent)
                   34477:     {
                   34478:         $ret = $indent . "<rest>\n";
                   34479:         if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
                   34480:             $info['baseurl'] = array($info['baseurl']);
                   34481:         }
                   34482: 
                   34483:         if (isset($info['baseurl'])) {
                   34484:             foreach ($info['baseurl'] as $url) {
                   34485:                 $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
                   34486:                 $ret .= ">" . $url['_content'] . "</baseurl>\n";
                   34487:             }
                   34488:         }
                   34489:         $ret .= $indent . "</rest>\n";
                   34490:         return $ret;
                   34491:     }
                   34492: 
                   34493:     /**
                   34494:      * Generate the <mirrors> tag
                   34495:      * @access private
                   34496:      */
                   34497:     function _makeMirrorsXml($channelInfo)
                   34498:     {
                   34499:         $ret = "";
                   34500:         if (!isset($channelInfo['servers']['mirror'][0])) {
                   34501:             $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
                   34502:         }
                   34503:         foreach ($channelInfo['servers']['mirror'] as $mirror) {
                   34504:             $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
                   34505:             if (isset($mirror['attribs']['port'])) {
                   34506:                 $ret .= ' port="' . $mirror['attribs']['port'] . '"';
                   34507:             }
                   34508:             if (isset($mirror['attribs']['ssl'])) {
                   34509:                 $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
                   34510:             }
                   34511:             $ret .= ">\n";
                   34512:             if (isset($mirror['rest'])) {
                   34513:                 if (isset($mirror['rest'])) {
                   34514:                     $ret .= $this->_makeRestXml($mirror['rest'], '   ');
                   34515:                 }
                   34516:                 $ret .= "  </mirror>\n";
                   34517:             } else {
                   34518:                 $ret .= "/>\n";
                   34519:             }
                   34520:         }
                   34521:         return $ret;
                   34522:     }
                   34523: 
                   34524:     /**
                   34525:      * Generate the <functions> tag
                   34526:      * @access private
                   34527:      */
                   34528:     function _makeFunctionsXml($functions, $indent, $rest = false)
                   34529:     {
                   34530:         $ret = '';
                   34531:         if (!isset($functions[0])) {
                   34532:             $functions = array($functions);
                   34533:         }
                   34534:         foreach ($functions as $function) {
                   34535:             $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
                   34536:             if ($rest) {
                   34537:                 $ret .= ' uri="' . $function['attribs']['uri'] . '"';
                   34538:             }
                   34539:             $ret .= ">" . $function['_content'] . "</function>\n";
                   34540:         }
                   34541:         return $ret;
                   34542:     }
                   34543: 
                   34544:     /**
                   34545:      * Validation error.  Also marks the object contents as invalid
                   34546:      * @param error code
                   34547:      * @param array error information
                   34548:      * @access private
                   34549:      */
                   34550:     function _validateError($code, $params = array())
                   34551:     {
                   34552:         $this->_stack->push($code, 'error', $params);
                   34553:         $this->_isValid = false;
                   34554:     }
                   34555: 
                   34556:     /**
                   34557:      * Validation warning.  Does not mark the object contents invalid.
                   34558:      * @param error code
                   34559:      * @param array error information
                   34560:      * @access private
                   34561:      */
                   34562:     function _validateWarning($code, $params = array())
                   34563:     {
                   34564:         $this->_stack->push($code, 'warning', $params);
                   34565:     }
                   34566: 
                   34567:     /**
                   34568:      * Validate parsed file.
                   34569:      *
                   34570:      * @access public
                   34571:      * @return boolean
                   34572:      */
                   34573:     function validate()
                   34574:     {
                   34575:         $this->_isValid = true;
                   34576:         $info = $this->_channelInfo;
                   34577:         if (empty($info['name'])) {
                   34578:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
                   34579:         } elseif (!$this->validChannelServer($info['name'])) {
                   34580:             if ($info['name'] != '__uri') {
                   34581:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
                   34582:                     'name' => $info['name']));
                   34583:             }
                   34584:         }
                   34585:         if (empty($info['summary'])) {
                   34586:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   34587:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   34588:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   34589:                 array('summary' => $info['summary']));
                   34590:         }
                   34591:         if (isset($info['suggestedalias'])) {
                   34592:             if (!$this->validChannelServer($info['suggestedalias'])) {
                   34593:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   34594:                     array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
                   34595:             }
                   34596:         }
                   34597:         if (isset($info['localalias'])) {
                   34598:             if (!$this->validChannelServer($info['localalias'])) {
                   34599:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   34600:                     array('tag' => 'localalias', 'name' =>$info['localalias']));
                   34601:             }
                   34602:         }
                   34603:         if (isset($info['validatepackage'])) {
                   34604:             if (!isset($info['validatepackage']['_content'])) {
                   34605:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
                   34606:             }
                   34607:             if (!isset($info['validatepackage']['attribs']['version'])) {
                   34608:                 $content = isset($info['validatepackage']['_content']) ?
                   34609:                     $info['validatepackage']['_content'] :
                   34610:                     null;
                   34611:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
                   34612:                     array('package' => $content));
                   34613:             }
                   34614:         }
                   34615: 
                   34616:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
                   34617:               !is_numeric($info['servers']['primary']['attribs']['port'])) {
                   34618:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
                   34619:                 array('port' => $info['servers']['primary']['attribs']['port']));
                   34620:         }
                   34621: 
                   34622:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
                   34623:               $info['servers']['primary']['attribs']['ssl'] != 'yes') {
                   34624:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   34625:                 array('ssl' => $info['servers']['primary']['attribs']['ssl'],
                   34626:                     'server' => $info['name']));
                   34627:         }
                   34628: 
                   34629:         if (isset($info['servers']['primary']['rest']) &&
                   34630:               isset($info['servers']['primary']['rest']['baseurl'])) {
                   34631:             $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
                   34632:         }
                   34633:         if (isset($info['servers']['mirror'])) {
                   34634:             if ($this->_channelInfo['name'] == '__uri') {
                   34635:                 $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
                   34636:             }
                   34637:             if (!isset($info['servers']['mirror'][0])) {
                   34638:                 $info['servers']['mirror'] = array($info['servers']['mirror']);
                   34639:             }
                   34640:             foreach ($info['servers']['mirror'] as $mirror) {
                   34641:                 if (!isset($mirror['attribs']['host'])) {
                   34642:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
                   34643:                       array('type' => 'mirror'));
                   34644:                 } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
                   34645:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
                   34646:                         array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
                   34647:                 }
                   34648:                 if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
                   34649:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   34650:                         array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
                   34651:                 }
                   34652:                 if (isset($mirror['rest'])) {
                   34653:                     $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
                   34654:                         $mirror['attribs']['host']);
                   34655:                 }
                   34656:             }
                   34657:         }
                   34658:         return $this->_isValid;
                   34659:     }
                   34660: 
                   34661:     /**
                   34662:      * @param string  rest - protocol name this function applies to
                   34663:      * @param array the functions
                   34664:      * @param string the name of the parent element (mirror name, for instance)
                   34665:      */
                   34666:     function _validateFunctions($protocol, $functions, $parent = '')
                   34667:     {
                   34668:         if (!isset($functions[0])) {
                   34669:             $functions = array($functions);
                   34670:         }
                   34671: 
                   34672:         foreach ($functions as $function) {
                   34673:             if (!isset($function['_content']) || empty($function['_content'])) {
                   34674:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
                   34675:                     array('parent' => $parent, 'protocol' => $protocol));
                   34676:             }
                   34677: 
                   34678:             if ($protocol == 'rest') {
                   34679:                 if (!isset($function['attribs']['type']) ||
                   34680:                       empty($function['attribs']['type'])) {
                   34681:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
                   34682:                         array('parent' => $parent, 'protocol' => $protocol));
                   34683:                 }
                   34684:             } else {
                   34685:                 if (!isset($function['attribs']['version']) ||
                   34686:                       empty($function['attribs']['version'])) {
                   34687:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
                   34688:                         array('parent' => $parent, 'protocol' => $protocol));
                   34689:                 }
                   34690:             }
                   34691:         }
                   34692:     }
                   34693: 
                   34694:     /**
                   34695:      * Test whether a string contains a valid channel server.
                   34696:      * @param string $ver the package version to test
                   34697:      * @return bool
                   34698:      */
                   34699:     function validChannelServer($server)
                   34700:     {
                   34701:         if ($server == '__uri') {
                   34702:             return true;
                   34703:         }
                   34704:         return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
                   34705:     }
                   34706: 
                   34707:     /**
                   34708:      * @return string|false
                   34709:      */
                   34710:     function getName()
                   34711:     {
                   34712:         if (isset($this->_channelInfo['name'])) {
                   34713:             return $this->_channelInfo['name'];
                   34714:         }
                   34715: 
                   34716:         return false;
                   34717:     }
                   34718: 
                   34719:     /**
                   34720:      * @return string|false
                   34721:      */
                   34722:     function getServer()
                   34723:     {
                   34724:         if (isset($this->_channelInfo['name'])) {
                   34725:             return $this->_channelInfo['name'];
                   34726:         }
                   34727: 
                   34728:         return false;
                   34729:     }
                   34730: 
                   34731:     /**
                   34732:      * @return int|80 port number to connect to
                   34733:      */
                   34734:     function getPort($mirror = false)
                   34735:     {
                   34736:         if ($mirror) {
                   34737:             if ($mir = $this->getMirror($mirror)) {
                   34738:                 if (isset($mir['attribs']['port'])) {
                   34739:                     return $mir['attribs']['port'];
                   34740:                 }
                   34741: 
                   34742:                 if ($this->getSSL($mirror)) {
                   34743:                     return 443;
                   34744:                 }
                   34745: 
                   34746:                 return 80;
                   34747:             }
                   34748: 
                   34749:             return false;
                   34750:         }
                   34751: 
                   34752:         if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
                   34753:             return $this->_channelInfo['servers']['primary']['attribs']['port'];
                   34754:         }
                   34755: 
                   34756:         if ($this->getSSL()) {
                   34757:             return 443;
                   34758:         }
                   34759: 
                   34760:         return 80;
                   34761:     }
                   34762: 
                   34763:     /**
                   34764:      * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
                   34765:      */
                   34766:     function getSSL($mirror = false)
                   34767:     {
                   34768:         if ($mirror) {
                   34769:             if ($mir = $this->getMirror($mirror)) {
                   34770:                 if (isset($mir['attribs']['ssl'])) {
                   34771:                     return true;
                   34772:                 }
                   34773: 
                   34774:                 return false;
                   34775:             }
                   34776: 
                   34777:             return false;
                   34778:         }
                   34779: 
                   34780:         if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   34781:             return true;
                   34782:         }
                   34783: 
                   34784:         return false;
                   34785:     }
                   34786: 
                   34787:     /**
                   34788:      * @return string|false
                   34789:      */
                   34790:     function getSummary()
                   34791:     {
                   34792:         if (isset($this->_channelInfo['summary'])) {
                   34793:             return $this->_channelInfo['summary'];
                   34794:         }
                   34795: 
                   34796:         return false;
                   34797:     }
                   34798: 
                   34799:     /**
                   34800:      * @param string protocol type
                   34801:      * @param string Mirror name
                   34802:      * @return array|false
                   34803:      */
                   34804:     function getFunctions($protocol, $mirror = false)
                   34805:     {
                   34806:         if ($this->getName() == '__uri') {
                   34807:             return false;
                   34808:         }
                   34809: 
                   34810:         $function = $protocol == 'rest' ? 'baseurl' : 'function';
                   34811:         if ($mirror) {
                   34812:             if ($mir = $this->getMirror($mirror)) {
                   34813:                 if (isset($mir[$protocol][$function])) {
                   34814:                     return $mir[$protocol][$function];
                   34815:                 }
                   34816:             }
                   34817: 
                   34818:             return false;
                   34819:         }
                   34820: 
                   34821:         if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
                   34822:             return $this->_channelInfo['servers']['primary'][$protocol][$function];
                   34823:         }
                   34824: 
                   34825:         return false;
                   34826:     }
                   34827: 
                   34828:     /**
                   34829:      * @param string Protocol type
                   34830:      * @param string Function name (null to return the
                   34831:      *               first protocol of the type requested)
                   34832:      * @param string Mirror name, if any
                   34833:      * @return array
                   34834:      */
                   34835:      function getFunction($type, $name = null, $mirror = false)
                   34836:      {
                   34837:         $protocols = $this->getFunctions($type, $mirror);
                   34838:         if (!$protocols) {
                   34839:             return false;
                   34840:         }
                   34841: 
                   34842:         foreach ($protocols as $protocol) {
                   34843:             if ($name === null) {
                   34844:                 return $protocol;
                   34845:             }
                   34846: 
                   34847:             if ($protocol['_content'] != $name) {
                   34848:                 continue;
                   34849:             }
                   34850: 
                   34851:             return $protocol;
                   34852:         }
                   34853: 
                   34854:         return false;
                   34855:      }
                   34856: 
                   34857:     /**
                   34858:      * @param string protocol type
                   34859:      * @param string protocol name
                   34860:      * @param string version
                   34861:      * @param string mirror name
                   34862:      * @return boolean
                   34863:      */
                   34864:     function supports($type, $name = null, $mirror = false, $version = '1.0')
                   34865:     {
                   34866:         $protocols = $this->getFunctions($type, $mirror);
                   34867:         if (!$protocols) {
                   34868:             return false;
                   34869:         }
                   34870: 
                   34871:         foreach ($protocols as $protocol) {
                   34872:             if ($protocol['attribs']['version'] != $version) {
                   34873:                 continue;
                   34874:             }
                   34875: 
                   34876:             if ($name === null) {
                   34877:                 return true;
                   34878:             }
                   34879: 
                   34880:             if ($protocol['_content'] != $name) {
                   34881:                 continue;
                   34882:             }
                   34883: 
                   34884:             return true;
                   34885:         }
                   34886: 
                   34887:         return false;
                   34888:     }
                   34889: 
                   34890:     /**
                   34891:      * Determines whether a channel supports Representational State Transfer (REST) protocols
                   34892:      * for retrieving channel information
                   34893:      * @param string
                   34894:      * @return bool
                   34895:      */
                   34896:     function supportsREST($mirror = false)
                   34897:     {
                   34898:         if ($mirror == $this->_channelInfo['name']) {
                   34899:             $mirror = false;
                   34900:         }
                   34901: 
                   34902:         if ($mirror) {
                   34903:             if ($mir = $this->getMirror($mirror)) {
                   34904:                 return isset($mir['rest']);
                   34905:             }
                   34906: 
                   34907:             return false;
                   34908:         }
                   34909: 
                   34910:         return isset($this->_channelInfo['servers']['primary']['rest']);
                   34911:     }
                   34912: 
                   34913:     /**
                   34914:      * Get the URL to access a base resource.
                   34915:      *
                   34916:      * Hyperlinks in the returned xml will be used to retrieve the proper information
                   34917:      * needed.  This allows extreme extensibility and flexibility in implementation
                   34918:      * @param string Resource Type to retrieve
                   34919:      */
                   34920:     function getBaseURL($resourceType, $mirror = false)
                   34921:     {
                   34922:         if ($mirror == $this->_channelInfo['name']) {
                   34923:             $mirror = false;
                   34924:         }
                   34925: 
                   34926:         if ($mirror) {
                   34927:             $mir = $this->getMirror($mirror);
                   34928:             if (!$mir) {
                   34929:                 return false;
                   34930:             }
                   34931: 
                   34932:             $rest = $mir['rest'];
                   34933:         } else {
                   34934:             $rest = $this->_channelInfo['servers']['primary']['rest'];
                   34935:         }
                   34936: 
                   34937:         if (!isset($rest['baseurl'][0])) {
                   34938:             $rest['baseurl'] = array($rest['baseurl']);
                   34939:         }
                   34940: 
                   34941:         foreach ($rest['baseurl'] as $baseurl) {
                   34942:             if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
                   34943:                 return $baseurl['_content'];
                   34944:             }
                   34945:         }
                   34946: 
                   34947:         return false;
                   34948:     }
                   34949: 
                   34950:     /**
                   34951:      * Since REST does not implement RPC, provide this as a logical wrapper around
                   34952:      * resetFunctions for REST
                   34953:      * @param string|false mirror name, if any
                   34954:      */
                   34955:     function resetREST($mirror = false)
                   34956:     {
                   34957:         return $this->resetFunctions('rest', $mirror);
                   34958:     }
                   34959: 
                   34960:     /**
                   34961:      * Empty all protocol definitions
                   34962:      * @param string protocol type
                   34963:      * @param string|false mirror name, if any
                   34964:      */
                   34965:     function resetFunctions($type, $mirror = false)
                   34966:     {
                   34967:         if ($mirror) {
                   34968:             if (isset($this->_channelInfo['servers']['mirror'])) {
                   34969:                 $mirrors = $this->_channelInfo['servers']['mirror'];
                   34970:                 if (!isset($mirrors[0])) {
                   34971:                     $mirrors = array($mirrors);
                   34972:                 }
                   34973: 
                   34974:                 foreach ($mirrors as $i => $mir) {
                   34975:                     if ($mir['attribs']['host'] == $mirror) {
                   34976:                         if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
                   34977:                             unset($this->_channelInfo['servers']['mirror'][$i][$type]);
                   34978:                         }
                   34979: 
                   34980:                         return true;
                   34981:                     }
                   34982:                 }
                   34983: 
                   34984:                 return false;
                   34985:             }
                   34986: 
                   34987:             return false;
                   34988:         }
                   34989: 
                   34990:         if (isset($this->_channelInfo['servers']['primary'][$type])) {
                   34991:             unset($this->_channelInfo['servers']['primary'][$type]);
                   34992:         }
                   34993: 
                   34994:         return true;
                   34995:     }
                   34996: 
                   34997:     /**
                   34998:      * Set a channel's protocols to the protocols supported by pearweb
                   34999:      */
                   35000:     function setDefaultPEARProtocols($version = '1.0', $mirror = false)
                   35001:     {
                   35002:         switch ($version) {
                   35003:             case '1.0' :
                   35004:                 $this->resetREST($mirror);
                   35005: 
                   35006:                 if (!isset($this->_channelInfo['servers'])) {
                   35007:                     $this->_channelInfo['servers'] = array('primary' =>
                   35008:                         array('rest' => array()));
                   35009:                 } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   35010:                     $this->_channelInfo['servers']['primary'] = array('rest' => array());
                   35011:                 }
                   35012: 
                   35013:                 return true;
                   35014:             break;
                   35015:             default :
                   35016:                 return false;
                   35017:             break;
                   35018:         }
                   35019:     }
                   35020: 
                   35021:     /**
                   35022:      * @return array
                   35023:      */
                   35024:     function getMirrors()
                   35025:     {
                   35026:         if (isset($this->_channelInfo['servers']['mirror'])) {
                   35027:             $mirrors = $this->_channelInfo['servers']['mirror'];
                   35028:             if (!isset($mirrors[0])) {
                   35029:                 $mirrors = array($mirrors);
                   35030:             }
                   35031: 
                   35032:             return $mirrors;
                   35033:         }
                   35034: 
                   35035:         return array();
                   35036:     }
                   35037: 
                   35038:     /**
                   35039:      * Get the unserialized XML representing a mirror
                   35040:      * @return array|false
                   35041:      */
                   35042:     function getMirror($server)
                   35043:     {
                   35044:         foreach ($this->getMirrors() as $mirror) {
                   35045:             if ($mirror['attribs']['host'] == $server) {
                   35046:                 return $mirror;
                   35047:             }
                   35048:         }
                   35049: 
                   35050:         return false;
                   35051:     }
                   35052: 
                   35053:     /**
                   35054:      * @param string
                   35055:      * @return string|false
                   35056:      * @error PEAR_CHANNELFILE_ERROR_NO_NAME
                   35057:      * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
                   35058:      */
                   35059:     function setName($name)
                   35060:     {
                   35061:         return $this->setServer($name);
                   35062:     }
                   35063: 
                   35064:     /**
                   35065:      * Set the socket number (port) that is used to connect to this channel
                   35066:      * @param integer
                   35067:      * @param string|false name of the mirror server, or false for the primary
                   35068:      */
                   35069:     function setPort($port, $mirror = false)
                   35070:     {
                   35071:         if ($mirror) {
                   35072:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35073:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35074:                     array('mirror' => $mirror));
                   35075:                 return false;
                   35076:             }
                   35077: 
                   35078:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35079:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35080:                     if ($mirror == $mir['attribs']['host']) {
                   35081:                         $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
                   35082:                         return true;
                   35083:                     }
                   35084:                 }
                   35085: 
                   35086:                 return false;
                   35087:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35088:                 $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
                   35089:                 $this->_isValid = false;
                   35090:                 return true;
                   35091:             }
                   35092:         }
                   35093: 
                   35094:         $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
                   35095:         $this->_isValid = false;
                   35096:         return true;
                   35097:     }
                   35098: 
                   35099:     /**
                   35100:      * Set the socket number (port) that is used to connect to this channel
                   35101:      * @param bool Determines whether to turn on SSL support or turn it off
                   35102:      * @param string|false name of the mirror server, or false for the primary
                   35103:      */
                   35104:     function setSSL($ssl = true, $mirror = false)
                   35105:     {
                   35106:         if ($mirror) {
                   35107:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35108:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35109:                     array('mirror' => $mirror));
                   35110:                 return false;
                   35111:             }
                   35112: 
                   35113:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35114:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35115:                     if ($mirror == $mir['attribs']['host']) {
                   35116:                         if (!$ssl) {
                   35117:                             if (isset($this->_channelInfo['servers']['mirror'][$i]
                   35118:                                   ['attribs']['ssl'])) {
                   35119:                                 unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
                   35120:                             }
                   35121:                         } else {
                   35122:                             $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
                   35123:                         }
                   35124: 
                   35125:                         return true;
                   35126:                     }
                   35127:                 }
                   35128: 
                   35129:                 return false;
                   35130:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35131:                 if (!$ssl) {
                   35132:                     if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
                   35133:                         unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
                   35134:                     }
                   35135:                 } else {
                   35136:                     $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
                   35137:                 }
                   35138: 
                   35139:                 $this->_isValid = false;
                   35140:                 return true;
                   35141:             }
                   35142:         }
                   35143: 
                   35144:         if ($ssl) {
                   35145:             $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
                   35146:         } else {
                   35147:             if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   35148:                 unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
                   35149:             }
                   35150:         }
                   35151: 
                   35152:         $this->_isValid = false;
                   35153:         return true;
                   35154:     }
                   35155: 
                   35156:     /**
                   35157:      * @param string
                   35158:      * @return string|false
                   35159:      * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
                   35160:      * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
                   35161:      */
                   35162:     function setServer($server, $mirror = false)
                   35163:     {
                   35164:         if (empty($server)) {
                   35165:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
                   35166:             return false;
                   35167:         } elseif (!$this->validChannelServer($server)) {
                   35168:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   35169:                 array('tag' => 'name', 'name' => $server));
                   35170:             return false;
                   35171:         }
                   35172: 
                   35173:         if ($mirror) {
                   35174:             $found = false;
                   35175:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35176:                 if ($mirror == $mir['attribs']['host']) {
                   35177:                     $found = true;
                   35178:                     break;
                   35179:                 }
                   35180:             }
                   35181: 
                   35182:             if (!$found) {
                   35183:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35184:                     array('mirror' => $mirror));
                   35185:                 return false;
                   35186:             }
                   35187: 
                   35188:             $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
                   35189:             return true;
                   35190:         }
                   35191: 
                   35192:         $this->_channelInfo['name'] = $server;
                   35193:         return true;
                   35194:     }
                   35195: 
                   35196:     /**
                   35197:      * @param string
                   35198:      * @return boolean success
                   35199:      * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
                   35200:      * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
                   35201:      */
                   35202:     function setSummary($summary)
                   35203:     {
                   35204:         if (empty($summary)) {
                   35205:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   35206:             return false;
                   35207:         } elseif (strpos(trim($summary), "\n") !== false) {
                   35208:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   35209:                 array('summary' => $summary));
                   35210:         }
                   35211: 
                   35212:         $this->_channelInfo['summary'] = $summary;
                   35213:         return true;
                   35214:     }
                   35215: 
                   35216:     /**
                   35217:      * @param string
                   35218:      * @param boolean determines whether the alias is in channel.xml or local
                   35219:      * @return boolean success
                   35220:      */
                   35221:     function setAlias($alias, $local = false)
                   35222:     {
                   35223:         if (!$this->validChannelServer($alias)) {
                   35224:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   35225:                 array('tag' => 'suggestedalias', 'name' => $alias));
                   35226:             return false;
                   35227:         }
                   35228: 
                   35229:         if ($local) {
                   35230:             $this->_channelInfo['localalias'] = $alias;
                   35231:         } else {
                   35232:             $this->_channelInfo['suggestedalias'] = $alias;
                   35233:         }
                   35234: 
                   35235:         return true;
                   35236:     }
                   35237: 
                   35238:     /**
                   35239:      * @return string
                   35240:      */
                   35241:     function getAlias()
                   35242:     {
                   35243:         if (isset($this->_channelInfo['localalias'])) {
                   35244:             return $this->_channelInfo['localalias'];
                   35245:         }
                   35246:         if (isset($this->_channelInfo['suggestedalias'])) {
                   35247:             return $this->_channelInfo['suggestedalias'];
                   35248:         }
                   35249:         if (isset($this->_channelInfo['name'])) {
                   35250:             return $this->_channelInfo['name'];
                   35251:         }
                   35252:         return '';
                   35253:     }
                   35254: 
                   35255:     /**
                   35256:      * Set the package validation object if it differs from PEAR's default
                   35257:      * The class must be includeable via changing _ in the classname to path separator,
                   35258:      * but no checking of this is made.
                   35259:      * @param string|false pass in false to reset to the default packagename regex
                   35260:      * @return boolean success
                   35261:      */
                   35262:     function setValidationPackage($validateclass, $version)
                   35263:     {
                   35264:         if (empty($validateclass)) {
                   35265:             unset($this->_channelInfo['validatepackage']);
                   35266:         }
                   35267:         $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
                   35268:         $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
                   35269:     }
                   35270: 
                   35271:     /**
                   35272:      * Add a protocol to the provides section
                   35273:      * @param string protocol type
                   35274:      * @param string protocol version
                   35275:      * @param string protocol name, if any
                   35276:      * @param string mirror name, if this is a mirror's protocol
                   35277:      * @return bool
                   35278:      */
                   35279:     function addFunction($type, $version, $name = '', $mirror = false)
                   35280:     {
                   35281:         if ($mirror) {
                   35282:             return $this->addMirrorFunction($mirror, $type, $version, $name);
                   35283:         }
                   35284: 
                   35285:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   35286:         if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
                   35287:             if (!isset($this->_channelInfo['servers'])) {
                   35288:                 $this->_channelInfo['servers'] = array('primary' =>
                   35289:                     array($type => array()));
                   35290:             } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   35291:                 $this->_channelInfo['servers']['primary'] = array($type => array());
                   35292:             }
                   35293: 
                   35294:             $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
                   35295:             $this->_isValid = false;
                   35296:             return true;
                   35297:         } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
                   35298:             $this->_channelInfo['servers']['primary'][$type]['function'] = array(
                   35299:                 $this->_channelInfo['servers']['primary'][$type]['function']);
                   35300:         }
                   35301: 
                   35302:         $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
                   35303:         return true;
                   35304:     }
                   35305:     /**
                   35306:      * Add a protocol to a mirror's provides section
                   35307:      * @param string mirror name (server)
                   35308:      * @param string protocol type
                   35309:      * @param string protocol version
                   35310:      * @param string protocol name, if any
                   35311:      */
                   35312:     function addMirrorFunction($mirror, $type, $version, $name = '')
                   35313:     {
                   35314:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35315:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35316:                 array('mirror' => $mirror));
                   35317:             return false;
                   35318:         }
                   35319: 
                   35320:         $setmirror = false;
                   35321:         if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35322:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35323:                 if ($mirror == $mir['attribs']['host']) {
                   35324:                     $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   35325:                     break;
                   35326:                 }
                   35327:             }
                   35328:         } else {
                   35329:             if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35330:                 $setmirror = &$this->_channelInfo['servers']['mirror'];
                   35331:             }
                   35332:         }
                   35333: 
                   35334:         if (!$setmirror) {
                   35335:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35336:                 array('mirror' => $mirror));
                   35337:             return false;
                   35338:         }
                   35339: 
                   35340:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   35341:         if (!isset($setmirror[$type]['function'])) {
                   35342:             $setmirror[$type]['function'] = $set;
                   35343:             $this->_isValid = false;
                   35344:             return true;
                   35345:         } elseif (!isset($setmirror[$type]['function'][0])) {
                   35346:             $setmirror[$type]['function'] = array($setmirror[$type]['function']);
                   35347:         }
                   35348: 
                   35349:         $setmirror[$type]['function'][] = $set;
                   35350:         $this->_isValid = false;
                   35351:         return true;
                   35352:     }
                   35353: 
                   35354:     /**
                   35355:      * @param string Resource Type this url links to
                   35356:      * @param string URL
                   35357:      * @param string|false mirror name, if this is not a primary server REST base URL
                   35358:      */
                   35359:     function setBaseURL($resourceType, $url, $mirror = false)
                   35360:     {
                   35361:         if ($mirror) {
                   35362:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35363:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35364:                     array('mirror' => $mirror));
                   35365:                 return false;
                   35366:             }
                   35367: 
                   35368:             $setmirror = false;
                   35369:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35370:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35371:                     if ($mirror == $mir['attribs']['host']) {
                   35372:                         $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   35373:                         break;
                   35374:                     }
                   35375:                 }
                   35376:             } else {
                   35377:                 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35378:                     $setmirror = &$this->_channelInfo['servers']['mirror'];
                   35379:                 }
                   35380:             }
                   35381:         } else {
                   35382:             $setmirror = &$this->_channelInfo['servers']['primary'];
                   35383:         }
                   35384: 
                   35385:         $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
                   35386:         if (!isset($setmirror['rest'])) {
                   35387:             $setmirror['rest'] = array();
                   35388:         }
                   35389: 
                   35390:         if (!isset($setmirror['rest']['baseurl'])) {
                   35391:             $setmirror['rest']['baseurl'] = $set;
                   35392:             $this->_isValid = false;
                   35393:             return true;
                   35394:         } elseif (!isset($setmirror['rest']['baseurl'][0])) {
                   35395:             $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
                   35396:         }
                   35397: 
                   35398:         foreach ($setmirror['rest']['baseurl'] as $i => $url) {
                   35399:             if ($url['attribs']['type'] == $resourceType) {
                   35400:                 $this->_isValid = false;
                   35401:                 $setmirror['rest']['baseurl'][$i] = $set;
                   35402:                 return true;
                   35403:             }
                   35404:         }
                   35405: 
                   35406:         $setmirror['rest']['baseurl'][] = $set;
                   35407:         $this->_isValid = false;
                   35408:         return true;
                   35409:     }
                   35410: 
                   35411:     /**
                   35412:      * @param string mirror server
                   35413:      * @param int mirror http port
                   35414:      * @return boolean
                   35415:      */
                   35416:     function addMirror($server, $port = null)
                   35417:     {
                   35418:         if ($this->_channelInfo['name'] == '__uri') {
                   35419:             return false; // the __uri channel cannot have mirrors by definition
                   35420:         }
                   35421: 
                   35422:         $set = array('attribs' => array('host' => $server));
                   35423:         if (is_numeric($port)) {
                   35424:             $set['attribs']['port'] = $port;
                   35425:         }
                   35426: 
                   35427:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35428:             $this->_channelInfo['servers']['mirror'] = $set;
                   35429:             return true;
                   35430:         }
                   35431: 
                   35432:         if (!isset($this->_channelInfo['servers']['mirror'][0])) {
                   35433:             $this->_channelInfo['servers']['mirror'] =
                   35434:                 array($this->_channelInfo['servers']['mirror']);
                   35435:         }
                   35436: 
                   35437:         $this->_channelInfo['servers']['mirror'][] = $set;
                   35438:         return true;
                   35439:     }
                   35440: 
                   35441:     /**
                   35442:      * Retrieve the name of the validation package for this channel
                   35443:      * @return string|false
                   35444:      */
                   35445:     function getValidationPackage()
                   35446:     {
                   35447:         if (!$this->_isValid && !$this->validate()) {
                   35448:             return false;
                   35449:         }
                   35450: 
                   35451:         if (!isset($this->_channelInfo['validatepackage'])) {
                   35452:             return array('attribs' => array('version' => 'default'),
                   35453:                 '_content' => 'PEAR_Validate');
                   35454:         }
                   35455: 
                   35456:         return $this->_channelInfo['validatepackage'];
                   35457:     }
                   35458: 
                   35459:     /**
                   35460:      * Retrieve the object that can be used for custom validation
                   35461:      * @param string|false the name of the package to validate.  If the package is
                   35462:      *                     the channel validation package, PEAR_Validate is returned
                   35463:      * @return PEAR_Validate|false false is returned if the validation package
                   35464:      *         cannot be located
                   35465:      */
                   35466:     function &getValidationObject($package = false)
                   35467:     {
                   35468:         if (!class_exists('PEAR_Validate')) {
                   35469:             require_once 'PEAR/Validate.php';
                   35470:         }
                   35471: 
                   35472:         if (!$this->_isValid) {
                   35473:             if (!$this->validate()) {
                   35474:                 $a = false;
                   35475:                 return $a;
                   35476:             }
                   35477:         }
                   35478: 
                   35479:         if (isset($this->_channelInfo['validatepackage'])) {
                   35480:             if ($package == $this->_channelInfo['validatepackage']) {
                   35481:                 // channel validation packages are always validated by PEAR_Validate
                   35482:                 $val = &new PEAR_Validate;
                   35483:                 return $val;
                   35484:             }
                   35485: 
                   35486:             if (!class_exists(str_replace('.', '_',
                   35487:                   $this->_channelInfo['validatepackage']['_content']))) {
                   35488:                 if ($this->isIncludeable(str_replace('_', '/',
                   35489:                       $this->_channelInfo['validatepackage']['_content']) . '.php')) {
                   35490:                     include_once str_replace('_', '/',
                   35491:                         $this->_channelInfo['validatepackage']['_content']) . '.php';
                   35492:                     $vclass = str_replace('.', '_',
                   35493:                         $this->_channelInfo['validatepackage']['_content']);
                   35494:                     $val = &new $vclass;
                   35495:                 } else {
                   35496:                     $a = false;
                   35497:                     return $a;
                   35498:                 }
                   35499:             } else {
                   35500:                 $vclass = str_replace('.', '_',
                   35501:                     $this->_channelInfo['validatepackage']['_content']);
                   35502:                 $val = &new $vclass;
                   35503:             }
                   35504:         } else {
                   35505:             $val = &new PEAR_Validate;
                   35506:         }
                   35507: 
                   35508:         return $val;
                   35509:     }
                   35510: 
                   35511:     function isIncludeable($path)
                   35512:     {
                   35513:         $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
                   35514:         foreach ($possibilities as $dir) {
                   35515:             if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
                   35516:                   && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
                   35517:                 return true;
                   35518:             }
                   35519:         }
                   35520: 
                   35521:         return false;
                   35522:     }
                   35523: 
                   35524:     /**
                   35525:      * This function is used by the channel updater and retrieves a value set by
                   35526:      * the registry, or the current time if it has not been set
                   35527:      * @return string
                   35528:      */
                   35529:     function lastModified()
                   35530:     {
                   35531:         if (isset($this->_channelInfo['_lastmodified'])) {
                   35532:             return $this->_channelInfo['_lastmodified'];
                   35533:         }
                   35534: 
                   35535:         return time();
                   35536:     }
                   35537: }PEAR-1.9.4/PEAR/Command.php0000644000076500000240000003063311605156760014061 0ustar  helgistaff<?php
                   35538: /**
                   35539:  * PEAR_Command, command pattern class
                   35540:  *
                   35541:  * PHP versions 4 and 5
                   35542:  *
                   35543:  * @category   pear
                   35544:  * @package    PEAR
                   35545:  * @author     Stig Bakken <ssb@php.net>
                   35546:  * @author     Greg Beaver <cellog@php.net>
                   35547:  * @copyright  1997-2009 The Authors
                   35548:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   35549:  * @version    CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $
                   35550:  * @link       http://pear.php.net/package/PEAR
                   35551:  * @since      File available since Release 0.1
                   35552:  */
                   35553: 
                   35554: /**
                   35555:  * Needed for error handling
                   35556:  */
                   35557: require_once 'PEAR.php';
                   35558: require_once 'PEAR/Frontend.php';
                   35559: require_once 'PEAR/XMLParser.php';
                   35560: 
                   35561: /**
                   35562:  * List of commands and what classes they are implemented in.
                   35563:  * @var array command => implementing class
                   35564:  */
                   35565: $GLOBALS['_PEAR_Command_commandlist'] = array();
                   35566: 
                   35567: /**
                   35568:  * List of commands and their descriptions
                   35569:  * @var array command => description
                   35570:  */
                   35571: $GLOBALS['_PEAR_Command_commanddesc'] = array();
                   35572: 
                   35573: /**
                   35574:  * List of shortcuts to common commands.
                   35575:  * @var array shortcut => command
                   35576:  */
                   35577: $GLOBALS['_PEAR_Command_shortcuts'] = array();
                   35578: 
                   35579: /**
                   35580:  * Array of command objects
                   35581:  * @var array class => object
                   35582:  */
                   35583: $GLOBALS['_PEAR_Command_objects'] = array();
                   35584: 
                   35585: /**
                   35586:  * PEAR command class, a simple factory class for administrative
                   35587:  * commands.
                   35588:  *
                   35589:  * How to implement command classes:
                   35590:  *
                   35591:  * - The class must be called PEAR_Command_Nnn, installed in the
                   35592:  *   "PEAR/Common" subdir, with a method called getCommands() that
                   35593:  *   returns an array of the commands implemented by the class (see
                   35594:  *   PEAR/Command/Install.php for an example).
                   35595:  *
                   35596:  * - The class must implement a run() function that is called with three
                   35597:  *   params:
                   35598:  *
                   35599:  *    (string) command name
                   35600:  *    (array)  assoc array with options, freely defined by each
                   35601:  *             command, for example:
                   35602:  *             array('force' => true)
                   35603:  *    (array)  list of the other parameters
                   35604:  *
                   35605:  *   The run() function returns a PEAR_CommandResponse object.  Use
                   35606:  *   these methods to get information:
                   35607:  *
                   35608:  *    int getStatus()   Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
                   35609:  *                      *_PARTIAL means that you need to issue at least
                   35610:  *                      one more command to complete the operation
                   35611:  *                      (used for example for validation steps).
                   35612:  *
                   35613:  *    string getMessage()  Returns a message for the user.  Remember,
                   35614:  *                         no HTML or other interface-specific markup.
                   35615:  *
                   35616:  *   If something unexpected happens, run() returns a PEAR error.
                   35617:  *
                   35618:  * - DON'T OUTPUT ANYTHING! Return text for output instead.
                   35619:  *
                   35620:  * - DON'T USE HTML! The text you return will be used from both Gtk,
                   35621:  *   web and command-line interfaces, so for now, keep everything to
                   35622:  *   plain text.
                   35623:  *
                   35624:  * - DON'T USE EXIT OR DIE! Always use pear errors.  From static
                   35625:  *   classes do PEAR::raiseError(), from other classes do
                   35626:  *   $this->raiseError().
                   35627:  * @category   pear
                   35628:  * @package    PEAR
                   35629:  * @author     Stig Bakken <ssb@php.net>
                   35630:  * @author     Greg Beaver <cellog@php.net>
                   35631:  * @copyright  1997-2009 The Authors
                   35632:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   35633:  * @version    Release: 1.9.4
                   35634:  * @link       http://pear.php.net/package/PEAR
                   35635:  * @since      Class available since Release 0.1
                   35636:  */
                   35637: class PEAR_Command
                   35638: {
                   35639:     // {{{ factory()
                   35640: 
                   35641:     /**
                   35642:      * Get the right object for executing a command.
                   35643:      *
                   35644:      * @param string $command The name of the command
                   35645:      * @param object $config  Instance of PEAR_Config object
                   35646:      *
                   35647:      * @return object the command object or a PEAR error
                   35648:      *
                   35649:      * @access public
                   35650:      * @static
                   35651:      */
                   35652:     function &factory($command, &$config)
                   35653:     {
                   35654:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   35655:             PEAR_Command::registerCommands();
                   35656:         }
                   35657:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   35658:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   35659:         }
                   35660:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   35661:             $a = PEAR::raiseError("unknown command `$command'");
                   35662:             return $a;
                   35663:         }
                   35664:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   35665:         if (!class_exists($class)) {
                   35666:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   35667:         }
                   35668:         if (!class_exists($class)) {
                   35669:             $a = PEAR::raiseError("unknown command `$command'");
                   35670:             return $a;
                   35671:         }
                   35672:         $ui =& PEAR_Command::getFrontendObject();
                   35673:         $obj = &new $class($ui, $config);
                   35674:         return $obj;
                   35675:     }
                   35676: 
                   35677:     // }}}
                   35678:     // {{{ & getObject()
                   35679:     function &getObject($command)
                   35680:     {
                   35681:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   35682:         if (!class_exists($class)) {
                   35683:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   35684:         }
                   35685:         if (!class_exists($class)) {
                   35686:             return PEAR::raiseError("unknown command `$command'");
                   35687:         }
                   35688:         $ui =& PEAR_Command::getFrontendObject();
                   35689:         $config = &PEAR_Config::singleton();
                   35690:         $obj = &new $class($ui, $config);
                   35691:         return $obj;
                   35692:     }
                   35693: 
                   35694:     // }}}
                   35695:     // {{{ & getFrontendObject()
                   35696: 
                   35697:     /**
                   35698:      * Get instance of frontend object.
                   35699:      *
                   35700:      * @return object|PEAR_Error
                   35701:      * @static
                   35702:      */
                   35703:     function &getFrontendObject()
                   35704:     {
                   35705:         $a = &PEAR_Frontend::singleton();
                   35706:         return $a;
                   35707:     }
                   35708: 
                   35709:     // }}}
                   35710:     // {{{ & setFrontendClass()
                   35711: 
                   35712:     /**
                   35713:      * Load current frontend class.
                   35714:      *
                   35715:      * @param string $uiclass Name of class implementing the frontend
                   35716:      *
                   35717:      * @return object the frontend object, or a PEAR error
                   35718:      * @static
                   35719:      */
                   35720:     function &setFrontendClass($uiclass)
                   35721:     {
                   35722:         $a = &PEAR_Frontend::setFrontendClass($uiclass);
                   35723:         return $a;
                   35724:     }
                   35725: 
                   35726:     // }}}
                   35727:     // {{{ setFrontendType()
                   35728: 
                   35729:     /**
                   35730:      * Set current frontend.
                   35731:      *
                   35732:      * @param string $uitype Name of the frontend type (for example "CLI")
                   35733:      *
                   35734:      * @return object the frontend object, or a PEAR error
                   35735:      * @static
                   35736:      */
                   35737:     function setFrontendType($uitype)
                   35738:     {
                   35739:         $uiclass = 'PEAR_Frontend_' . $uitype;
                   35740:         return PEAR_Command::setFrontendClass($uiclass);
                   35741:     }
                   35742: 
                   35743:     // }}}
                   35744:     // {{{ registerCommands()
                   35745: 
                   35746:     /**
                   35747:      * Scan through the Command directory looking for classes
                   35748:      * and see what commands they implement.
                   35749:      *
                   35750:      * @param bool   (optional) if FALSE (default), the new list of
                   35751:      *               commands should replace the current one.  If TRUE,
                   35752:      *               new entries will be merged with old.
                   35753:      *
                   35754:      * @param string (optional) where (what directory) to look for
                   35755:      *               classes, defaults to the Command subdirectory of
                   35756:      *               the directory from where this file (__FILE__) is
                   35757:      *               included.
                   35758:      *
                   35759:      * @return bool TRUE on success, a PEAR error on failure
                   35760:      *
                   35761:      * @access public
                   35762:      * @static
                   35763:      */
                   35764:     function registerCommands($merge = false, $dir = null)
                   35765:     {
                   35766:         $parser = new PEAR_XMLParser;
                   35767:         if ($dir === null) {
                   35768:             $dir = dirname(__FILE__) . '/Command';
                   35769:         }
                   35770:         if (!is_dir($dir)) {
                   35771:             return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
                   35772:         }
                   35773:         $dp = @opendir($dir);
                   35774:         if (empty($dp)) {
                   35775:             return PEAR::raiseError("registerCommands: opendir($dir) failed");
                   35776:         }
                   35777:         if (!$merge) {
                   35778:             $GLOBALS['_PEAR_Command_commandlist'] = array();
                   35779:         }
                   35780: 
                   35781:         while ($file = readdir($dp)) {
                   35782:             if ($file{0} == '.' || substr($file, -4) != '.xml') {
                   35783:                 continue;
                   35784:             }
                   35785: 
                   35786:             $f = substr($file, 0, -4);
                   35787:             $class = "PEAR_Command_" . $f;
                   35788:             // List of commands
                   35789:             if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
                   35790:                 $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
                   35791:             }
                   35792: 
                   35793:             $parser->parse(file_get_contents("$dir/$file"));
                   35794:             $implements = $parser->getData();
                   35795:             foreach ($implements as $command => $desc) {
                   35796:                 if ($command == 'attribs') {
                   35797:                     continue;
                   35798:                 }
                   35799: 
                   35800:                 if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   35801:                     return PEAR::raiseError('Command "' . $command . '" already registered in ' .
                   35802:                         'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   35803:                 }
                   35804: 
                   35805:                 $GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
                   35806:                 $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
                   35807:                 if (isset($desc['shortcut'])) {
                   35808:                     $shortcut = $desc['shortcut'];
                   35809:                     if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
                   35810:                         return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
                   35811:                             'registered to command "' . $command . '" in class "' .
                   35812:                             $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   35813:                     }
                   35814:                     $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
                   35815:                 }
                   35816: 
                   35817:                 if (isset($desc['options']) && $desc['options']) {
                   35818:                     foreach ($desc['options'] as $oname => $option) {
                   35819:                         if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
                   35820:                             return PEAR::raiseError('Option "' . $oname . '" short option "' .
                   35821:                                 $option['shortopt'] . '" must be ' .
                   35822:                                 'only 1 character in Command "' . $command . '" in class "' .
                   35823:                                 $class . '"');
                   35824:                         }
                   35825:                     }
                   35826:                 }
                   35827:             }
                   35828:         }
                   35829: 
                   35830:         ksort($GLOBALS['_PEAR_Command_shortcuts']);
                   35831:         ksort($GLOBALS['_PEAR_Command_commandlist']);
                   35832:         @closedir($dp);
                   35833:         return true;
                   35834:     }
                   35835: 
                   35836:     // }}}
                   35837:     // {{{ getCommands()
                   35838: 
                   35839:     /**
                   35840:      * Get the list of currently supported commands, and what
                   35841:      * classes implement them.
                   35842:      *
                   35843:      * @return array command => implementing class
                   35844:      *
                   35845:      * @access public
                   35846:      * @static
                   35847:      */
                   35848:     function getCommands()
                   35849:     {
                   35850:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   35851:             PEAR_Command::registerCommands();
                   35852:         }
                   35853:         return $GLOBALS['_PEAR_Command_commandlist'];
                   35854:     }
                   35855: 
                   35856:     // }}}
                   35857:     // {{{ getShortcuts()
                   35858: 
                   35859:     /**
                   35860:      * Get the list of command shortcuts.
                   35861:      *
                   35862:      * @return array shortcut => command
                   35863:      *
                   35864:      * @access public
                   35865:      * @static
                   35866:      */
                   35867:     function getShortcuts()
                   35868:     {
                   35869:         if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
                   35870:             PEAR_Command::registerCommands();
                   35871:         }
                   35872:         return $GLOBALS['_PEAR_Command_shortcuts'];
                   35873:     }
                   35874: 
                   35875:     // }}}
                   35876:     // {{{ getGetoptArgs()
                   35877: 
                   35878:     /**
                   35879:      * Compiles arguments for getopt.
                   35880:      *
                   35881:      * @param string $command     command to get optstring for
                   35882:      * @param string $short_args  (reference) short getopt format
                   35883:      * @param array  $long_args   (reference) long getopt format
                   35884:      *
                   35885:      * @return void
                   35886:      *
                   35887:      * @access public
                   35888:      * @static
                   35889:      */
                   35890:     function getGetoptArgs($command, &$short_args, &$long_args)
                   35891:     {
                   35892:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   35893:             PEAR_Command::registerCommands();
                   35894:         }
                   35895:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   35896:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   35897:         }
                   35898:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   35899:             return null;
                   35900:         }
                   35901:         $obj = &PEAR_Command::getObject($command);
                   35902:         return $obj->getGetoptArgs($command, $short_args, $long_args);
                   35903:     }
                   35904: 
                   35905:     // }}}
                   35906:     // {{{ getDescription()
                   35907: 
                   35908:     /**
                   35909:      * Get description for a command.
                   35910:      *
                   35911:      * @param  string $command Name of the command
                   35912:      *
                   35913:      * @return string command description
                   35914:      *
                   35915:      * @access public
                   35916:      * @static
                   35917:      */
                   35918:     function getDescription($command)
                   35919:     {
                   35920:         if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
                   35921:             return null;
                   35922:         }
                   35923:         return $GLOBALS['_PEAR_Command_commanddesc'][$command];
                   35924:     }
                   35925: 
                   35926:     // }}}
                   35927:     // {{{ getHelp()
                   35928: 
                   35929:     /**
                   35930:      * Get help for command.
                   35931:      *
                   35932:      * @param string $command Name of the command to return help for
                   35933:      *
                   35934:      * @access public
                   35935:      * @static
                   35936:      */
                   35937:     function getHelp($command)
                   35938:     {
                   35939:         $cmds = PEAR_Command::getCommands();
                   35940:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   35941:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   35942:         }
                   35943:         if (isset($cmds[$command])) {
                   35944:             $obj = &PEAR_Command::getObject($command);
                   35945:             return $obj->getHelp($command);
                   35946:         }
                   35947:         return false;
                   35948:     }
                   35949:     // }}}
                   35950: }PEAR-1.9.4/PEAR/Common.php0000644000076500000240000006225511605156760013740 0ustar  helgistaff<?php
                   35951: /**
                   35952:  * PEAR_Common, the base class for the PEAR Installer
                   35953:  *
                   35954:  * PHP versions 4 and 5
                   35955:  *
                   35956:  * @category   pear
                   35957:  * @package    PEAR
                   35958:  * @author     Stig Bakken <ssb@php.net>
                   35959:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   35960:  * @author     Greg Beaver <cellog@php.net>
                   35961:  * @copyright  1997-2009 The Authors
                   35962:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   35963:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   35964:  * @link       http://pear.php.net/package/PEAR
                   35965:  * @since      File available since Release 0.1.0
                   35966:  * @deprecated File deprecated since Release 1.4.0a1
                   35967:  */
                   35968: 
                   35969: /**
                   35970:  * Include error handling
                   35971:  */
                   35972: require_once 'PEAR.php';
                   35973: 
                   35974: /**
                   35975:  * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
                   35976:  */
                   35977: define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
                   35978: define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
                   35979: define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
                   35980: 
                   35981: // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
                   35982: define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
                   35983: define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
                   35984: 
                   35985: // XXX far from perfect :-)
                   35986: define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
                   35987:     ')(-([.0-9a-zA-Z]+))?');
                   35988: define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
                   35989:     '\\z/');
                   35990: 
                   35991: define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
                   35992: define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
                   35993: 
                   35994: // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
                   35995: define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
                   35996: define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
                   35997: 
                   35998: define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
                   35999:          . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
                   36000: define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
                   36001: 
                   36002: define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
                   36003:     . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
                   36004: define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
                   36005: 
                   36006: /**
                   36007:  * List of temporary files and directories registered by
                   36008:  * PEAR_Common::addTempFile().
                   36009:  * @var array
                   36010:  */
                   36011: $GLOBALS['_PEAR_Common_tempfiles'] = array();
                   36012: 
                   36013: /**
                   36014:  * Valid maintainer roles
                   36015:  * @var array
                   36016:  */
                   36017: $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
                   36018: 
                   36019: /**
                   36020:  * Valid release states
                   36021:  * @var array
                   36022:  */
                   36023: $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
                   36024: 
                   36025: /**
                   36026:  * Valid dependency types
                   36027:  * @var array
                   36028:  */
                   36029: $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
                   36030: 
                   36031: /**
                   36032:  * Valid dependency relations
                   36033:  * @var array
                   36034:  */
                   36035: $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
                   36036: 
                   36037: /**
                   36038:  * Valid file roles
                   36039:  * @var array
                   36040:  */
                   36041: $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
                   36042: 
                   36043: /**
                   36044:  * Valid replacement types
                   36045:  * @var array
                   36046:  */
                   36047: $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
                   36048: 
                   36049: /**
                   36050:  * Valid "provide" types
                   36051:  * @var array
                   36052:  */
                   36053: $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
                   36054: 
                   36055: /**
                   36056:  * Valid "provide" types
                   36057:  * @var array
                   36058:  */
                   36059: $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');
                   36060: 
                   36061: /**
                   36062:  * Class providing common functionality for PEAR administration classes.
                   36063:  * @category   pear
                   36064:  * @package    PEAR
                   36065:  * @author     Stig Bakken <ssb@php.net>
                   36066:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   36067:  * @author     Greg Beaver <cellog@php.net>
                   36068:  * @copyright  1997-2009 The Authors
                   36069:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   36070:  * @version    Release: 1.9.4
                   36071:  * @link       http://pear.php.net/package/PEAR
                   36072:  * @since      Class available since Release 1.4.0a1
                   36073:  * @deprecated This class will disappear, and its components will be spread
                   36074:  *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
                   36075:  */
                   36076: class PEAR_Common extends PEAR
                   36077: {
                   36078:     /**
                   36079:      * User Interface object (PEAR_Frontend_* class).  If null,
                   36080:      * the log() method uses print.
                   36081:      * @var object
                   36082:      */
                   36083:     var $ui = null;
                   36084: 
                   36085:     /**
                   36086:      * Configuration object (PEAR_Config).
                   36087:      * @var PEAR_Config
                   36088:      */
                   36089:     var $config = null;
                   36090: 
                   36091:     /** stack of elements, gives some sort of XML context */
                   36092:     var $element_stack = array();
                   36093: 
                   36094:     /** name of currently parsed XML element */
                   36095:     var $current_element;
                   36096: 
                   36097:     /** array of attributes of the currently parsed XML element */
                   36098:     var $current_attributes = array();
                   36099: 
                   36100:     /** assoc with information about a package */
                   36101:     var $pkginfo = array();
                   36102: 
                   36103:     var $current_path = null;
                   36104: 
                   36105:     /**
                   36106:      * Flag variable used to mark a valid package file
                   36107:      * @var boolean
                   36108:      * @access private
                   36109:      */
                   36110:     var $_validPackageFile;
                   36111: 
                   36112:     /**
                   36113:      * PEAR_Common constructor
                   36114:      *
                   36115:      * @access public
                   36116:      */
                   36117:     function PEAR_Common()
                   36118:     {
                   36119:         parent::PEAR();
                   36120:         $this->config = &PEAR_Config::singleton();
                   36121:         $this->debug = $this->config->get('verbose');
                   36122:     }
                   36123: 
                   36124:     /**
                   36125:      * PEAR_Common destructor
                   36126:      *
                   36127:      * @access private
                   36128:      */
                   36129:     function _PEAR_Common()
                   36130:     {
                   36131:         // doesn't work due to bug #14744
                   36132:         //$tempfiles = $this->_tempfiles;
                   36133:         $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
                   36134:         while ($file = array_shift($tempfiles)) {
                   36135:             if (@is_dir($file)) {
                   36136:                 if (!class_exists('System')) {
                   36137:                     require_once 'System.php';
                   36138:                 }
                   36139: 
                   36140:                 System::rm(array('-rf', $file));
                   36141:             } elseif (file_exists($file)) {
                   36142:                 unlink($file);
                   36143:             }
                   36144:         }
                   36145:     }
                   36146: 
                   36147:     /**
                   36148:      * Register a temporary file or directory.  When the destructor is
                   36149:      * executed, all registered temporary files and directories are
                   36150:      * removed.
                   36151:      *
                   36152:      * @param string  $file  name of file or directory
                   36153:      *
                   36154:      * @return void
                   36155:      *
                   36156:      * @access public
                   36157:      */
                   36158:     function addTempFile($file)
                   36159:     {
                   36160:         if (!class_exists('PEAR_Frontend')) {
                   36161:             require_once 'PEAR/Frontend.php';
                   36162:         }
                   36163:         PEAR_Frontend::addTempFile($file);
                   36164:     }
                   36165: 
                   36166:     /**
                   36167:      * Wrapper to System::mkDir(), creates a directory as well as
                   36168:      * any necessary parent directories.
                   36169:      *
                   36170:      * @param string  $dir  directory name
                   36171:      *
                   36172:      * @return bool TRUE on success, or a PEAR error
                   36173:      *
                   36174:      * @access public
                   36175:      */
                   36176:     function mkDirHier($dir)
                   36177:     {
                   36178:         // Only used in Installer - move it there ?
                   36179:         $this->log(2, "+ create dir $dir");
                   36180:         if (!class_exists('System')) {
                   36181:             require_once 'System.php';
                   36182:         }
                   36183:         return System::mkDir(array('-p', $dir));
                   36184:     }
                   36185: 
                   36186:     /**
                   36187:      * Logging method.
                   36188:      *
                   36189:      * @param int    $level  log level (0 is quiet, higher is noisier)
                   36190:      * @param string $msg    message to write to the log
                   36191:      *
                   36192:      * @return void
                   36193:      *
                   36194:      * @access public
                   36195:      * @static
                   36196:      */
                   36197:     function log($level, $msg, $append_crlf = true)
                   36198:     {
                   36199:         if ($this->debug >= $level) {
                   36200:             if (!class_exists('PEAR_Frontend')) {
                   36201:                 require_once 'PEAR/Frontend.php';
                   36202:             }
                   36203: 
                   36204:             $ui = &PEAR_Frontend::singleton();
                   36205:             if (is_a($ui, 'PEAR_Frontend')) {
                   36206:                 $ui->log($msg, $append_crlf);
                   36207:             } else {
                   36208:                 print "$msg\n";
                   36209:             }
                   36210:         }
                   36211:     }
                   36212: 
                   36213:     /**
                   36214:      * Create and register a temporary directory.
                   36215:      *
                   36216:      * @param string $tmpdir (optional) Directory to use as tmpdir.
                   36217:      *                       Will use system defaults (for example
                   36218:      *                       /tmp or c:\windows\temp) if not specified
                   36219:      *
                   36220:      * @return string name of created directory
                   36221:      *
                   36222:      * @access public
                   36223:      */
                   36224:     function mkTempDir($tmpdir = '')
                   36225:     {
                   36226:         $topt = $tmpdir ? array('-t', $tmpdir) : array();
                   36227:         $topt = array_merge($topt, array('-d', 'pear'));
                   36228:         if (!class_exists('System')) {
                   36229:             require_once 'System.php';
                   36230:         }
                   36231: 
                   36232:         if (!$tmpdir = System::mktemp($topt)) {
                   36233:             return false;
                   36234:         }
                   36235: 
                   36236:         $this->addTempFile($tmpdir);
                   36237:         return $tmpdir;
                   36238:     }
                   36239: 
                   36240:     /**
                   36241:      * Set object that represents the frontend to be used.
                   36242:      *
                   36243:      * @param  object Reference of the frontend object
                   36244:      * @return void
                   36245:      * @access public
                   36246:      */
                   36247:     function setFrontendObject(&$ui)
                   36248:     {
                   36249:         $this->ui = &$ui;
                   36250:     }
                   36251: 
                   36252:     /**
                   36253:      * Return an array containing all of the states that are more stable than
                   36254:      * or equal to the passed in state
                   36255:      *
                   36256:      * @param string Release state
                   36257:      * @param boolean Determines whether to include $state in the list
                   36258:      * @return false|array False if $state is not a valid release state
                   36259:      */
                   36260:     function betterStates($state, $include = false)
                   36261:     {
                   36262:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   36263:         $i = array_search($state, $states);
                   36264:         if ($i === false) {
                   36265:             return false;
                   36266:         }
                   36267:         if ($include) {
                   36268:             $i--;
                   36269:         }
                   36270:         return array_slice($states, $i + 1);
                   36271:     }
                   36272: 
                   36273:     /**
                   36274:      * Get the valid roles for a PEAR package maintainer
                   36275:      *
                   36276:      * @return array
                   36277:      * @static
                   36278:      */
                   36279:     function getUserRoles()
                   36280:     {
                   36281:         return $GLOBALS['_PEAR_Common_maintainer_roles'];
                   36282:     }
                   36283: 
                   36284:     /**
                   36285:      * Get the valid package release states of packages
                   36286:      *
                   36287:      * @return array
                   36288:      * @static
                   36289:      */
                   36290:     function getReleaseStates()
                   36291:     {
                   36292:         return $GLOBALS['_PEAR_Common_release_states'];
                   36293:     }
                   36294: 
                   36295:     /**
                   36296:      * Get the implemented dependency types (php, ext, pkg etc.)
                   36297:      *
                   36298:      * @return array
                   36299:      * @static
                   36300:      */
                   36301:     function getDependencyTypes()
                   36302:     {
                   36303:         return $GLOBALS['_PEAR_Common_dependency_types'];
                   36304:     }
                   36305: 
                   36306:     /**
                   36307:      * Get the implemented dependency relations (has, lt, ge etc.)
                   36308:      *
                   36309:      * @return array
                   36310:      * @static
                   36311:      */
                   36312:     function getDependencyRelations()
                   36313:     {
                   36314:         return $GLOBALS['_PEAR_Common_dependency_relations'];
                   36315:     }
                   36316: 
                   36317:     /**
                   36318:      * Get the implemented file roles
                   36319:      *
                   36320:      * @return array
                   36321:      * @static
                   36322:      */
                   36323:     function getFileRoles()
                   36324:     {
                   36325:         return $GLOBALS['_PEAR_Common_file_roles'];
                   36326:     }
                   36327: 
                   36328:     /**
                   36329:      * Get the implemented file replacement types in
                   36330:      *
                   36331:      * @return array
                   36332:      * @static
                   36333:      */
                   36334:     function getReplacementTypes()
                   36335:     {
                   36336:         return $GLOBALS['_PEAR_Common_replacement_types'];
                   36337:     }
                   36338: 
                   36339:     /**
                   36340:      * Get the implemented file replacement types in
                   36341:      *
                   36342:      * @return array
                   36343:      * @static
                   36344:      */
                   36345:     function getProvideTypes()
                   36346:     {
                   36347:         return $GLOBALS['_PEAR_Common_provide_types'];
                   36348:     }
                   36349: 
                   36350:     /**
                   36351:      * Get the implemented file replacement types in
                   36352:      *
                   36353:      * @return array
                   36354:      * @static
                   36355:      */
                   36356:     function getScriptPhases()
                   36357:     {
                   36358:         return $GLOBALS['_PEAR_Common_script_phases'];
                   36359:     }
                   36360: 
                   36361:     /**
                   36362:      * Test whether a string contains a valid package name.
                   36363:      *
                   36364:      * @param string $name the package name to test
                   36365:      *
                   36366:      * @return bool
                   36367:      *
                   36368:      * @access public
                   36369:      */
                   36370:     function validPackageName($name)
                   36371:     {
                   36372:         return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
                   36373:     }
                   36374: 
                   36375:     /**
                   36376:      * Test whether a string contains a valid package version.
                   36377:      *
                   36378:      * @param string $ver the package version to test
                   36379:      *
                   36380:      * @return bool
                   36381:      *
                   36382:      * @access public
                   36383:      */
                   36384:     function validPackageVersion($ver)
                   36385:     {
                   36386:         return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   36387:     }
                   36388: 
                   36389:     /**
                   36390:      * @param string $path relative or absolute include path
                   36391:      * @return boolean
                   36392:      * @static
                   36393:      */
                   36394:     function isIncludeable($path)
                   36395:     {
                   36396:         if (file_exists($path) && is_readable($path)) {
                   36397:             return true;
                   36398:         }
                   36399: 
                   36400:         $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
                   36401:         foreach ($ipath as $include) {
                   36402:             $test = realpath($include . DIRECTORY_SEPARATOR . $path);
                   36403:             if (file_exists($test) && is_readable($test)) {
                   36404:                 return true;
                   36405:             }
                   36406:         }
                   36407: 
                   36408:         return false;
                   36409:     }
                   36410: 
                   36411:     function _postProcessChecks($pf)
                   36412:     {
                   36413:         if (!PEAR::isError($pf)) {
                   36414:             return $this->_postProcessValidPackagexml($pf);
                   36415:         }
                   36416: 
                   36417:         $errs = $pf->getUserinfo();
                   36418:         if (is_array($errs)) {
                   36419:             foreach ($errs as $error) {
                   36420:                 $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   36421:             }
                   36422:         }
                   36423: 
                   36424:         return $pf;
                   36425:     }
                   36426: 
                   36427:     /**
                   36428:      * Returns information about a package file.  Expects the name of
                   36429:      * a gzipped tar file as input.
                   36430:      *
                   36431:      * @param string  $file  name of .tgz file
                   36432:      *
                   36433:      * @return array  array with package information
                   36434:      *
                   36435:      * @access public
                   36436:      * @deprecated use PEAR_PackageFile->fromTgzFile() instead
                   36437:      *
                   36438:      */
                   36439:     function infoFromTgzFile($file)
                   36440:     {
                   36441:         $packagefile = &new PEAR_PackageFile($this->config);
                   36442:         $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
                   36443:         return $this->_postProcessChecks($pf);
                   36444:     }
                   36445: 
                   36446:     /**
                   36447:      * Returns information about a package file.  Expects the name of
                   36448:      * a package xml file as input.
                   36449:      *
                   36450:      * @param string  $descfile  name of package xml file
                   36451:      *
                   36452:      * @return array  array with package information
                   36453:      *
                   36454:      * @access public
                   36455:      * @deprecated use PEAR_PackageFile->fromPackageFile() instead
                   36456:      *
                   36457:      */
                   36458:     function infoFromDescriptionFile($descfile)
                   36459:     {
                   36460:         $packagefile = &new PEAR_PackageFile($this->config);
                   36461:         $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   36462:         return $this->_postProcessChecks($pf);
                   36463:     }
                   36464: 
                   36465:     /**
                   36466:      * Returns information about a package file.  Expects the contents
                   36467:      * of a package xml file as input.
                   36468:      *
                   36469:      * @param string  $data  contents of package.xml file
                   36470:      *
                   36471:      * @return array   array with package information
                   36472:      *
                   36473:      * @access public
                   36474:      * @deprecated use PEAR_PackageFile->fromXmlstring() instead
                   36475:      *
                   36476:      */
                   36477:     function infoFromString($data)
                   36478:     {
                   36479:         $packagefile = &new PEAR_PackageFile($this->config);
                   36480:         $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
                   36481:         return $this->_postProcessChecks($pf);
                   36482:     }
                   36483: 
                   36484:     /**
                   36485:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   36486:      * @return array
                   36487:      */
                   36488:     function _postProcessValidPackagexml(&$pf)
                   36489:     {
                   36490:         if (!is_a($pf, 'PEAR_PackageFile_v2')) {
                   36491:             $this->pkginfo = $pf->toArray();
                   36492:             return $this->pkginfo;
                   36493:         }
                   36494: 
                   36495:         // sort of make this into a package.xml 1.0-style array
                   36496:         // changelog is not converted to old format.
                   36497:         $arr = $pf->toArray(true);
                   36498:         $arr = array_merge($arr, $arr['old']);
                   36499:         unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
                   36500:               $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
                   36501:               $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
                   36502:               $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
                   36503:               $arr['helper'], $arr['contributor']);
                   36504:         $arr['filelist'] = $pf->getFilelist();
                   36505:         $this->pkginfo = $arr;
                   36506:         return $arr;
                   36507:     }
                   36508: 
                   36509:     /**
                   36510:      * Returns package information from different sources
                   36511:      *
                   36512:      * This method is able to extract information about a package
                   36513:      * from a .tgz archive or from a XML package definition file.
                   36514:      *
                   36515:      * @access public
                   36516:      * @param  string Filename of the source ('package.xml', '<package>.tgz')
                   36517:      * @return string
                   36518:      * @deprecated use PEAR_PackageFile->fromAnyFile() instead
                   36519:      */
                   36520:     function infoFromAny($info)
                   36521:     {
                   36522:         if (is_string($info) && file_exists($info)) {
                   36523:             $packagefile = &new PEAR_PackageFile($this->config);
                   36524:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   36525:             if (PEAR::isError($pf)) {
                   36526:                 $errs = $pf->getUserinfo();
                   36527:                 if (is_array($errs)) {
                   36528:                     foreach ($errs as $error) {
                   36529:                         $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   36530:                     }
                   36531:                 }
                   36532: 
                   36533:                 return $pf;
                   36534:             }
                   36535: 
                   36536:             return $this->_postProcessValidPackagexml($pf);
                   36537:         }
                   36538: 
                   36539:         return $info;
                   36540:     }
                   36541: 
                   36542:     /**
                   36543:      * Return an XML document based on the package info (as returned
                   36544:      * by the PEAR_Common::infoFrom* methods).
                   36545:      *
                   36546:      * @param array  $pkginfo  package info
                   36547:      *
                   36548:      * @return string XML data
                   36549:      *
                   36550:      * @access public
                   36551:      * @deprecated use a PEAR_PackageFile_v* object's generator instead
                   36552:      */
                   36553:     function xmlFromInfo($pkginfo)
                   36554:     {
                   36555:         $config      = &PEAR_Config::singleton();
                   36556:         $packagefile = &new PEAR_PackageFile($config);
                   36557:         $pf = &$packagefile->fromArray($pkginfo);
                   36558:         $gen = &$pf->getDefaultGenerator();
                   36559:         return $gen->toXml(PEAR_VALIDATE_PACKAGING);
                   36560:     }
                   36561: 
                   36562:     /**
                   36563:      * Validate XML package definition file.
                   36564:      *
                   36565:      * @param  string $info Filename of the package archive or of the
                   36566:      *                package definition file
                   36567:      * @param  array $errors Array that will contain the errors
                   36568:      * @param  array $warnings Array that will contain the warnings
                   36569:      * @param  string $dir_prefix (optional) directory where source files
                   36570:      *                may be found, or empty if they are not available
                   36571:      * @access public
                   36572:      * @return boolean
                   36573:      * @deprecated use the validation of PEAR_PackageFile objects
                   36574:      */
                   36575:     function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
                   36576:     {
                   36577:         $config      = &PEAR_Config::singleton();
                   36578:         $packagefile = &new PEAR_PackageFile($config);
                   36579:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   36580:         if (strpos($info, '<?xml') !== false) {
                   36581:             $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
                   36582:         } else {
                   36583:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   36584:         }
                   36585: 
                   36586:         PEAR::staticPopErrorHandling();
                   36587:         if (PEAR::isError($pf)) {
                   36588:             $errs = $pf->getUserinfo();
                   36589:             if (is_array($errs)) {
                   36590:                 foreach ($errs as $error) {
                   36591:                     if ($error['level'] == 'error') {
                   36592:                         $errors[] = $error['message'];
                   36593:                     } else {
                   36594:                         $warnings[] = $error['message'];
                   36595:                     }
                   36596:                 }
                   36597:             }
                   36598: 
                   36599:             return false;
                   36600:         }
                   36601: 
                   36602:         return true;
                   36603:     }
                   36604: 
                   36605:     /**
                   36606:      * Build a "provides" array from data returned by
                   36607:      * analyzeSourceCode().  The format of the built array is like
                   36608:      * this:
                   36609:      *
                   36610:      *  array(
                   36611:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   36612:      *    ...
                   36613:      *  )
                   36614:      *
                   36615:      *
                   36616:      * @param array $srcinfo array with information about a source file
                   36617:      * as returned by the analyzeSourceCode() method.
                   36618:      *
                   36619:      * @return void
                   36620:      *
                   36621:      * @access public
                   36622:      *
                   36623:      */
                   36624:     function buildProvidesArray($srcinfo)
                   36625:     {
                   36626:         $file = basename($srcinfo['source_file']);
                   36627:         $pn = '';
                   36628:         if (isset($this->_packageName)) {
                   36629:             $pn = $this->_packageName;
                   36630:         }
                   36631: 
                   36632:         $pnl = strlen($pn);
                   36633:         foreach ($srcinfo['declared_classes'] as $class) {
                   36634:             $key = "class;$class";
                   36635:             if (isset($this->pkginfo['provides'][$key])) {
                   36636:                 continue;
                   36637:             }
                   36638: 
                   36639:             $this->pkginfo['provides'][$key] =
                   36640:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   36641:             if (isset($srcinfo['inheritance'][$class])) {
                   36642:                 $this->pkginfo['provides'][$key]['extends'] =
                   36643:                     $srcinfo['inheritance'][$class];
                   36644:             }
                   36645:         }
                   36646: 
                   36647:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   36648:             foreach ($methods as $method) {
                   36649:                 $function = "$class::$method";
                   36650:                 $key = "function;$function";
                   36651:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   36652:                     isset($this->pkginfo['provides'][$key])) {
                   36653:                     continue;
                   36654:                 }
                   36655: 
                   36656:                 $this->pkginfo['provides'][$key] =
                   36657:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   36658:             }
                   36659:         }
                   36660: 
                   36661:         foreach ($srcinfo['declared_functions'] as $function) {
                   36662:             $key = "function;$function";
                   36663:             if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
                   36664:                 continue;
                   36665:             }
                   36666: 
                   36667:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   36668:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   36669:             }
                   36670: 
                   36671:             $this->pkginfo['provides'][$key] =
                   36672:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   36673:         }
                   36674:     }
                   36675: 
                   36676:     /**
                   36677:      * Analyze the source code of the given PHP file
                   36678:      *
                   36679:      * @param  string Filename of the PHP file
                   36680:      * @return mixed
                   36681:      * @access public
                   36682:      */
                   36683:     function analyzeSourceCode($file)
                   36684:     {
                   36685:         if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   36686:             require_once 'PEAR/PackageFile/v2/Validator.php';
                   36687:         }
                   36688: 
                   36689:         $a = new PEAR_PackageFile_v2_Validator;
                   36690:         return $a->analyzeSourceCode($file);
                   36691:     }
                   36692: 
                   36693:     function detectDependencies($any, $status_callback = null)
                   36694:     {
                   36695:         if (!function_exists("token_get_all")) {
                   36696:             return false;
                   36697:         }
                   36698: 
                   36699:         if (PEAR::isError($info = $this->infoFromAny($any))) {
                   36700:             return $this->raiseError($info);
                   36701:         }
                   36702: 
                   36703:         if (!is_array($info)) {
                   36704:             return false;
                   36705:         }
                   36706: 
                   36707:         $deps = array();
                   36708:         $used_c = $decl_c = $decl_f = $decl_m = array();
                   36709:         foreach ($info['filelist'] as $file => $fa) {
                   36710:             $tmp = $this->analyzeSourceCode($file);
                   36711:             $used_c = @array_merge($used_c, $tmp['used_classes']);
                   36712:             $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
                   36713:             $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
                   36714:             $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
                   36715:             $inheri = @array_merge($inheri, $tmp['inheritance']);
                   36716:         }
                   36717: 
                   36718:         $used_c = array_unique($used_c);
                   36719:         $decl_c = array_unique($decl_c);
                   36720:         $undecl_c = array_diff($used_c, $decl_c);
                   36721: 
                   36722:         return array('used_classes' => $used_c,
                   36723:                      'declared_classes' => $decl_c,
                   36724:                      'declared_methods' => $decl_m,
                   36725:                      'declared_functions' => $decl_f,
                   36726:                      'undeclared_classes' => $undecl_c,
                   36727:                      'inheritance' => $inheri,
                   36728:                      );
                   36729:     }
                   36730: 
                   36731:     /**
                   36732:      * Download a file through HTTP.  Considers suggested file name in
                   36733:      * Content-disposition: header and can run a callback function for
                   36734:      * different events.  The callback will be called with two
                   36735:      * parameters: the callback type, and parameters.  The implemented
                   36736:      * callback types are:
                   36737:      *
                   36738:      *  'setup'       called at the very beginning, parameter is a UI object
                   36739:      *                that should be used for all output
                   36740:      *  'message'     the parameter is a string with an informational message
                   36741:      *  'saveas'      may be used to save with a different file name, the
                   36742:      *                parameter is the filename that is about to be used.
                   36743:      *                If a 'saveas' callback returns a non-empty string,
                   36744:      *                that file name will be used as the filename instead.
                   36745:      *                Note that $save_dir will not be affected by this, only
                   36746:      *                the basename of the file.
                   36747:      *  'start'       download is starting, parameter is number of bytes
                   36748:      *                that are expected, or -1 if unknown
                   36749:      *  'bytesread'   parameter is the number of bytes read so far
                   36750:      *  'done'        download is complete, parameter is the total number
                   36751:      *                of bytes read
                   36752:      *  'connfailed'  if the TCP connection fails, this callback is called
                   36753:      *                with array(host,port,errno,errmsg)
                   36754:      *  'writefailed' if writing to disk fails, this callback is called
                   36755:      *                with array(destfile,errmsg)
                   36756:      *
                   36757:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   36758:      * setting), the proxy will be used.
                   36759:      *
                   36760:      * @param string  $url       the URL to download
                   36761:      * @param object  $ui        PEAR_Frontend_* instance
                   36762:      * @param object  $config    PEAR_Config instance
                   36763:      * @param string  $save_dir  (optional) directory to save file in
                   36764:      * @param mixed   $callback  (optional) function/method to call for status
                   36765:      *                           updates
                   36766:      *
                   36767:      * @return string  Returns the full path of the downloaded file or a PEAR
                   36768:      *                 error on failure.  If the error is caused by
                   36769:      *                 socket-related errors, the error object will
                   36770:      *                 have the fsockopen error code available through
                   36771:      *                 getCode().
                   36772:      *
                   36773:      * @access public
                   36774:      * @deprecated in favor of PEAR_Downloader::downloadHttp()
                   36775:      */
                   36776:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
                   36777:     {
                   36778:         if (!class_exists('PEAR_Downloader')) {
                   36779:             require_once 'PEAR/Downloader.php';
                   36780:         }
                   36781:         return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
                   36782:     }
                   36783: }
                   36784: 
                   36785: require_once 'PEAR/Config.php';
                   36786: require_once 'PEAR/PackageFile.php';PEAR-1.9.4/PEAR/Config.php0000644000076500000240000020445211605156760013712 0ustar  helgistaff<?php
                   36787: /**
                   36788:  * PEAR_Config, customized configuration handling for the PEAR Installer
                   36789:  *
                   36790:  * PHP versions 4 and 5
                   36791:  *
                   36792:  * @category   pear
                   36793:  * @package    PEAR
                   36794:  * @author     Stig Bakken <ssb@php.net>
                   36795:  * @author     Greg Beaver <cellog@php.net>
                   36796:  * @copyright  1997-2009 The Authors
                   36797:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   36798:  * @version    CVS: $Id: Config.php 313023 2011-07-06 19:17:11Z dufuz $
                   36799:  * @link       http://pear.php.net/package/PEAR
                   36800:  * @since      File available since Release 0.1
                   36801:  */
                   36802: 
                   36803: /**
                   36804:  * Required for error handling
                   36805:  */
                   36806: require_once 'PEAR.php';
                   36807: require_once 'PEAR/Registry.php';
                   36808: require_once 'PEAR/Installer/Role.php';
                   36809: require_once 'System.php';
                   36810: 
                   36811: /**
                   36812:  * Last created PEAR_Config instance.
                   36813:  * @var object
                   36814:  */
                   36815: $GLOBALS['_PEAR_Config_instance'] = null;
                   36816: if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
                   36817:     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
                   36818: } else {
                   36819:     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
                   36820: }
                   36821: 
                   36822: // Below we define constants with default values for all configuration
                   36823: // parameters except username/password.  All of them can have their
                   36824: // defaults set through environment variables.  The reason we use the
                   36825: // PHP_ prefix is for some security, PHP protects environment
                   36826: // variables starting with PHP_*.
                   36827: 
                   36828: // default channel and preferred mirror is based on whether we are invoked through
                   36829: // the "pear" or the "pecl" command
                   36830: if (!defined('PEAR_RUNTYPE')) {
                   36831:     define('PEAR_RUNTYPE', 'pear');
                   36832: }
                   36833: 
                   36834: if (PEAR_RUNTYPE == 'pear') {
                   36835:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
                   36836: } else {
                   36837:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
                   36838: }
                   36839: 
                   36840: if (getenv('PHP_PEAR_SYSCONF_DIR')) {
                   36841:     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
                   36842: } elseif (getenv('SystemRoot')) {
                   36843:     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
                   36844: } else {
                   36845:     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
                   36846: }
                   36847: 
                   36848: // Default for master_server
                   36849: if (getenv('PHP_PEAR_MASTER_SERVER')) {
                   36850:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
                   36851: } else {
                   36852:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
                   36853: }
                   36854: 
                   36855: // Default for http_proxy
                   36856: if (getenv('PHP_PEAR_HTTP_PROXY')) {
                   36857:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
                   36858: } elseif (getenv('http_proxy')) {
                   36859:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
                   36860: } else {
                   36861:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
                   36862: }
                   36863: 
                   36864: // Default for php_dir
                   36865: if (getenv('PHP_PEAR_INSTALL_DIR')) {
                   36866:     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
                   36867: } else {
                   36868:     if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
                   36869:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   36870:     } else {
                   36871:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   36872:     }
                   36873: }
                   36874: 
                   36875: // Default for ext_dir
                   36876: if (getenv('PHP_PEAR_EXTENSION_DIR')) {
                   36877:     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
                   36878: } else {
                   36879:     if (ini_get('extension_dir')) {
                   36880:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
                   36881:     } elseif (defined('PEAR_EXTENSION_DIR') &&
                   36882:               file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
                   36883:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
                   36884:     } elseif (defined('PHP_EXTENSION_DIR')) {
                   36885:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
                   36886:     } else {
                   36887:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
                   36888:     }
                   36889: }
                   36890: 
                   36891: // Default for doc_dir
                   36892: if (getenv('PHP_PEAR_DOC_DIR')) {
                   36893:     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
                   36894: } else {
                   36895:     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
                   36896:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
                   36897: }
                   36898: 
                   36899: // Default for bin_dir
                   36900: if (getenv('PHP_PEAR_BIN_DIR')) {
                   36901:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
                   36902: } else {
                   36903:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
                   36904: }
                   36905: 
                   36906: // Default for data_dir
                   36907: if (getenv('PHP_PEAR_DATA_DIR')) {
                   36908:     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
                   36909: } else {
                   36910:     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
                   36911:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
                   36912: }
                   36913: 
                   36914: // Default for cfg_dir
                   36915: if (getenv('PHP_PEAR_CFG_DIR')) {
                   36916:     define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
                   36917: } else {
                   36918:     define('PEAR_CONFIG_DEFAULT_CFG_DIR',
                   36919:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
                   36920: }
                   36921: 
                   36922: // Default for www_dir
                   36923: if (getenv('PHP_PEAR_WWW_DIR')) {
                   36924:     define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
                   36925: } else {
                   36926:     define('PEAR_CONFIG_DEFAULT_WWW_DIR',
                   36927:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
                   36928: }
                   36929: 
                   36930: // Default for test_dir
                   36931: if (getenv('PHP_PEAR_TEST_DIR')) {
                   36932:     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
                   36933: } else {
                   36934:     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
                   36935:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
                   36936: }
                   36937: 
                   36938: // Default for temp_dir
                   36939: if (getenv('PHP_PEAR_TEMP_DIR')) {
                   36940:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
                   36941: } else {
                   36942:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
                   36943:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   36944:            DIRECTORY_SEPARATOR . 'temp');
                   36945: }
                   36946: 
                   36947: // Default for cache_dir
                   36948: if (getenv('PHP_PEAR_CACHE_DIR')) {
                   36949:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
                   36950: } else {
                   36951:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
                   36952:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   36953:            DIRECTORY_SEPARATOR . 'cache');
                   36954: }
                   36955: 
                   36956: // Default for download_dir
                   36957: if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
                   36958:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
                   36959: } else {
                   36960:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
                   36961:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   36962:            DIRECTORY_SEPARATOR . 'download');
                   36963: }
                   36964: 
                   36965: // Default for php_bin
                   36966: if (getenv('PHP_PEAR_PHP_BIN')) {
                   36967:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
                   36968: } else {
                   36969:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
                   36970:            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
                   36971: }
                   36972: 
                   36973: // Default for verbose
                   36974: if (getenv('PHP_PEAR_VERBOSE')) {
                   36975:     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
                   36976: } else {
                   36977:     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
                   36978: }
                   36979: 
                   36980: // Default for preferred_state
                   36981: if (getenv('PHP_PEAR_PREFERRED_STATE')) {
                   36982:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
                   36983: } else {
                   36984:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
                   36985: }
                   36986: 
                   36987: // Default for umask
                   36988: if (getenv('PHP_PEAR_UMASK')) {
                   36989:     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
                   36990: } else {
                   36991:     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
                   36992: }
                   36993: 
                   36994: // Default for cache_ttl
                   36995: if (getenv('PHP_PEAR_CACHE_TTL')) {
                   36996:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
                   36997: } else {
                   36998:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
                   36999: }
                   37000: 
                   37001: // Default for sig_type
                   37002: if (getenv('PHP_PEAR_SIG_TYPE')) {
                   37003:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
                   37004: } else {
                   37005:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
                   37006: }
                   37007: 
                   37008: // Default for sig_bin
                   37009: if (getenv('PHP_PEAR_SIG_BIN')) {
                   37010:     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
                   37011: } else {
                   37012:     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
                   37013:            System::which(
                   37014:                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
                   37015: }
                   37016: 
                   37017: // Default for sig_keydir
                   37018: if (getenv('PHP_PEAR_SIG_KEYDIR')) {
                   37019:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
                   37020: } else {
                   37021:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
                   37022:            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
                   37023: }
                   37024: 
                   37025: /**
                   37026:  * This is a class for storing configuration data, keeping track of
                   37027:  * which are system-defined, user-defined or defaulted.
                   37028:  * @category   pear
                   37029:  * @package    PEAR
                   37030:  * @author     Stig Bakken <ssb@php.net>
                   37031:  * @author     Greg Beaver <cellog@php.net>
                   37032:  * @copyright  1997-2009 The Authors
                   37033:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   37034:  * @version    Release: 1.9.4
                   37035:  * @link       http://pear.php.net/package/PEAR
                   37036:  * @since      Class available since Release 0.1
                   37037:  */
                   37038: class PEAR_Config extends PEAR
                   37039: {
                   37040:     /**
                   37041:      * Array of config files used.
                   37042:      *
                   37043:      * @var array layer => config file
                   37044:      */
                   37045:     var $files = array(
                   37046:         'system' => '',
                   37047:         'user' => '',
                   37048:         );
                   37049: 
                   37050:     var $layers = array();
                   37051: 
                   37052:     /**
                   37053:      * Configuration data, two-dimensional array where the first
                   37054:      * dimension is the config layer ('user', 'system' and 'default'),
                   37055:      * and the second dimension is keyname => value.
                   37056:      *
                   37057:      * The order in the first dimension is important!  Earlier
                   37058:      * layers will shadow later ones when a config value is
                   37059:      * requested (if a 'user' value exists, it will be returned first,
                   37060:      * then 'system' and finally 'default').
                   37061:      *
                   37062:      * @var array layer => array(keyname => value, ...)
                   37063:      */
                   37064:     var $configuration = array(
                   37065:         'user' => array(),
                   37066:         'system' => array(),
                   37067:         'default' => array(),
                   37068:         );
                   37069: 
                   37070:     /**
                   37071:      * Configuration values that can be set for a channel
                   37072:      *
                   37073:      * All other configuration values can only have a global value
                   37074:      * @var array
                   37075:      * @access private
                   37076:      */
                   37077:     var $_channelConfigInfo = array(
                   37078:         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
                   37079:         'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
                   37080:         'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
                   37081:         );
                   37082: 
                   37083:     /**
                   37084:      * Channels that can be accessed
                   37085:      * @see setChannels()
                   37086:      * @var array
                   37087:      * @access private
                   37088:      */
                   37089:     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
                   37090: 
                   37091:     /**
                   37092:      * This variable is used to control the directory values returned
                   37093:      * @see setInstallRoot();
                   37094:      * @var string|false
                   37095:      * @access private
                   37096:      */
                   37097:     var $_installRoot = false;
                   37098: 
                   37099:     /**
                   37100:      * If requested, this will always refer to the registry
                   37101:      * contained in php_dir
                   37102:      * @var PEAR_Registry
                   37103:      */
                   37104:     var $_registry = array();
                   37105: 
                   37106:     /**
                   37107:      * @var array
                   37108:      * @access private
                   37109:      */
                   37110:     var $_regInitialized = array();
                   37111: 
                   37112:     /**
                   37113:      * @var bool
                   37114:      * @access private
                   37115:      */
                   37116:     var $_noRegistry = false;
                   37117: 
                   37118:     /**
                   37119:      * amount of errors found while parsing config
                   37120:      * @var integer
                   37121:      * @access private
                   37122:      */
                   37123:     var $_errorsFound = 0;
                   37124:     var $_lastError = null;
                   37125: 
                   37126:     /**
                   37127:      * Information about the configuration data.  Stores the type,
                   37128:      * default value and a documentation string for each configuration
                   37129:      * value.
                   37130:      *
                   37131:      * @var array layer => array(infotype => value, ...)
                   37132:      */
                   37133:     var $configuration_info = array(
                   37134:         // Channels/Internet Access
                   37135:         'default_channel' => array(
                   37136:             'type' => 'string',
                   37137:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   37138:             'doc' => 'the default channel to use for all non explicit commands',
                   37139:             'prompt' => 'Default Channel',
                   37140:             'group' => 'Internet Access',
                   37141:             ),
                   37142:         'preferred_mirror' => array(
                   37143:             'type' => 'string',
                   37144:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   37145:             'doc' => 'the default server or mirror to use for channel actions',
                   37146:             'prompt' => 'Default Channel Mirror',
                   37147:             'group' => 'Internet Access',
                   37148:             ),
                   37149:         'remote_config' => array(
                   37150:             'type' => 'password',
                   37151:             'default' => '',
                   37152:             'doc' => 'ftp url of remote configuration file to use for synchronized install',
                   37153:             'prompt' => 'Remote Configuration File',
                   37154:             'group' => 'Internet Access',
                   37155:             ),
                   37156:         'auto_discover' => array(
                   37157:             'type' => 'integer',
                   37158:             'default' => 0,
                   37159:             'doc' => 'whether to automatically discover new channels',
                   37160:             'prompt' => 'Auto-discover new Channels',
                   37161:             'group' => 'Internet Access',
                   37162:             ),
                   37163:         // Internet Access
                   37164:         'master_server' => array(
                   37165:             'type' => 'string',
                   37166:             'default' => 'pear.php.net',
                   37167:             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
                   37168:             'prompt' => 'PEAR server [DEPRECATED]',
                   37169:             'group' => 'Internet Access',
                   37170:             ),
                   37171:         'http_proxy' => array(
                   37172:             'type' => 'string',
                   37173:             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
                   37174:             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
                   37175:             'prompt' => 'HTTP Proxy Server Address',
                   37176:             'group' => 'Internet Access',
                   37177:             ),
                   37178:         // File Locations
                   37179:         'php_dir' => array(
                   37180:             'type' => 'directory',
                   37181:             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
                   37182:             'doc' => 'directory where .php files are installed',
                   37183:             'prompt' => 'PEAR directory',
                   37184:             'group' => 'File Locations',
                   37185:             ),
                   37186:         'ext_dir' => array(
                   37187:             'type' => 'directory',
                   37188:             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
                   37189:             'doc' => 'directory where loadable extensions are installed',
                   37190:             'prompt' => 'PHP extension directory',
                   37191:             'group' => 'File Locations',
                   37192:             ),
                   37193:         'doc_dir' => array(
                   37194:             'type' => 'directory',
                   37195:             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
                   37196:             'doc' => 'directory where documentation is installed',
                   37197:             'prompt' => 'PEAR documentation directory',
                   37198:             'group' => 'File Locations',
                   37199:             ),
                   37200:         'bin_dir' => array(
                   37201:             'type' => 'directory',
                   37202:             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
                   37203:             'doc' => 'directory where executables are installed',
                   37204:             'prompt' => 'PEAR executables directory',
                   37205:             'group' => 'File Locations',
                   37206:             ),
                   37207:         'data_dir' => array(
                   37208:             'type' => 'directory',
                   37209:             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
                   37210:             'doc' => 'directory where data files are installed',
                   37211:             'prompt' => 'PEAR data directory',
                   37212:             'group' => 'File Locations (Advanced)',
                   37213:             ),
                   37214:         'cfg_dir' => array(
                   37215:             'type' => 'directory',
                   37216:             'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
                   37217:             'doc' => 'directory where modifiable configuration files are installed',
                   37218:             'prompt' => 'PEAR configuration file directory',
                   37219:             'group' => 'File Locations (Advanced)',
                   37220:             ),
                   37221:         'www_dir' => array(
                   37222:             'type' => 'directory',
                   37223:             'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
                   37224:             'doc' => 'directory where www frontend files (html/js) are installed',
                   37225:             'prompt' => 'PEAR www files directory',
                   37226:             'group' => 'File Locations (Advanced)',
                   37227:             ),
                   37228:         'test_dir' => array(
                   37229:             'type' => 'directory',
                   37230:             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
                   37231:             'doc' => 'directory where regression tests are installed',
                   37232:             'prompt' => 'PEAR test directory',
                   37233:             'group' => 'File Locations (Advanced)',
                   37234:             ),
                   37235:         'cache_dir' => array(
                   37236:             'type' => 'directory',
                   37237:             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
                   37238:             'doc' => 'directory which is used for web service cache',
                   37239:             'prompt' => 'PEAR Installer cache directory',
                   37240:             'group' => 'File Locations (Advanced)',
                   37241:             ),
                   37242:         'temp_dir' => array(
                   37243:             'type' => 'directory',
                   37244:             'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
                   37245:             'doc' => 'directory which is used for all temp files',
                   37246:             'prompt' => 'PEAR Installer temp directory',
                   37247:             'group' => 'File Locations (Advanced)',
                   37248:             ),
                   37249:         'download_dir' => array(
                   37250:             'type' => 'directory',
                   37251:             'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
                   37252:             'doc' => 'directory which is used for all downloaded files',
                   37253:             'prompt' => 'PEAR Installer download directory',
                   37254:             'group' => 'File Locations (Advanced)',
                   37255:             ),
                   37256:         'php_bin' => array(
                   37257:             'type' => 'file',
                   37258:             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
                   37259:             'doc' => 'PHP CLI/CGI binary for executing scripts',
                   37260:             'prompt' => 'PHP CLI/CGI binary',
                   37261:             'group' => 'File Locations (Advanced)',
                   37262:             ),
                   37263:         'php_prefix' => array(
                   37264:             'type' => 'string',
                   37265:             'default' => '',
                   37266:             'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
                   37267:             'prompt' => '--program-prefix passed to PHP\'s ./configure',
                   37268:             'group' => 'File Locations (Advanced)',
                   37269:             ),
                   37270:         'php_suffix' => array(
                   37271:             'type' => 'string',
                   37272:             'default' => '',
                   37273:             'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
                   37274:             'prompt' => '--program-suffix passed to PHP\'s ./configure',
                   37275:             'group' => 'File Locations (Advanced)',
                   37276:             ),
                   37277:         'php_ini' => array(
                   37278:             'type' => 'file',
                   37279:             'default' => '',
                   37280:             'doc' => 'location of php.ini in which to enable PECL extensions on install',
                   37281:             'prompt' => 'php.ini location',
                   37282:             'group' => 'File Locations (Advanced)',
                   37283:             ),
                   37284:         // Maintainers
                   37285:         'username' => array(
                   37286:             'type' => 'string',
                   37287:             'default' => '',
                   37288:             'doc' => '(maintainers) your PEAR account name',
                   37289:             'prompt' => 'PEAR username (for maintainers)',
                   37290:             'group' => 'Maintainers',
                   37291:             ),
                   37292:         'password' => array(
                   37293:             'type' => 'password',
                   37294:             'default' => '',
                   37295:             'doc' => '(maintainers) your PEAR account password',
                   37296:             'prompt' => 'PEAR password (for maintainers)',
                   37297:             'group' => 'Maintainers',
                   37298:             ),
                   37299:         // Advanced
                   37300:         'verbose' => array(
                   37301:             'type' => 'integer',
                   37302:             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
                   37303:             'doc' => 'verbosity level
                   37304: 0: really quiet
                   37305: 1: somewhat quiet
                   37306: 2: verbose
                   37307: 3: debug',
                   37308:             'prompt' => 'Debug Log Level',
                   37309:             'group' => 'Advanced',
                   37310:             ),
                   37311:         'preferred_state' => array(
                   37312:             'type' => 'set',
                   37313:             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
                   37314:             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
                   37315:             'valid_set' => array(
                   37316:                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
                   37317:             'prompt' => 'Preferred Package State',
                   37318:             'group' => 'Advanced',
                   37319:             ),
                   37320:         'umask' => array(
                   37321:             'type' => 'mask',
                   37322:             'default' => PEAR_CONFIG_DEFAULT_UMASK,
                   37323:             'doc' => 'umask used when creating files (Unix-like systems only)',
                   37324:             'prompt' => 'Unix file mask',
                   37325:             'group' => 'Advanced',
                   37326:             ),
                   37327:         'cache_ttl' => array(
                   37328:             'type' => 'integer',
                   37329:             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
                   37330:             'doc' => 'amount of secs where the local cache is used and not updated',
                   37331:             'prompt' => 'Cache TimeToLive',
                   37332:             'group' => 'Advanced',
                   37333:             ),
                   37334:         'sig_type' => array(
                   37335:             'type' => 'set',
                   37336:             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
                   37337:             'doc' => 'which package signature mechanism to use',
                   37338:             'valid_set' => array('gpg'),
                   37339:             'prompt' => 'Package Signature Type',
                   37340:             'group' => 'Maintainers',
                   37341:             ),
                   37342:         'sig_bin' => array(
                   37343:             'type' => 'string',
                   37344:             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
                   37345:             'doc' => 'which package signature mechanism to use',
                   37346:             'prompt' => 'Signature Handling Program',
                   37347:             'group' => 'Maintainers',
                   37348:             ),
                   37349:         'sig_keyid' => array(
                   37350:             'type' => 'string',
                   37351:             'default' => '',
                   37352:             'doc' => 'which key to use for signing with',
                   37353:             'prompt' => 'Signature Key Id',
                   37354:             'group' => 'Maintainers',
                   37355:             ),
                   37356:         'sig_keydir' => array(
                   37357:             'type' => 'directory',
                   37358:             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
                   37359:             'doc' => 'directory where signature keys are located',
                   37360:             'prompt' => 'Signature Key Directory',
                   37361:             'group' => 'Maintainers',
                   37362:             ),
                   37363:         // __channels is reserved - used for channel-specific configuration
                   37364:         );
                   37365: 
                   37366:     /**
                   37367:      * Constructor.
                   37368:      *
                   37369:      * @param string file to read user-defined options from
                   37370:      * @param string file to read system-wide defaults from
                   37371:      * @param bool   determines whether a registry object "follows"
                   37372:      *               the value of php_dir (is automatically created
                   37373:      *               and moved when php_dir is changed)
                   37374:      * @param bool   if true, fails if configuration files cannot be loaded
                   37375:      *
                   37376:      * @access public
                   37377:      *
                   37378:      * @see PEAR_Config::singleton
                   37379:      */
                   37380:     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
                   37381:                          $strict = true)
                   37382:     {
                   37383:         $this->PEAR();
                   37384:         PEAR_Installer_Role::initializeConfig($this);
                   37385:         $sl = DIRECTORY_SEPARATOR;
                   37386:         if (empty($user_file)) {
                   37387:             if (OS_WINDOWS) {
                   37388:                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
                   37389:             } else {
                   37390:                 $user_file = getenv('HOME') . $sl . '.pearrc';
                   37391:             }
                   37392:         }
                   37393: 
                   37394:         if (empty($system_file)) {
                   37395:             $system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
                   37396:             if (OS_WINDOWS) {
                   37397:                 $system_file .= 'pearsys.ini';
                   37398:             } else {
                   37399:                 $system_file .= 'pear.conf';
                   37400:             }
                   37401:         }
                   37402: 
                   37403:         $this->layers = array_keys($this->configuration);
                   37404:         $this->files['user']   = $user_file;
                   37405:         $this->files['system'] = $system_file;
                   37406:         if ($user_file && file_exists($user_file)) {
                   37407:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   37408:             $this->readConfigFile($user_file, 'user', $strict);
                   37409:             $this->popErrorHandling();
                   37410:             if ($this->_errorsFound > 0) {
                   37411:                 return;
                   37412:             }
                   37413:         }
                   37414: 
                   37415:         if ($system_file && @file_exists($system_file)) {
                   37416:             $this->mergeConfigFile($system_file, false, 'system', $strict);
                   37417:             if ($this->_errorsFound > 0) {
                   37418:                 return;
                   37419:             }
                   37420: 
                   37421:         }
                   37422: 
                   37423:         if (!$ftp_file) {
                   37424:             $ftp_file = $this->get('remote_config');
                   37425:         }
                   37426: 
                   37427:         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
                   37428:             $this->readFTPConfigFile($ftp_file);
                   37429:         }
                   37430: 
                   37431:         foreach ($this->configuration_info as $key => $info) {
                   37432:             $this->configuration['default'][$key] = $info['default'];
                   37433:         }
                   37434: 
                   37435:         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
                   37436:         $this->_registry['default']->setConfig($this, false);
                   37437:         $this->_regInitialized['default'] = false;
                   37438:         //$GLOBALS['_PEAR_Config_instance'] = &$this;
                   37439:     }
                   37440: 
                   37441:     /**
                   37442:      * Return the default locations of user and system configuration files
                   37443:      * @static
                   37444:      */
                   37445:     function getDefaultConfigFiles()
                   37446:     {
                   37447:         $sl = DIRECTORY_SEPARATOR;
                   37448:         if (OS_WINDOWS) {
                   37449:             return array(
                   37450:                 'user'   => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
                   37451:                 'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
                   37452:             );
                   37453:         }
                   37454: 
                   37455:         return array(
                   37456:             'user'   => getenv('HOME') . $sl . '.pearrc',
                   37457:             'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
                   37458:         );
                   37459:     }
                   37460: 
                   37461:     /**
                   37462:      * Static singleton method.  If you want to keep only one instance
                   37463:      * of this class in use, this method will give you a reference to
                   37464:      * the last created PEAR_Config object if one exists, or create a
                   37465:      * new object.
                   37466:      *
                   37467:      * @param string (optional) file to read user-defined options from
                   37468:      * @param string (optional) file to read system-wide defaults from
                   37469:      *
                   37470:      * @return object an existing or new PEAR_Config instance
                   37471:      *
                   37472:      * @access public
                   37473:      *
                   37474:      * @see PEAR_Config::PEAR_Config
                   37475:      */
                   37476:     function &singleton($user_file = '', $system_file = '', $strict = true)
                   37477:     {
                   37478:         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
                   37479:             return $GLOBALS['_PEAR_Config_instance'];
                   37480:         }
                   37481: 
                   37482:         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
                   37483:         if ($t_conf->_errorsFound > 0) {
                   37484:              return $t_conf->lastError;
                   37485:         }
                   37486: 
                   37487:         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
                   37488:         return $GLOBALS['_PEAR_Config_instance'];
                   37489:     }
                   37490: 
                   37491:     /**
                   37492:      * Determine whether any configuration files have been detected, and whether a
                   37493:      * registry object can be retrieved from this configuration.
                   37494:      * @return bool
                   37495:      * @since PEAR 1.4.0a1
                   37496:      */
                   37497:     function validConfiguration()
                   37498:     {
                   37499:         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
                   37500:             return true;
                   37501:         }
                   37502: 
                   37503:         return false;
                   37504:     }
                   37505: 
                   37506:     /**
                   37507:      * Reads configuration data from a file.  All existing values in
                   37508:      * the config layer are discarded and replaced with data from the
                   37509:      * file.
                   37510:      * @param string file to read from, if NULL or not specified, the
                   37511:      *               last-used file for the same layer (second param) is used
                   37512:      * @param string config layer to insert data into ('user' or 'system')
                   37513:      * @return bool TRUE on success or a PEAR error on failure
                   37514:      */
                   37515:     function readConfigFile($file = null, $layer = 'user', $strict = true)
                   37516:     {
                   37517:         if (empty($this->files[$layer])) {
                   37518:             return $this->raiseError("unknown config layer `$layer'");
                   37519:         }
                   37520: 
                   37521:         if ($file === null) {
                   37522:             $file = $this->files[$layer];
                   37523:         }
                   37524: 
                   37525:         $data = $this->_readConfigDataFrom($file);
                   37526:         if (PEAR::isError($data)) {
                   37527:             if (!$strict) {
                   37528:                 return true;
                   37529:             }
                   37530: 
                   37531:             $this->_errorsFound++;
                   37532:             $this->lastError = $data;
                   37533: 
                   37534:             return $data;
                   37535:         }
                   37536: 
                   37537:         $this->files[$layer] = $file;
                   37538:         $this->_decodeInput($data);
                   37539:         $this->configuration[$layer] = $data;
                   37540:         $this->_setupChannels();
                   37541:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   37542:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   37543:             $this->_registry[$layer]->setConfig($this, false);
                   37544:             $this->_regInitialized[$layer] = false;
                   37545:         } else {
                   37546:             unset($this->_registry[$layer]);
                   37547:         }
                   37548:         return true;
                   37549:     }
                   37550: 
                   37551:     /**
                   37552:      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
                   37553:      * @return true|PEAR_Error
                   37554:      */
                   37555:     function readFTPConfigFile($path)
                   37556:     {
                   37557:         do { // poor man's try
                   37558:             if (!class_exists('PEAR_FTP')) {
                   37559:                 if (!class_exists('PEAR_Common')) {
                   37560:                     require_once 'PEAR/Common.php';
                   37561:                 }
                   37562:                 if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
                   37563:                     require_once 'PEAR/FTP.php';
                   37564:                 }
                   37565:             }
                   37566: 
                   37567:             if (!class_exists('PEAR_FTP')) {
                   37568:                 return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
                   37569:             }
                   37570: 
                   37571:             $this->_ftp = &new PEAR_FTP;
                   37572:             $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
                   37573:             $e = $this->_ftp->init($path);
                   37574:             if (PEAR::isError($e)) {
                   37575:                 $this->_ftp->popErrorHandling();
                   37576:                 return $e;
                   37577:             }
                   37578: 
                   37579:             $tmp = System::mktemp('-d');
                   37580:             PEAR_Common::addTempFile($tmp);
                   37581:             $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
                   37582:                 'pear.ini', false, FTP_BINARY);
                   37583:             if (PEAR::isError($e)) {
                   37584:                 $this->_ftp->popErrorHandling();
                   37585:                 return $e;
                   37586:             }
                   37587: 
                   37588:             PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
                   37589:             $this->_ftp->disconnect();
                   37590:             $this->_ftp->popErrorHandling();
                   37591:             $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
                   37592:             $e = $this->readConfigFile(null, 'ftp');
                   37593:             if (PEAR::isError($e)) {
                   37594:                 return $e;
                   37595:             }
                   37596: 
                   37597:             $fail = array();
                   37598:             foreach ($this->configuration_info as $key => $val) {
                   37599:                 if (in_array($this->getGroup($key),
                   37600:                       array('File Locations', 'File Locations (Advanced)')) &&
                   37601:                       $this->getType($key) == 'directory') {
                   37602:                     // any directory configs must be set for this to work
                   37603:                     if (!isset($this->configuration['ftp'][$key])) {
                   37604:                         $fail[] = $key;
                   37605:                     }
                   37606:                 }
                   37607:             }
                   37608: 
                   37609:             if (!count($fail)) {
                   37610:                 return true;
                   37611:             }
                   37612: 
                   37613:             $fail = '"' . implode('", "', $fail) . '"';
                   37614:             unset($this->files['ftp']);
                   37615:             unset($this->configuration['ftp']);
                   37616:             return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
                   37617:                 'directory configuration variables.  These variables were not set: ' .
                   37618:                 $fail);
                   37619:         } while (false); // poor man's catch
                   37620:         unset($this->files['ftp']);
                   37621:         return PEAR::raiseError('no remote host specified');
                   37622:     }
                   37623: 
                   37624:     /**
                   37625:      * Reads the existing configurations and creates the _channels array from it
                   37626:      */
                   37627:     function _setupChannels()
                   37628:     {
                   37629:         $set = array_flip(array_values($this->_channels));
                   37630:         foreach ($this->configuration as $layer => $data) {
                   37631:             $i = 1000;
                   37632:             if (isset($data['__channels']) && is_array($data['__channels'])) {
                   37633:                 foreach ($data['__channels'] as $channel => $info) {
                   37634:                     $set[$channel] = $i++;
                   37635:                 }
                   37636:             }
                   37637:         }
                   37638:         $this->_channels = array_values(array_flip($set));
                   37639:         $this->setChannels($this->_channels);
                   37640:     }
                   37641: 
                   37642:     function deleteChannel($channel)
                   37643:     {
                   37644:         $ch = strtolower($channel);
                   37645:         foreach ($this->configuration as $layer => $data) {
                   37646:             if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
                   37647:                 unset($this->configuration[$layer]['__channels'][$ch]);
                   37648:             }
                   37649:         }
                   37650: 
                   37651:         $this->_channels = array_flip($this->_channels);
                   37652:         unset($this->_channels[$ch]);
                   37653:         $this->_channels = array_flip($this->_channels);
                   37654:     }
                   37655: 
                   37656:     /**
                   37657:      * Merges data into a config layer from a file.  Does the same
                   37658:      * thing as readConfigFile, except it does not replace all
                   37659:      * existing values in the config layer.
                   37660:      * @param string file to read from
                   37661:      * @param bool whether to overwrite existing data (default TRUE)
                   37662:      * @param string config layer to insert data into ('user' or 'system')
                   37663:      * @param string if true, errors are returned if file opening fails
                   37664:      * @return bool TRUE on success or a PEAR error on failure
                   37665:      */
                   37666:     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
                   37667:     {
                   37668:         if (empty($this->files[$layer])) {
                   37669:             return $this->raiseError("unknown config layer `$layer'");
                   37670:         }
                   37671: 
                   37672:         if ($file === null) {
                   37673:             $file = $this->files[$layer];
                   37674:         }
                   37675: 
                   37676:         $data = $this->_readConfigDataFrom($file);
                   37677:         if (PEAR::isError($data)) {
                   37678:             if (!$strict) {
                   37679:                 return true;
                   37680:             }
                   37681: 
                   37682:             $this->_errorsFound++;
                   37683:             $this->lastError = $data;
                   37684: 
                   37685:             return $data;
                   37686:         }
                   37687: 
                   37688:         $this->_decodeInput($data);
                   37689:         if ($override) {
                   37690:             $this->configuration[$layer] =
                   37691:                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
                   37692:         } else {
                   37693:             $this->configuration[$layer] =
                   37694:                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
                   37695:         }
                   37696: 
                   37697:         $this->_setupChannels();
                   37698:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   37699:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   37700:             $this->_registry[$layer]->setConfig($this, false);
                   37701:             $this->_regInitialized[$layer] = false;
                   37702:         } else {
                   37703:             unset($this->_registry[$layer]);
                   37704:         }
                   37705:         return true;
                   37706:     }
                   37707: 
                   37708:     /**
                   37709:      * @param array
                   37710:      * @param array
                   37711:      * @return array
                   37712:      * @static
                   37713:      */
                   37714:     function arrayMergeRecursive($arr2, $arr1)
                   37715:     {
                   37716:         $ret = array();
                   37717:         foreach ($arr2 as $key => $data) {
                   37718:             if (!isset($arr1[$key])) {
                   37719:                 $ret[$key] = $data;
                   37720:                 unset($arr1[$key]);
                   37721:                 continue;
                   37722:             }
                   37723:             if (is_array($data)) {
                   37724:                 if (!is_array($arr1[$key])) {
                   37725:                     $ret[$key] = $arr1[$key];
                   37726:                     unset($arr1[$key]);
                   37727:                     continue;
                   37728:                 }
                   37729:                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
                   37730:                 unset($arr1[$key]);
                   37731:             }
                   37732:         }
                   37733: 
                   37734:         return array_merge($ret, $arr1);
                   37735:     }
                   37736: 
                   37737:     /**
                   37738:      * Writes data into a config layer from a file.
                   37739:      *
                   37740:      * @param string|null file to read from, or null for default
                   37741:      * @param string config layer to insert data into ('user' or
                   37742:      *               'system')
                   37743:      * @param string|null data to write to config file or null for internal data [DEPRECATED]
                   37744:      * @return bool TRUE on success or a PEAR error on failure
                   37745:      */
                   37746:     function writeConfigFile($file = null, $layer = 'user', $data = null)
                   37747:     {
                   37748:         $this->_lazyChannelSetup($layer);
                   37749:         if ($layer == 'both' || $layer == 'all') {
                   37750:             foreach ($this->files as $type => $file) {
                   37751:                 $err = $this->writeConfigFile($file, $type, $data);
                   37752:                 if (PEAR::isError($err)) {
                   37753:                     return $err;
                   37754:                 }
                   37755:             }
                   37756:             return true;
                   37757:         }
                   37758: 
                   37759:         if (empty($this->files[$layer])) {
                   37760:             return $this->raiseError("unknown config file type `$layer'");
                   37761:         }
                   37762: 
                   37763:         if ($file === null) {
                   37764:             $file = $this->files[$layer];
                   37765:         }
                   37766: 
                   37767:         $data = ($data === null) ? $this->configuration[$layer] : $data;
                   37768:         $this->_encodeOutput($data);
                   37769:         $opt = array('-p', dirname($file));
                   37770:         if (!@System::mkDir($opt)) {
                   37771:             return $this->raiseError("could not create directory: " . dirname($file));
                   37772:         }
                   37773: 
                   37774:         if (file_exists($file) && is_file($file) && !is_writeable($file)) {
                   37775:             return $this->raiseError("no write access to $file!");
                   37776:         }
                   37777: 
                   37778:         $fp = @fopen($file, "w");
                   37779:         if (!$fp) {
                   37780:             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
                   37781:         }
                   37782: 
                   37783:         $contents = "#PEAR_Config 0.9\n" . serialize($data);
                   37784:         if (!@fwrite($fp, $contents)) {
                   37785:             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
                   37786:         }
                   37787:         return true;
                   37788:     }
                   37789: 
                   37790:     /**
                   37791:      * Reads configuration data from a file and returns the parsed data
                   37792:      * in an array.
                   37793:      *
                   37794:      * @param string file to read from
                   37795:      * @return array configuration data or a PEAR error on failure
                   37796:      * @access private
                   37797:      */
                   37798:     function _readConfigDataFrom($file)
                   37799:     {
                   37800:         $fp = false;
                   37801:         if (file_exists($file)) {
                   37802:             $fp = @fopen($file, "r");
                   37803:         }
                   37804: 
                   37805:         if (!$fp) {
                   37806:             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
                   37807:         }
                   37808: 
                   37809:         $size = filesize($file);
                   37810:         $rt = get_magic_quotes_runtime();
                   37811:         set_magic_quotes_runtime(0);
                   37812:         fclose($fp);
                   37813:         $contents = file_get_contents($file);
                   37814:         if (empty($contents)) {
                   37815:             return $this->raiseError('Configuration file "' . $file . '" is empty');
                   37816:         }
                   37817: 
                   37818:         set_magic_quotes_runtime($rt);
                   37819: 
                   37820:         $version = false;
                   37821:         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
                   37822:             $version = $matches[1];
                   37823:             $contents = substr($contents, strlen($matches[0]));
                   37824:         } else {
                   37825:             // Museum config file
                   37826:             if (substr($contents,0,2) == 'a:') {
                   37827:                 $version = '0.1';
                   37828:             }
                   37829:         }
                   37830: 
                   37831:         if ($version && version_compare("$version", '1', '<')) {
                   37832:             // no '@', it is possible that unserialize
                   37833:             // raises a notice but it seems to block IO to
                   37834:             // STDOUT if a '@' is used and a notice is raise
                   37835:             $data = unserialize($contents);
                   37836: 
                   37837:             if (!is_array($data) && !$data) {
                   37838:                 if ($contents == serialize(false)) {
                   37839:                     $data = array();
                   37840:                 } else {
                   37841:                     $err = $this->raiseError("PEAR_Config: bad data in $file");
                   37842:                     return $err;
                   37843:                 }
                   37844:             }
                   37845:             if (!is_array($data)) {
                   37846:                 if (strlen(trim($contents)) > 0) {
                   37847:                     $error = "PEAR_Config: bad data in $file";
                   37848:                     $err = $this->raiseError($error);
                   37849:                     return $err;
                   37850:                 }
                   37851: 
                   37852:                 $data = array();
                   37853:             }
                   37854:         // add parsing of newer formats here...
                   37855:         } else {
                   37856:             $err = $this->raiseError("$file: unknown version `$version'");
                   37857:             return $err;
                   37858:         }
                   37859: 
                   37860:         return $data;
                   37861:     }
                   37862: 
                   37863:     /**
                   37864:     * Gets the file used for storing the config for a layer
                   37865:     *
                   37866:     * @param string $layer 'user' or 'system'
                   37867:     */
                   37868:     function getConfFile($layer)
                   37869:     {
                   37870:         return $this->files[$layer];
                   37871:     }
                   37872: 
                   37873:     /**
                   37874:      * @param string Configuration class name, used for detecting duplicate calls
                   37875:      * @param array information on a role as parsed from its xml file
                   37876:      * @return true|PEAR_Error
                   37877:      * @access private
                   37878:      */
                   37879:     function _addConfigVars($class, $vars)
                   37880:     {
                   37881:         static $called = array();
                   37882:         if (isset($called[$class])) {
                   37883:             return;
                   37884:         }
                   37885: 
                   37886:         $called[$class] = 1;
                   37887:         if (count($vars) > 3) {
                   37888:             return $this->raiseError('Roles can only define 3 new config variables or less');
                   37889:         }
                   37890: 
                   37891:         foreach ($vars as $name => $var) {
                   37892:             if (!is_array($var)) {
                   37893:                 return $this->raiseError('Configuration information must be an array');
                   37894:             }
                   37895: 
                   37896:             if (!isset($var['type'])) {
                   37897:                 return $this->raiseError('Configuration information must contain a type');
                   37898:             } elseif (!in_array($var['type'],
                   37899:                     array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
                   37900:                   return $this->raiseError(
                   37901:                       'Configuration type must be one of directory, file, string, ' .
                   37902:                       'mask, set, or password');
                   37903:             }
                   37904:             if (!isset($var['default'])) {
                   37905:                 return $this->raiseError(
                   37906:                     'Configuration information must contain a default value ("default" index)');
                   37907:             }
                   37908: 
                   37909:             if (is_array($var['default'])) {
                   37910:                 $real_default = '';
                   37911:                 foreach ($var['default'] as $config_var => $val) {
                   37912:                     if (strpos($config_var, 'text') === 0) {
                   37913:                         $real_default .= $val;
                   37914:                     } elseif (strpos($config_var, 'constant') === 0) {
                   37915:                         if (!defined($val)) {
                   37916:                             return $this->raiseError(
                   37917:                                 'Unknown constant "' . $val . '" requested in ' .
                   37918:                                 'default value for configuration variable "' .
                   37919:                                 $name . '"');
                   37920:                         }
                   37921: 
                   37922:                         $real_default .= constant($val);
                   37923:                     } elseif (isset($this->configuration_info[$config_var])) {
                   37924:                         $real_default .=
                   37925:                             $this->configuration_info[$config_var]['default'];
                   37926:                     } else {
                   37927:                         return $this->raiseError(
                   37928:                             'Unknown request for "' . $config_var . '" value in ' .
                   37929:                             'default value for configuration variable "' .
                   37930:                             $name . '"');
                   37931:                     }
                   37932:                 }
                   37933:                 $var['default'] = $real_default;
                   37934:             }
                   37935: 
                   37936:             if ($var['type'] == 'integer') {
                   37937:                 $var['default'] = (integer) $var['default'];
                   37938:             }
                   37939: 
                   37940:             if (!isset($var['doc'])) {
                   37941:                 return $this->raiseError(
                   37942:                     'Configuration information must contain a summary ("doc" index)');
                   37943:             }
                   37944: 
                   37945:             if (!isset($var['prompt'])) {
                   37946:                 return $this->raiseError(
                   37947:                     'Configuration information must contain a simple prompt ("prompt" index)');
                   37948:             }
                   37949: 
                   37950:             if (!isset($var['group'])) {
                   37951:                 return $this->raiseError(
                   37952:                     'Configuration information must contain a simple group ("group" index)');
                   37953:             }
                   37954: 
                   37955:             if (isset($this->configuration_info[$name])) {
                   37956:                 return $this->raiseError('Configuration variable "' . $name .
                   37957:                     '" already exists');
                   37958:             }
                   37959: 
                   37960:             $this->configuration_info[$name] = $var;
                   37961:             // fix bug #7351: setting custom config variable in a channel fails
                   37962:             $this->_channelConfigInfo[] = $name;
                   37963:         }
                   37964: 
                   37965:         return true;
                   37966:     }
                   37967: 
                   37968:     /**
                   37969:      * Encodes/scrambles configuration data before writing to files.
                   37970:      * Currently, 'password' values will be base64-encoded as to avoid
                   37971:      * that people spot cleartext passwords by accident.
                   37972:      *
                   37973:      * @param array (reference) array to encode values in
                   37974:      * @return bool TRUE on success
                   37975:      * @access private
                   37976:      */
                   37977:     function _encodeOutput(&$data)
                   37978:     {
                   37979:         foreach ($data as $key => $value) {
                   37980:             if ($key == '__channels') {
                   37981:                 foreach ($data['__channels'] as $channel => $blah) {
                   37982:                     $this->_encodeOutput($data['__channels'][$channel]);
                   37983:                 }
                   37984:             }
                   37985: 
                   37986:             if (!isset($this->configuration_info[$key])) {
                   37987:                 continue;
                   37988:             }
                   37989: 
                   37990:             $type = $this->configuration_info[$key]['type'];
                   37991:             switch ($type) {
                   37992:                 // we base64-encode passwords so they are at least
                   37993:                 // not shown in plain by accident
                   37994:                 case 'password': {
                   37995:                     $data[$key] = base64_encode($data[$key]);
                   37996:                     break;
                   37997:                 }
                   37998:                 case 'mask': {
                   37999:                     $data[$key] = octdec($data[$key]);
                   38000:                     break;
                   38001:                 }
                   38002:             }
                   38003:         }
                   38004: 
                   38005:         return true;
                   38006:     }
                   38007: 
                   38008:     /**
                   38009:      * Decodes/unscrambles configuration data after reading from files.
                   38010:      *
                   38011:      * @param array (reference) array to encode values in
                   38012:      * @return bool TRUE on success
                   38013:      * @access private
                   38014:      *
                   38015:      * @see PEAR_Config::_encodeOutput
                   38016:      */
                   38017:     function _decodeInput(&$data)
                   38018:     {
                   38019:         if (!is_array($data)) {
                   38020:             return true;
                   38021:         }
                   38022: 
                   38023:         foreach ($data as $key => $value) {
                   38024:             if ($key == '__channels') {
                   38025:                 foreach ($data['__channels'] as $channel => $blah) {
                   38026:                     $this->_decodeInput($data['__channels'][$channel]);
                   38027:                 }
                   38028:             }
                   38029: 
                   38030:             if (!isset($this->configuration_info[$key])) {
                   38031:                 continue;
                   38032:             }
                   38033: 
                   38034:             $type = $this->configuration_info[$key]['type'];
                   38035:             switch ($type) {
                   38036:                 case 'password': {
                   38037:                     $data[$key] = base64_decode($data[$key]);
                   38038:                     break;
                   38039:                 }
                   38040:                 case 'mask': {
                   38041:                     $data[$key] = decoct($data[$key]);
                   38042:                     break;
                   38043:                 }
                   38044:             }
                   38045:         }
                   38046: 
                   38047:         return true;
                   38048:     }
                   38049: 
                   38050:     /**
                   38051:      * Retrieve the default channel.
                   38052:      *
                   38053:      * On startup, channels are not initialized, so if the default channel is not
                   38054:      * pear.php.net, then initialize the config.
                   38055:      * @param string registry layer
                   38056:      * @return string|false
                   38057:      */
                   38058:     function getDefaultChannel($layer = null)
                   38059:     {
                   38060:         $ret = false;
                   38061:         if ($layer === null) {
                   38062:             foreach ($this->layers as $layer) {
                   38063:                 if (isset($this->configuration[$layer]['default_channel'])) {
                   38064:                     $ret = $this->configuration[$layer]['default_channel'];
                   38065:                     break;
                   38066:                 }
                   38067:             }
                   38068:         } elseif (isset($this->configuration[$layer]['default_channel'])) {
                   38069:             $ret = $this->configuration[$layer]['default_channel'];
                   38070:         }
                   38071: 
                   38072:         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
                   38073:             $ret = 'pecl.php.net';
                   38074:         }
                   38075: 
                   38076:         if ($ret) {
                   38077:             if ($ret != 'pear.php.net') {
                   38078:                 $this->_lazyChannelSetup();
                   38079:             }
                   38080: 
                   38081:             return $ret;
                   38082:         }
                   38083: 
                   38084:         return PEAR_CONFIG_DEFAULT_CHANNEL;
                   38085:     }
                   38086: 
                   38087:     /**
                   38088:      * Returns a configuration value, prioritizing layers as per the
                   38089:      * layers property.
                   38090:      *
                   38091:      * @param string config key
                   38092:      * @return mixed the config value, or NULL if not found
                   38093:      * @access public
                   38094:      */
                   38095:     function get($key, $layer = null, $channel = false)
                   38096:     {
                   38097:         if (!isset($this->configuration_info[$key])) {
                   38098:             return null;
                   38099:         }
                   38100: 
                   38101:         if ($key == '__channels') {
                   38102:             return null;
                   38103:         }
                   38104: 
                   38105:         if ($key == 'default_channel') {
                   38106:             return $this->getDefaultChannel($layer);
                   38107:         }
                   38108: 
                   38109:         if (!$channel) {
                   38110:             $channel = $this->getDefaultChannel();
                   38111:         } elseif ($channel != 'pear.php.net') {
                   38112:             $this->_lazyChannelSetup();
                   38113:         }
                   38114:         $channel = strtolower($channel);
                   38115: 
                   38116:         $test = (in_array($key, $this->_channelConfigInfo)) ?
                   38117:             $this->_getChannelValue($key, $layer, $channel) :
                   38118:             null;
                   38119:         if ($test !== null) {
                   38120:             if ($this->_installRoot) {
                   38121:                 if (in_array($this->getGroup($key),
                   38122:                       array('File Locations', 'File Locations (Advanced)')) &&
                   38123:                       $this->getType($key) == 'directory') {
                   38124:                     return $this->_prependPath($test, $this->_installRoot);
                   38125:                 }
                   38126:             }
                   38127:             return $test;
                   38128:         }
                   38129: 
                   38130:         if ($layer === null) {
                   38131:             foreach ($this->layers as $layer) {
                   38132:                 if (isset($this->configuration[$layer][$key])) {
                   38133:                     $test = $this->configuration[$layer][$key];
                   38134:                     if ($this->_installRoot) {
                   38135:                         if (in_array($this->getGroup($key),
                   38136:                               array('File Locations', 'File Locations (Advanced)')) &&
                   38137:                               $this->getType($key) == 'directory') {
                   38138:                             return $this->_prependPath($test, $this->_installRoot);
                   38139:                         }
                   38140:                     }
                   38141: 
                   38142:                     if ($key == 'preferred_mirror') {
                   38143:                         $reg = &$this->getRegistry();
                   38144:                         if (is_object($reg)) {
                   38145:                             $chan = &$reg->getChannel($channel);
                   38146:                             if (PEAR::isError($chan)) {
                   38147:                                 return $channel;
                   38148:                             }
                   38149: 
                   38150:                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   38151:                                 return $channel; // mirror does not exist
                   38152:                             }
                   38153:                         }
                   38154:                     }
                   38155:                     return $test;
                   38156:                 }
                   38157:             }
                   38158:         } elseif (isset($this->configuration[$layer][$key])) {
                   38159:             $test = $this->configuration[$layer][$key];
                   38160:             if ($this->_installRoot) {
                   38161:                 if (in_array($this->getGroup($key),
                   38162:                       array('File Locations', 'File Locations (Advanced)')) &&
                   38163:                       $this->getType($key) == 'directory') {
                   38164:                     return $this->_prependPath($test, $this->_installRoot);
                   38165:                 }
                   38166:             }
                   38167: 
                   38168:             if ($key == 'preferred_mirror') {
                   38169:                 $reg = &$this->getRegistry();
                   38170:                 if (is_object($reg)) {
                   38171:                     $chan = &$reg->getChannel($channel);
                   38172:                     if (PEAR::isError($chan)) {
                   38173:                         return $channel;
                   38174:                     }
                   38175: 
                   38176:                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   38177:                         return $channel; // mirror does not exist
                   38178:                     }
                   38179:                 }
                   38180:             }
                   38181: 
                   38182:             return $test;
                   38183:         }
                   38184: 
                   38185:         return null;
                   38186:     }
                   38187: 
                   38188:     /**
                   38189:      * Returns a channel-specific configuration value, prioritizing layers as per the
                   38190:      * layers property.
                   38191:      *
                   38192:      * @param string config key
                   38193:      * @return mixed the config value, or NULL if not found
                   38194:      * @access private
                   38195:      */
                   38196:     function _getChannelValue($key, $layer, $channel)
                   38197:     {
                   38198:         if ($key == '__channels' || $channel == 'pear.php.net') {
                   38199:             return null;
                   38200:         }
                   38201: 
                   38202:         $ret = null;
                   38203:         if ($layer === null) {
                   38204:             foreach ($this->layers as $ilayer) {
                   38205:                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
                   38206:                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
                   38207:                     break;
                   38208:                 }
                   38209:             }
                   38210:         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38211:             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
                   38212:         }
                   38213: 
                   38214:         if ($key != 'preferred_mirror') {
                   38215:             return $ret;
                   38216:         }
                   38217: 
                   38218: 
                   38219:         if ($ret !== null) {
                   38220:             $reg = &$this->getRegistry($layer);
                   38221:             if (is_object($reg)) {
                   38222:                 $chan = &$reg->getChannel($channel);
                   38223:                 if (PEAR::isError($chan)) {
                   38224:                     return $channel;
                   38225:                 }
                   38226: 
                   38227:                 if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
                   38228:                     return $channel; // mirror does not exist
                   38229:                 }
                   38230:             }
                   38231: 
                   38232:             return $ret;
                   38233:         }
                   38234: 
                   38235:         if ($channel != $this->getDefaultChannel($layer)) {
                   38236:             return $channel; // we must use the channel name as the preferred mirror
                   38237:                              // if the user has not chosen an alternate
                   38238:         }
                   38239: 
                   38240:         return $this->getDefaultChannel($layer);
                   38241:     }
                   38242: 
                   38243:     /**
                   38244:      * Set a config value in a specific layer (defaults to 'user').
                   38245:      * Enforces the types defined in the configuration_info array.  An
                   38246:      * integer config variable will be cast to int, and a set config
                   38247:      * variable will be validated against its legal values.
                   38248:      *
                   38249:      * @param string config key
                   38250:      * @param string config value
                   38251:      * @param string (optional) config layer
                   38252:      * @param string channel to set this value for, or null for global value
                   38253:      * @return bool TRUE on success, FALSE on failure
                   38254:      */
                   38255:     function set($key, $value, $layer = 'user', $channel = false)
                   38256:     {
                   38257:         if ($key == '__channels') {
                   38258:             return false;
                   38259:         }
                   38260: 
                   38261:         if (!isset($this->configuration[$layer])) {
                   38262:             return false;
                   38263:         }
                   38264: 
                   38265:         if ($key == 'default_channel') {
                   38266:             // can only set this value globally
                   38267:             $channel = 'pear.php.net';
                   38268:             if ($value != 'pear.php.net') {
                   38269:                 $this->_lazyChannelSetup($layer);
                   38270:             }
                   38271:         }
                   38272: 
                   38273:         if ($key == 'preferred_mirror') {
                   38274:             if ($channel == '__uri') {
                   38275:                 return false; // can't set the __uri pseudo-channel's mirror
                   38276:             }
                   38277: 
                   38278:             $reg = &$this->getRegistry($layer);
                   38279:             if (is_object($reg)) {
                   38280:                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
                   38281:                 if (PEAR::isError($chan)) {
                   38282:                     return false;
                   38283:                 }
                   38284: 
                   38285:                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
                   38286:                     return false; // mirror does not exist
                   38287:                 }
                   38288:             }
                   38289:         }
                   38290: 
                   38291:         if (!isset($this->configuration_info[$key])) {
                   38292:             return false;
                   38293:         }
                   38294: 
                   38295:         extract($this->configuration_info[$key]);
                   38296:         switch ($type) {
                   38297:             case 'integer':
                   38298:                 $value = (int)$value;
                   38299:                 break;
                   38300:             case 'set': {
                   38301:                 // If a valid_set is specified, require the value to
                   38302:                 // be in the set.  If there is no valid_set, accept
                   38303:                 // any value.
                   38304:                 if ($valid_set) {
                   38305:                     reset($valid_set);
                   38306:                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
                   38307:                         (key($valid_set) !== 0 && empty($valid_set[$value])))
                   38308:                     {
                   38309:                         return false;
                   38310:                     }
                   38311:                 }
                   38312:                 break;
                   38313:             }
                   38314:         }
                   38315: 
                   38316:         if (!$channel) {
                   38317:             $channel = $this->get('default_channel', null, 'pear.php.net');
                   38318:         }
                   38319: 
                   38320:         if (!in_array($channel, $this->_channels)) {
                   38321:             $this->_lazyChannelSetup($layer);
                   38322:             $reg = &$this->getRegistry($layer);
                   38323:             if ($reg) {
                   38324:                 $channel = $reg->channelName($channel);
                   38325:             }
                   38326: 
                   38327:             if (!in_array($channel, $this->_channels)) {
                   38328:                 return false;
                   38329:             }
                   38330:         }
                   38331: 
                   38332:         if ($channel != 'pear.php.net') {
                   38333:             if (in_array($key, $this->_channelConfigInfo)) {
                   38334:                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
                   38335:                 return true;
                   38336:             }
                   38337: 
                   38338:             return false;
                   38339:         }
                   38340: 
                   38341:         if ($key == 'default_channel') {
                   38342:             if (!isset($reg)) {
                   38343:                 $reg = &$this->getRegistry($layer);
                   38344:                 if (!$reg) {
                   38345:                     $reg = &$this->getRegistry();
                   38346:                 }
                   38347:             }
                   38348: 
                   38349:             if ($reg) {
                   38350:                 $value = $reg->channelName($value);
                   38351:             }
                   38352: 
                   38353:             if (!$value) {
                   38354:                 return false;
                   38355:             }
                   38356:         }
                   38357: 
                   38358:         $this->configuration[$layer][$key] = $value;
                   38359:         if ($key == 'php_dir' && !$this->_noRegistry) {
                   38360:             if (!isset($this->_registry[$layer]) ||
                   38361:                   $value != $this->_registry[$layer]->install_dir) {
                   38362:                 $this->_registry[$layer] = &new PEAR_Registry($value);
                   38363:                 $this->_regInitialized[$layer] = false;
                   38364:                 $this->_registry[$layer]->setConfig($this, false);
                   38365:             }
                   38366:         }
                   38367: 
                   38368:         return true;
                   38369:     }
                   38370: 
                   38371:     function _lazyChannelSetup($uselayer = false)
                   38372:     {
                   38373:         if ($this->_noRegistry) {
                   38374:             return;
                   38375:         }
                   38376: 
                   38377:         $merge = false;
                   38378:         foreach ($this->_registry as $layer => $p) {
                   38379:             if ($uselayer && $uselayer != $layer) {
                   38380:                 continue;
                   38381:             }
                   38382: 
                   38383:             if (!$this->_regInitialized[$layer]) {
                   38384:                 if ($layer == 'default' && isset($this->_registry['user']) ||
                   38385:                       isset($this->_registry['system'])) {
                   38386:                     // only use the default registry if there are no alternatives
                   38387:                     continue;
                   38388:                 }
                   38389: 
                   38390:                 if (!is_object($this->_registry[$layer])) {
                   38391:                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
                   38392:                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   38393:                         $this->_registry[$layer]->setConfig($this, false);
                   38394:                         $this->_regInitialized[$layer] = false;
                   38395:                     } else {
                   38396:                         unset($this->_registry[$layer]);
                   38397:                         return;
                   38398:                     }
                   38399:                 }
                   38400: 
                   38401:                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
                   38402:                 $this->_regInitialized[$layer] = true;
                   38403:                 $merge = true;
                   38404:             }
                   38405:         }
                   38406:     }
                   38407: 
                   38408:     /**
                   38409:      * Set the list of channels.
                   38410:      *
                   38411:      * This should be set via a call to {@link PEAR_Registry::listChannels()}
                   38412:      * @param array
                   38413:      * @param bool
                   38414:      * @return bool success of operation
                   38415:      */
                   38416:     function setChannels($channels, $merge = false)
                   38417:     {
                   38418:         if (!is_array($channels)) {
                   38419:             return false;
                   38420:         }
                   38421: 
                   38422:         if ($merge) {
                   38423:             $this->_channels = array_merge($this->_channels, $channels);
                   38424:         } else {
                   38425:             $this->_channels = $channels;
                   38426:         }
                   38427: 
                   38428:         foreach ($channels as $channel) {
                   38429:             $channel = strtolower($channel);
                   38430:             if ($channel == 'pear.php.net') {
                   38431:                 continue;
                   38432:             }
                   38433: 
                   38434:             foreach ($this->layers as $layer) {
                   38435:                 if (!isset($this->configuration[$layer]['__channels'])) {
                   38436:                     $this->configuration[$layer]['__channels'] = array();
                   38437:                 }
                   38438:                 if (!isset($this->configuration[$layer]['__channels'][$channel])
                   38439:                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
                   38440:                     $this->configuration[$layer]['__channels'][$channel] = array();
                   38441:                 }
                   38442:             }
                   38443:         }
                   38444: 
                   38445:         return true;
                   38446:     }
                   38447: 
                   38448:     /**
                   38449:      * Get the type of a config value.
                   38450:      *
                   38451:      * @param string  config key
                   38452:      *
                   38453:      * @return string type, one of "string", "integer", "file",
                   38454:      * "directory", "set" or "password".
                   38455:      *
                   38456:      * @access public
                   38457:      *
                   38458:      */
                   38459:     function getType($key)
                   38460:     {
                   38461:         if (isset($this->configuration_info[$key])) {
                   38462:             return $this->configuration_info[$key]['type'];
                   38463:         }
                   38464:         return false;
                   38465:     }
                   38466: 
                   38467:     /**
                   38468:      * Get the documentation for a config value.
                   38469:      *
                   38470:      * @param string  config key
                   38471:      * @return string documentation string
                   38472:      *
                   38473:      * @access public
                   38474:      *
                   38475:      */
                   38476:     function getDocs($key)
                   38477:     {
                   38478:         if (isset($this->configuration_info[$key])) {
                   38479:             return $this->configuration_info[$key]['doc'];
                   38480:         }
                   38481: 
                   38482:         return false;
                   38483:     }
                   38484: 
                   38485:     /**
                   38486:      * Get the short documentation for a config value.
                   38487:      *
                   38488:      * @param string  config key
                   38489:      * @return string short documentation string
                   38490:      *
                   38491:      * @access public
                   38492:      *
                   38493:      */
                   38494:     function getPrompt($key)
                   38495:     {
                   38496:         if (isset($this->configuration_info[$key])) {
                   38497:             return $this->configuration_info[$key]['prompt'];
                   38498:         }
                   38499: 
                   38500:         return false;
                   38501:     }
                   38502: 
                   38503:     /**
                   38504:      * Get the parameter group for a config key.
                   38505:      *
                   38506:      * @param string  config key
                   38507:      * @return string parameter group
                   38508:      *
                   38509:      * @access public
                   38510:      *
                   38511:      */
                   38512:     function getGroup($key)
                   38513:     {
                   38514:         if (isset($this->configuration_info[$key])) {
                   38515:             return $this->configuration_info[$key]['group'];
                   38516:         }
                   38517: 
                   38518:         return false;
                   38519:     }
                   38520: 
                   38521:     /**
                   38522:      * Get the list of parameter groups.
                   38523:      *
                   38524:      * @return array list of parameter groups
                   38525:      *
                   38526:      * @access public
                   38527:      *
                   38528:      */
                   38529:     function getGroups()
                   38530:     {
                   38531:         $tmp = array();
                   38532:         foreach ($this->configuration_info as $key => $info) {
                   38533:             $tmp[$info['group']] = 1;
                   38534:         }
                   38535: 
                   38536:         return array_keys($tmp);
                   38537:     }
                   38538: 
                   38539:     /**
                   38540:      * Get the list of the parameters in a group.
                   38541:      *
                   38542:      * @param string $group parameter group
                   38543:      * @return array list of parameters in $group
                   38544:      *
                   38545:      * @access public
                   38546:      *
                   38547:      */
                   38548:     function getGroupKeys($group)
                   38549:     {
                   38550:         $keys = array();
                   38551:         foreach ($this->configuration_info as $key => $info) {
                   38552:             if ($info['group'] == $group) {
                   38553:                 $keys[] = $key;
                   38554:             }
                   38555:         }
                   38556: 
                   38557:         return $keys;
                   38558:     }
                   38559: 
                   38560:     /**
                   38561:      * Get the list of allowed set values for a config value.  Returns
                   38562:      * NULL for config values that are not sets.
                   38563:      *
                   38564:      * @param string  config key
                   38565:      * @return array enumerated array of set values, or NULL if the
                   38566:      *               config key is unknown or not a set
                   38567:      *
                   38568:      * @access public
                   38569:      *
                   38570:      */
                   38571:     function getSetValues($key)
                   38572:     {
                   38573:         if (isset($this->configuration_info[$key]) &&
                   38574:             isset($this->configuration_info[$key]['type']) &&
                   38575:             $this->configuration_info[$key]['type'] == 'set')
                   38576:         {
                   38577:             $valid_set = $this->configuration_info[$key]['valid_set'];
                   38578:             reset($valid_set);
                   38579:             if (key($valid_set) === 0) {
                   38580:                 return $valid_set;
                   38581:             }
                   38582: 
                   38583:             return array_keys($valid_set);
                   38584:         }
                   38585: 
                   38586:         return null;
                   38587:     }
                   38588: 
                   38589:     /**
                   38590:      * Get all the current config keys.
                   38591:      *
                   38592:      * @return array simple array of config keys
                   38593:      *
                   38594:      * @access public
                   38595:      */
                   38596:     function getKeys()
                   38597:     {
                   38598:         $keys = array();
                   38599:         foreach ($this->layers as $layer) {
                   38600:             $test = $this->configuration[$layer];
                   38601:             if (isset($test['__channels'])) {
                   38602:                 foreach ($test['__channels'] as $channel => $configs) {
                   38603:                     $keys = array_merge($keys, $configs);
                   38604:                 }
                   38605:             }
                   38606: 
                   38607:             unset($test['__channels']);
                   38608:             $keys = array_merge($keys, $test);
                   38609: 
                   38610:         }
                   38611:         return array_keys($keys);
                   38612:     }
                   38613: 
                   38614:     /**
                   38615:      * Remove the a config key from a specific config layer.
                   38616:      *
                   38617:      * @param string config key
                   38618:      * @param string (optional) config layer
                   38619:      * @param string (optional) channel (defaults to default channel)
                   38620:      * @return bool TRUE on success, FALSE on failure
                   38621:      *
                   38622:      * @access public
                   38623:      */
                   38624:     function remove($key, $layer = 'user', $channel = null)
                   38625:     {
                   38626:         if ($channel === null) {
                   38627:             $channel = $this->getDefaultChannel();
                   38628:         }
                   38629: 
                   38630:         if ($channel !== 'pear.php.net') {
                   38631:             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38632:                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
                   38633:                 return true;
                   38634:             }
                   38635:         }
                   38636: 
                   38637:         if (isset($this->configuration[$layer][$key])) {
                   38638:             unset($this->configuration[$layer][$key]);
                   38639:             return true;
                   38640:         }
                   38641: 
                   38642:         return false;
                   38643:     }
                   38644: 
                   38645:     /**
                   38646:      * Temporarily remove an entire config layer.  USE WITH CARE!
                   38647:      *
                   38648:      * @param string config key
                   38649:      * @param string (optional) config layer
                   38650:      * @return bool TRUE on success, FALSE on failure
                   38651:      *
                   38652:      * @access public
                   38653:      */
                   38654:     function removeLayer($layer)
                   38655:     {
                   38656:         if (isset($this->configuration[$layer])) {
                   38657:             $this->configuration[$layer] = array();
                   38658:             return true;
                   38659:         }
                   38660: 
                   38661:         return false;
                   38662:     }
                   38663: 
                   38664:     /**
                   38665:      * Stores configuration data in a layer.
                   38666:      *
                   38667:      * @param string config layer to store
                   38668:      * @return bool TRUE on success, or PEAR error on failure
                   38669:      *
                   38670:      * @access public
                   38671:      */
                   38672:     function store($layer = 'user', $data = null)
                   38673:     {
                   38674:         return $this->writeConfigFile(null, $layer, $data);
                   38675:     }
                   38676: 
                   38677:     /**
                   38678:      * Tells what config layer that gets to define a key.
                   38679:      *
                   38680:      * @param string config key
                   38681:      * @param boolean return the defining channel
                   38682:      *
                   38683:      * @return string|array the config layer, or an empty string if not found.
                   38684:      *
                   38685:      *         if $returnchannel, the return is an array array('layer' => layername,
                   38686:      *         'channel' => channelname), or an empty string if not found
                   38687:      *
                   38688:      * @access public
                   38689:      */
                   38690:     function definedBy($key, $returnchannel = false)
                   38691:     {
                   38692:         foreach ($this->layers as $layer) {
                   38693:             $channel = $this->getDefaultChannel();
                   38694:             if ($channel !== 'pear.php.net') {
                   38695:                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38696:                     if ($returnchannel) {
                   38697:                         return array('layer' => $layer, 'channel' => $channel);
                   38698:                     }
                   38699:                     return $layer;
                   38700:                 }
                   38701:             }
                   38702: 
                   38703:             if (isset($this->configuration[$layer][$key])) {
                   38704:                 if ($returnchannel) {
                   38705:                     return array('layer' => $layer, 'channel' => 'pear.php.net');
                   38706:                 }
                   38707:                 return $layer;
                   38708:             }
                   38709:         }
                   38710: 
                   38711:         return '';
                   38712:     }
                   38713: 
                   38714:     /**
                   38715:      * Tells whether a given key exists as a config value.
                   38716:      *
                   38717:      * @param string config key
                   38718:      * @return bool whether <config key> exists in this object
                   38719:      *
                   38720:      * @access public
                   38721:      */
                   38722:     function isDefined($key)
                   38723:     {
                   38724:         foreach ($this->layers as $layer) {
                   38725:             if (isset($this->configuration[$layer][$key])) {
                   38726:                 return true;
                   38727:             }
                   38728:         }
                   38729: 
                   38730:         return false;
                   38731:     }
                   38732: 
                   38733:     /**
                   38734:      * Tells whether a given config layer exists.
                   38735:      *
                   38736:      * @param string config layer
                   38737:      * @return bool whether <config layer> exists in this object
                   38738:      *
                   38739:      * @access public
                   38740:      */
                   38741:     function isDefinedLayer($layer)
                   38742:     {
                   38743:         return isset($this->configuration[$layer]);
                   38744:     }
                   38745: 
                   38746:     /**
                   38747:      * Returns the layers defined (except the 'default' one)
                   38748:      *
                   38749:      * @return array of the defined layers
                   38750:      */
                   38751:     function getLayers()
                   38752:     {
                   38753:         $cf = $this->configuration;
                   38754:         unset($cf['default']);
                   38755:         return array_keys($cf);
                   38756:     }
                   38757: 
                   38758:     function apiVersion()
                   38759:     {
                   38760:         return '1.1';
                   38761:     }
                   38762: 
                   38763:     /**
                   38764:      * @return PEAR_Registry
                   38765:      */
                   38766:     function &getRegistry($use = null)
                   38767:     {
                   38768:         $layer = $use === null ? 'user' : $use;
                   38769:         if (isset($this->_registry[$layer])) {
                   38770:             return $this->_registry[$layer];
                   38771:         } elseif ($use === null && isset($this->_registry['system'])) {
                   38772:             return $this->_registry['system'];
                   38773:         } elseif ($use === null && isset($this->_registry['default'])) {
                   38774:             return $this->_registry['default'];
                   38775:         } elseif ($use) {
                   38776:             $a = false;
                   38777:             return $a;
                   38778:         }
                   38779: 
                   38780:         // only go here if null was passed in
                   38781:         echo "CRITICAL ERROR: Registry could not be initialized from any value";
                   38782:         exit(1);
                   38783:     }
                   38784: 
                   38785:     /**
                   38786:      * This is to allow customization like the use of installroot
                   38787:      * @param PEAR_Registry
                   38788:      * @return bool
                   38789:      */
                   38790:     function setRegistry(&$reg, $layer = 'user')
                   38791:     {
                   38792:         if ($this->_noRegistry) {
                   38793:             return false;
                   38794:         }
                   38795: 
                   38796:         if (!in_array($layer, array('user', 'system'))) {
                   38797:             return false;
                   38798:         }
                   38799: 
                   38800:         $this->_registry[$layer] = &$reg;
                   38801:         if (is_object($reg)) {
                   38802:             $this->_registry[$layer]->setConfig($this, false);
                   38803:         }
                   38804: 
                   38805:         return true;
                   38806:     }
                   38807: 
                   38808:     function noRegistry()
                   38809:     {
                   38810:         $this->_noRegistry = true;
                   38811:     }
                   38812: 
                   38813:     /**
                   38814:      * @return PEAR_REST
                   38815:      */
                   38816:     function &getREST($version, $options = array())
                   38817:     {
                   38818:         $version = str_replace('.', '', $version);
                   38819:         if (!class_exists($class = 'PEAR_REST_' . $version)) {
                   38820:             require_once 'PEAR/REST/' . $version . '.php';
                   38821:         }
                   38822: 
                   38823:         $remote = &new $class($this, $options);
                   38824:         return $remote;
                   38825:     }
                   38826: 
                   38827:     /**
                   38828:      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
                   38829:      * remote configuration file has been specified
                   38830:      * @return PEAR_FTP|false
                   38831:      */
                   38832:     function &getFTP()
                   38833:     {
                   38834:         if (isset($this->_ftp)) {
                   38835:             return $this->_ftp;
                   38836:         }
                   38837: 
                   38838:         $a = false;
                   38839:         return $a;
                   38840:     }
                   38841: 
                   38842:     function _prependPath($path, $prepend)
                   38843:     {
                   38844:         if (strlen($prepend) > 0) {
                   38845:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   38846:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   38847:                     $prepend = substr($prepend, 2);
                   38848:                 } elseif ($prepend{0} != '\\') {
                   38849:                     $prepend = "\\$prepend";
                   38850:                 }
                   38851:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   38852:             } else {
                   38853:                 $path = $prepend . $path;
                   38854:             }
                   38855:         }
                   38856:         return $path;
                   38857:     }
                   38858: 
                   38859:     /**
                   38860:      * @param string|false installation directory to prepend to all _dir variables, or false to
                   38861:      *                     disable
                   38862:      */
                   38863:     function setInstallRoot($root)
                   38864:     {
                   38865:         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
                   38866:             $root = substr($root, 0, -1);
                   38867:         }
                   38868:         $old = $this->_installRoot;
                   38869:         $this->_installRoot = $root;
                   38870:         if (($old != $root) && !$this->_noRegistry) {
                   38871:             foreach (array_keys($this->_registry) as $layer) {
                   38872:                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
                   38873:                     continue;
                   38874:                 }
                   38875:                 $this->_registry[$layer] =
                   38876:                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
                   38877:                 $this->_registry[$layer]->setConfig($this, false);
                   38878:                 $this->_regInitialized[$layer] = false;
                   38879:             }
                   38880:         }
                   38881:     }
                   38882: }
                   38883: PEAR-1.9.4/PEAR/DependencyDB.php0000644000076500000240000005725611605156760015001 0ustar  helgistaff<?php
                   38884: /**
                   38885:  * PEAR_DependencyDB, advanced installed packages dependency database
                   38886:  *
                   38887:  * PHP versions 4 and 5
                   38888:  *
                   38889:  * @category   pear
                   38890:  * @package    PEAR
                   38891:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   38892:  * @author     Greg Beaver <cellog@php.net>
                   38893:  * @copyright  1997-2009 The Authors
                   38894:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   38895:  * @version    CVS: $Id: DependencyDB.php 313023 2011-07-06 19:17:11Z dufuz $
                   38896:  * @link       http://pear.php.net/package/PEAR
                   38897:  * @since      File available since Release 1.4.0a1
                   38898:  */
                   38899: 
                   38900: /**
                   38901:  * Needed for error handling
                   38902:  */
                   38903: require_once 'PEAR.php';
                   38904: require_once 'PEAR/Config.php';
                   38905: 
                   38906: $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
                   38907: /**
                   38908:  * Track dependency relationships between installed packages
                   38909:  * @category   pear
                   38910:  * @package    PEAR
                   38911:  * @author     Greg Beaver <cellog@php.net>
                   38912:  * @author     Tomas V.V.Cox <cox@idec.net.com>
                   38913:  * @copyright  1997-2009 The Authors
                   38914:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   38915:  * @version    Release: 1.9.4
                   38916:  * @link       http://pear.php.net/package/PEAR
                   38917:  * @since      Class available since Release 1.4.0a1
                   38918:  */
                   38919: class PEAR_DependencyDB
                   38920: {
                   38921:     // {{{ properties
                   38922: 
                   38923:     /**
                   38924:      * This is initialized by {@link setConfig()}
                   38925:      * @var PEAR_Config
                   38926:      * @access private
                   38927:      */
                   38928:     var $_config;
                   38929:     /**
                   38930:      * This is initialized by {@link setConfig()}
                   38931:      * @var PEAR_Registry
                   38932:      * @access private
                   38933:      */
                   38934:     var $_registry;
                   38935:     /**
                   38936:      * Filename of the dependency DB (usually .depdb)
                   38937:      * @var string
                   38938:      * @access private
                   38939:      */
                   38940:     var $_depdb = false;
                   38941:     /**
                   38942:      * File name of the lockfile (usually .depdblock)
                   38943:      * @var string
                   38944:      * @access private
                   38945:      */
                   38946:     var $_lockfile = false;
                   38947:     /**
                   38948:      * Open file resource for locking the lockfile
                   38949:      * @var resource|false
                   38950:      * @access private
                   38951:      */
                   38952:     var $_lockFp = false;
                   38953:     /**
                   38954:      * API version of this class, used to validate a file on-disk
                   38955:      * @var string
                   38956:      * @access private
                   38957:      */
                   38958:     var $_version = '1.0';
                   38959:     /**
                   38960:      * Cached dependency database file
                   38961:      * @var array|null
                   38962:      * @access private
                   38963:      */
                   38964:     var $_cache;
                   38965: 
                   38966:     // }}}
                   38967:     // {{{ & singleton()
                   38968: 
                   38969:     /**
                   38970:      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
                   38971:      * @param PEAR_Config
                   38972:      * @param string|false full path to the dependency database, or false to use default
                   38973:      * @return PEAR_DependencyDB|PEAR_Error
                   38974:      * @static
                   38975:      */
                   38976:     function &singleton(&$config, $depdb = false)
                   38977:     {
                   38978:         $phpdir = $config->get('php_dir', null, 'pear.php.net');
                   38979:         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
                   38980:             $a = new PEAR_DependencyDB;
                   38981:             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
                   38982:             $a->setConfig($config, $depdb);
                   38983:             $e = $a->assertDepsDB();
                   38984:             if (PEAR::isError($e)) {
                   38985:                 return $e;
                   38986:             }
                   38987:         }
                   38988: 
                   38989:         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
                   38990:     }
                   38991: 
                   38992:     /**
                   38993:      * Set up the registry/location of dependency DB
                   38994:      * @param PEAR_Config|false
                   38995:      * @param string|false full path to the dependency database, or false to use default
                   38996:      */
                   38997:     function setConfig(&$config, $depdb = false)
                   38998:     {
                   38999:         if (!$config) {
                   39000:             $this->_config = &PEAR_Config::singleton();
                   39001:         } else {
                   39002:             $this->_config = &$config;
                   39003:         }
                   39004: 
                   39005:         $this->_registry = &$this->_config->getRegistry();
                   39006:         if (!$depdb) {
                   39007:             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
                   39008:                 DIRECTORY_SEPARATOR . '.depdb';
                   39009:         } else {
                   39010:             $this->_depdb = $depdb;
                   39011:         }
                   39012: 
                   39013:         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
                   39014:     }
                   39015:     // }}}
                   39016: 
                   39017:     function hasWriteAccess()
                   39018:     {
                   39019:         if (!file_exists($this->_depdb)) {
                   39020:             $dir = $this->_depdb;
                   39021:             while ($dir && $dir != '.') {
                   39022:                 $dir = dirname($dir); // cd ..
                   39023:                 if ($dir != '.' && file_exists($dir)) {
                   39024:                     if (is_writeable($dir)) {
                   39025:                         return true;
                   39026:                     }
                   39027: 
                   39028:                     return false;
                   39029:                 }
                   39030:             }
                   39031: 
                   39032:             return false;
                   39033:         }
                   39034: 
                   39035:         return is_writeable($this->_depdb);
                   39036:     }
                   39037: 
                   39038:     // {{{ assertDepsDB()
                   39039: 
                   39040:     /**
                   39041:      * Create the dependency database, if it doesn't exist.  Error if the database is
                   39042:      * newer than the code reading it.
                   39043:      * @return void|PEAR_Error
                   39044:      */
                   39045:     function assertDepsDB()
                   39046:     {
                   39047:         if (!is_file($this->_depdb)) {
                   39048:             $this->rebuildDB();
                   39049:             return;
                   39050:         }
                   39051: 
                   39052:         $depdb = $this->_getDepDB();
                   39053:         // Datatype format has been changed, rebuild the Deps DB
                   39054:         if ($depdb['_version'] < $this->_version) {
                   39055:             $this->rebuildDB();
                   39056:         }
                   39057: 
                   39058:         if ($depdb['_version']{0} > $this->_version{0}) {
                   39059:             return PEAR::raiseError('Dependency database is version ' .
                   39060:                 $depdb['_version'] . ', and we are version ' .
                   39061:                 $this->_version . ', cannot continue');
                   39062:         }
                   39063:     }
                   39064: 
                   39065:     /**
                   39066:      * Get a list of installed packages that depend on this package
                   39067:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39068:      * @return array|false
                   39069:      */
                   39070:     function getDependentPackages(&$pkg)
                   39071:     {
                   39072:         $data = $this->_getDepDB();
                   39073:         if (is_object($pkg)) {
                   39074:             $channel = strtolower($pkg->getChannel());
                   39075:             $package = strtolower($pkg->getPackage());
                   39076:         } else {
                   39077:             $channel = strtolower($pkg['channel']);
                   39078:             $package = strtolower($pkg['package']);
                   39079:         }
                   39080: 
                   39081:         if (isset($data['packages'][$channel][$package])) {
                   39082:             return $data['packages'][$channel][$package];
                   39083:         }
                   39084: 
                   39085:         return false;
                   39086:     }
                   39087: 
                   39088:     /**
                   39089:      * Get a list of the actual dependencies of installed packages that depend on
                   39090:      * a package.
                   39091:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39092:      * @return array|false
                   39093:      */
                   39094:     function getDependentPackageDependencies(&$pkg)
                   39095:     {
                   39096:         $data = $this->_getDepDB();
                   39097:         if (is_object($pkg)) {
                   39098:             $channel = strtolower($pkg->getChannel());
                   39099:             $package = strtolower($pkg->getPackage());
                   39100:         } else {
                   39101:             $channel = strtolower($pkg['channel']);
                   39102:             $package = strtolower($pkg['package']);
                   39103:         }
                   39104: 
                   39105:         $depend = $this->getDependentPackages($pkg);
                   39106:         if (!$depend) {
                   39107:             return false;
                   39108:         }
                   39109: 
                   39110:         $dependencies = array();
                   39111:         foreach ($depend as $info) {
                   39112:             $temp = $this->getDependencies($info);
                   39113:             foreach ($temp as $dep) {
                   39114:                 if (
                   39115:                     isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                   39116:                     strtolower($dep['dep']['channel']) == $channel &&
                   39117:                     strtolower($dep['dep']['name']) == $package
                   39118:                 ) {
                   39119:                     if (!isset($dependencies[$info['channel']])) {
                   39120:                         $dependencies[$info['channel']] = array();
                   39121:                     }
                   39122: 
                   39123:                     if (!isset($dependencies[$info['channel']][$info['package']])) {
                   39124:                         $dependencies[$info['channel']][$info['package']] = array();
                   39125:                     }
                   39126:                     $dependencies[$info['channel']][$info['package']][] = $dep;
                   39127:                 }
                   39128:             }
                   39129:         }
                   39130: 
                   39131:         return $dependencies;
                   39132:     }
                   39133: 
                   39134:     /**
                   39135:      * Get a list of dependencies of this installed package
                   39136:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39137:      * @return array|false
                   39138:      */
                   39139:     function getDependencies(&$pkg)
                   39140:     {
                   39141:         if (is_object($pkg)) {
                   39142:             $channel = strtolower($pkg->getChannel());
                   39143:             $package = strtolower($pkg->getPackage());
                   39144:         } else {
                   39145:             $channel = strtolower($pkg['channel']);
                   39146:             $package = strtolower($pkg['package']);
                   39147:         }
                   39148: 
                   39149:         $data = $this->_getDepDB();
                   39150:         if (isset($data['dependencies'][$channel][$package])) {
                   39151:             return $data['dependencies'][$channel][$package];
                   39152:         }
                   39153: 
                   39154:         return false;
                   39155:     }
                   39156: 
                   39157:     /**
                   39158:      * Determine whether $parent depends on $child, near or deep
                   39159:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39160:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39161:      */
                   39162:     function dependsOn($parent, $child)
                   39163:     {
                   39164:         $c = array();
                   39165:         $this->_getDepDB();
                   39166:         return $this->_dependsOn($parent, $child, $c);
                   39167:     }
                   39168: 
                   39169:     function _dependsOn($parent, $child, &$checked)
                   39170:     {
                   39171:         if (is_object($parent)) {
                   39172:             $channel = strtolower($parent->getChannel());
                   39173:             $package = strtolower($parent->getPackage());
                   39174:         } else {
                   39175:             $channel = strtolower($parent['channel']);
                   39176:             $package = strtolower($parent['package']);
                   39177:         }
                   39178: 
                   39179:         if (is_object($child)) {
                   39180:             $depchannel = strtolower($child->getChannel());
                   39181:             $deppackage = strtolower($child->getPackage());
                   39182:         } else {
                   39183:             $depchannel = strtolower($child['channel']);
                   39184:             $deppackage = strtolower($child['package']);
                   39185:         }
                   39186: 
                   39187:         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
                   39188:             return false; // avoid endless recursion
                   39189:         }
                   39190: 
                   39191:         $checked[$channel][$package][$depchannel][$deppackage] = true;
                   39192:         if (!isset($this->_cache['dependencies'][$channel][$package])) {
                   39193:             return false;
                   39194:         }
                   39195: 
                   39196:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   39197:             if (isset($info['dep']['uri'])) {
                   39198:                 if (is_object($child)) {
                   39199:                     if ($info['dep']['uri'] == $child->getURI()) {
                   39200:                         return true;
                   39201:                     }
                   39202:                 } elseif (isset($child['uri'])) {
                   39203:                     if ($info['dep']['uri'] == $child['uri']) {
                   39204:                         return true;
                   39205:                     }
                   39206:                 }
                   39207:                 return false;
                   39208:             }
                   39209: 
                   39210:             if (strtolower($info['dep']['channel']) == $depchannel &&
                   39211:                   strtolower($info['dep']['name']) == $deppackage) {
                   39212:                 return true;
                   39213:             }
                   39214:         }
                   39215: 
                   39216:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   39217:             if (isset($info['dep']['uri'])) {
                   39218:                 if ($this->_dependsOn(array(
                   39219:                         'uri' => $info['dep']['uri'],
                   39220:                         'package' => $info['dep']['name']), $child, $checked)) {
                   39221:                     return true;
                   39222:                 }
                   39223:             } else {
                   39224:                 if ($this->_dependsOn(array(
                   39225:                         'channel' => $info['dep']['channel'],
                   39226:                         'package' => $info['dep']['name']), $child, $checked)) {
                   39227:                     return true;
                   39228:                 }
                   39229:             }
                   39230:         }
                   39231: 
                   39232:         return false;
                   39233:     }
                   39234: 
                   39235:     /**
                   39236:      * Register dependencies of a package that is being installed or upgraded
                   39237:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39238:      */
                   39239:     function installPackage(&$package)
                   39240:     {
                   39241:         $data = $this->_getDepDB();
                   39242:         unset($this->_cache);
                   39243:         $this->_setPackageDeps($data, $package);
                   39244:         $this->_writeDepDB($data);
                   39245:     }
                   39246: 
                   39247:     /**
                   39248:      * Remove dependencies of a package that is being uninstalled, or upgraded.
                   39249:      *
                   39250:      * Upgraded packages first uninstall, then install
                   39251:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
                   39252:      *        indices 'channel' and 'package'
                   39253:      */
                   39254:     function uninstallPackage(&$pkg)
                   39255:     {
                   39256:         $data = $this->_getDepDB();
                   39257:         unset($this->_cache);
                   39258:         if (is_object($pkg)) {
                   39259:             $channel = strtolower($pkg->getChannel());
                   39260:             $package = strtolower($pkg->getPackage());
                   39261:         } else {
                   39262:             $channel = strtolower($pkg['channel']);
                   39263:             $package = strtolower($pkg['package']);
                   39264:         }
                   39265: 
                   39266:         if (!isset($data['dependencies'][$channel][$package])) {
                   39267:             return true;
                   39268:         }
                   39269: 
                   39270:         foreach ($data['dependencies'][$channel][$package] as $dep) {
                   39271:             $found      = false;
                   39272:             $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
                   39273:             $depname    = strtolower($dep['dep']['name']);
                   39274:             if (isset($data['packages'][$depchannel][$depname])) {
                   39275:                 foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
                   39276:                     if ($info['channel'] == $channel && $info['package'] == $package) {
                   39277:                         $found = true;
                   39278:                         break;
                   39279:                     }
                   39280:                 }
                   39281:             }
                   39282: 
                   39283:             if ($found) {
                   39284:                 unset($data['packages'][$depchannel][$depname][$i]);
                   39285:                 if (!count($data['packages'][$depchannel][$depname])) {
                   39286:                     unset($data['packages'][$depchannel][$depname]);
                   39287:                     if (!count($data['packages'][$depchannel])) {
                   39288:                         unset($data['packages'][$depchannel]);
                   39289:                     }
                   39290:                 } else {
                   39291:                     $data['packages'][$depchannel][$depname] =
                   39292:                         array_values($data['packages'][$depchannel][$depname]);
                   39293:                 }
                   39294:             }
                   39295:         }
                   39296: 
                   39297:         unset($data['dependencies'][$channel][$package]);
                   39298:         if (!count($data['dependencies'][$channel])) {
                   39299:             unset($data['dependencies'][$channel]);
                   39300:         }
                   39301: 
                   39302:         if (!count($data['dependencies'])) {
                   39303:             unset($data['dependencies']);
                   39304:         }
                   39305: 
                   39306:         if (!count($data['packages'])) {
                   39307:             unset($data['packages']);
                   39308:         }
                   39309: 
                   39310:         $this->_writeDepDB($data);
                   39311:     }
                   39312: 
                   39313:     /**
                   39314:      * Rebuild the dependency DB by reading registry entries.
                   39315:      * @return true|PEAR_Error
                   39316:      */
                   39317:     function rebuildDB()
                   39318:     {
                   39319:         $depdb = array('_version' => $this->_version);
                   39320:         if (!$this->hasWriteAccess()) {
                   39321:             // allow startup for read-only with older Registry
                   39322:             return $depdb;
                   39323:         }
                   39324: 
                   39325:         $packages = $this->_registry->listAllPackages();
                   39326:         if (PEAR::isError($packages)) {
                   39327:             return $packages;
                   39328:         }
                   39329: 
                   39330:         foreach ($packages as $channel => $ps) {
                   39331:             foreach ($ps as $package) {
                   39332:                 $package = $this->_registry->getPackage($package, $channel);
                   39333:                 if (PEAR::isError($package)) {
                   39334:                     return $package;
                   39335:                 }
                   39336:                 $this->_setPackageDeps($depdb, $package);
                   39337:             }
                   39338:         }
                   39339: 
                   39340:         $error = $this->_writeDepDB($depdb);
                   39341:         if (PEAR::isError($error)) {
                   39342:             return $error;
                   39343:         }
                   39344: 
                   39345:         $this->_cache = $depdb;
                   39346:         return true;
                   39347:     }
                   39348: 
                   39349:     /**
                   39350:      * Register usage of the dependency DB to prevent race conditions
                   39351:      * @param int one of the LOCK_* constants
                   39352:      * @return true|PEAR_Error
                   39353:      * @access private
                   39354:      */
                   39355:     function _lock($mode = LOCK_EX)
                   39356:     {
                   39357:         if (stristr(php_uname(), 'Windows 9')) {
                   39358:             return true;
                   39359:         }
                   39360: 
                   39361:         if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
                   39362:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   39363:             return true;
                   39364:         }
                   39365: 
                   39366:         $open_mode = 'w';
                   39367:         // XXX People reported problems with LOCK_SH and 'w'
                   39368:         if ($mode === LOCK_SH) {
                   39369:             if (!file_exists($this->_lockfile)) {
                   39370:                 touch($this->_lockfile);
                   39371:             } elseif (!is_file($this->_lockfile)) {
                   39372:                 return PEAR::raiseError('could not create Dependency lock file, ' .
                   39373:                     'it exists and is not a regular file');
                   39374:             }
                   39375:             $open_mode = 'r';
                   39376:         }
                   39377: 
                   39378:         if (!is_resource($this->_lockFp)) {
                   39379:             $this->_lockFp = @fopen($this->_lockfile, $open_mode);
                   39380:         }
                   39381: 
                   39382:         if (!is_resource($this->_lockFp)) {
                   39383:             return PEAR::raiseError("could not create Dependency lock file" .
                   39384:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   39385:         }
                   39386: 
                   39387:         if (!(int)flock($this->_lockFp, $mode)) {
                   39388:             switch ($mode) {
                   39389:                 case LOCK_SH: $str = 'shared';    break;
                   39390:                 case LOCK_EX: $str = 'exclusive'; break;
                   39391:                 case LOCK_UN: $str = 'unlock';    break;
                   39392:                 default:      $str = 'unknown';   break;
                   39393:             }
                   39394: 
                   39395:             return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
                   39396:         }
                   39397: 
                   39398:         return true;
                   39399:     }
                   39400: 
                   39401:     /**
                   39402:      * Release usage of dependency DB
                   39403:      * @return true|PEAR_Error
                   39404:      * @access private
                   39405:      */
                   39406:     function _unlock()
                   39407:     {
                   39408:         $ret = $this->_lock(LOCK_UN);
                   39409:         if (is_resource($this->_lockFp)) {
                   39410:             fclose($this->_lockFp);
                   39411:         }
                   39412:         $this->_lockFp = null;
                   39413:         return $ret;
                   39414:     }
                   39415: 
                   39416:     /**
                   39417:      * Load the dependency database from disk, or return the cache
                   39418:      * @return array|PEAR_Error
                   39419:      */
                   39420:     function _getDepDB()
                   39421:     {
                   39422:         if (!$this->hasWriteAccess()) {
                   39423:             return array('_version' => $this->_version);
                   39424:         }
                   39425: 
                   39426:         if (isset($this->_cache)) {
                   39427:             return $this->_cache;
                   39428:         }
                   39429: 
                   39430:         if (!$fp = fopen($this->_depdb, 'r')) {
                   39431:             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
                   39432:             return $err;
                   39433:         }
                   39434: 
                   39435:         $rt = get_magic_quotes_runtime();
                   39436:         set_magic_quotes_runtime(0);
                   39437:         clearstatcache();
                   39438:         fclose($fp);
                   39439:         $data = unserialize(file_get_contents($this->_depdb));
                   39440:         set_magic_quotes_runtime($rt);
                   39441:         $this->_cache = $data;
                   39442:         return $data;
                   39443:     }
                   39444: 
                   39445:     /**
                   39446:      * Write out the dependency database to disk
                   39447:      * @param array the database
                   39448:      * @return true|PEAR_Error
                   39449:      * @access private
                   39450:      */
                   39451:     function _writeDepDB(&$deps)
                   39452:     {
                   39453:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   39454:             return $e;
                   39455:         }
                   39456: 
                   39457:         if (!$fp = fopen($this->_depdb, 'wb')) {
                   39458:             $this->_unlock();
                   39459:             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
                   39460:         }
                   39461: 
                   39462:         $rt = get_magic_quotes_runtime();
                   39463:         set_magic_quotes_runtime(0);
                   39464:         fwrite($fp, serialize($deps));
                   39465:         set_magic_quotes_runtime($rt);
                   39466:         fclose($fp);
                   39467:         $this->_unlock();
                   39468:         $this->_cache = $deps;
                   39469:         return true;
                   39470:     }
                   39471: 
                   39472:     /**
                   39473:      * Register all dependencies from a package in the dependencies database, in essence
                   39474:      * "installing" the package's dependency information
                   39475:      * @param array the database
                   39476:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   39477:      * @access private
                   39478:      */
                   39479:     function _setPackageDeps(&$data, &$pkg)
                   39480:     {
                   39481:         $pkg->setConfig($this->_config);
                   39482:         if ($pkg->getPackagexmlVersion() == '1.0') {
                   39483:             $gen = &$pkg->getDefaultGenerator();
                   39484:             $deps = $gen->dependenciesToV2();
                   39485:         } else {
                   39486:             $deps = $pkg->getDeps(true);
                   39487:         }
                   39488: 
                   39489:         if (!$deps) {
                   39490:             return;
                   39491:         }
                   39492: 
                   39493:         if (!is_array($data)) {
                   39494:             $data = array();
                   39495:         }
                   39496: 
                   39497:         if (!isset($data['dependencies'])) {
                   39498:             $data['dependencies'] = array();
                   39499:         }
                   39500: 
                   39501:         $channel = strtolower($pkg->getChannel());
                   39502:         $package = strtolower($pkg->getPackage());
                   39503: 
                   39504:         if (!isset($data['dependencies'][$channel])) {
                   39505:             $data['dependencies'][$channel] = array();
                   39506:         }
                   39507: 
                   39508:         $data['dependencies'][$channel][$package] = array();
                   39509:         if (isset($deps['required']['package'])) {
                   39510:             if (!isset($deps['required']['package'][0])) {
                   39511:                 $deps['required']['package'] = array($deps['required']['package']);
                   39512:             }
                   39513: 
                   39514:             foreach ($deps['required']['package'] as $dep) {
                   39515:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   39516:             }
                   39517:         }
                   39518: 
                   39519:         if (isset($deps['optional']['package'])) {
                   39520:             if (!isset($deps['optional']['package'][0])) {
                   39521:                 $deps['optional']['package'] = array($deps['optional']['package']);
                   39522:             }
                   39523: 
                   39524:             foreach ($deps['optional']['package'] as $dep) {
                   39525:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   39526:             }
                   39527:         }
                   39528: 
                   39529:         if (isset($deps['required']['subpackage'])) {
                   39530:             if (!isset($deps['required']['subpackage'][0])) {
                   39531:                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
                   39532:             }
                   39533: 
                   39534:             foreach ($deps['required']['subpackage'] as $dep) {
                   39535:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   39536:             }
                   39537:         }
                   39538: 
                   39539:         if (isset($deps['optional']['subpackage'])) {
                   39540:             if (!isset($deps['optional']['subpackage'][0])) {
                   39541:                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
                   39542:             }
                   39543: 
                   39544:             foreach ($deps['optional']['subpackage'] as $dep) {
                   39545:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   39546:             }
                   39547:         }
                   39548: 
                   39549:         if (isset($deps['group'])) {
                   39550:             if (!isset($deps['group'][0])) {
                   39551:                 $deps['group'] = array($deps['group']);
                   39552:             }
                   39553: 
                   39554:             foreach ($deps['group'] as $group) {
                   39555:                 if (isset($group['package'])) {
                   39556:                     if (!isset($group['package'][0])) {
                   39557:                         $group['package'] = array($group['package']);
                   39558:                     }
                   39559: 
                   39560:                     foreach ($group['package'] as $dep) {
                   39561:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   39562:                             $group['attribs']['name']);
                   39563:                     }
                   39564:                 }
                   39565: 
                   39566:                 if (isset($group['subpackage'])) {
                   39567:                     if (!isset($group['subpackage'][0])) {
                   39568:                         $group['subpackage'] = array($group['subpackage']);
                   39569:                     }
                   39570: 
                   39571:                     foreach ($group['subpackage'] as $dep) {
                   39572:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   39573:                             $group['attribs']['name']);
                   39574:                     }
                   39575:                 }
                   39576:             }
                   39577:         }
                   39578: 
                   39579:         if ($data['dependencies'][$channel][$package] == array()) {
                   39580:             unset($data['dependencies'][$channel][$package]);
                   39581:             if (!count($data['dependencies'][$channel])) {
                   39582:                 unset($data['dependencies'][$channel]);
                   39583:             }
                   39584:         }
                   39585:     }
                   39586: 
                   39587:     /**
                   39588:      * @param array the database
                   39589:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   39590:      * @param array the specific dependency
                   39591:      * @param required|optional whether this is a required or an optional dep
                   39592:      * @param string|false dependency group this dependency is from, or false for ordinary dep
                   39593:      */
                   39594:     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
                   39595:     {
                   39596:         $info = array(
                   39597:             'dep'   => $dep,
                   39598:             'type'  => $type,
                   39599:             'group' => $group
                   39600:         );
                   39601: 
                   39602:         $dep  = array_map('strtolower', $dep);
                   39603:         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   39604:         if (!isset($data['dependencies'])) {
                   39605:             $data['dependencies'] = array();
                   39606:         }
                   39607: 
                   39608:         $channel = strtolower($pkg->getChannel());
                   39609:         $package = strtolower($pkg->getPackage());
                   39610: 
                   39611:         if (!isset($data['dependencies'][$channel])) {
                   39612:             $data['dependencies'][$channel] = array();
                   39613:         }
                   39614: 
                   39615:         if (!isset($data['dependencies'][$channel][$package])) {
                   39616:             $data['dependencies'][$channel][$package] = array();
                   39617:         }
                   39618: 
                   39619:         $data['dependencies'][$channel][$package][] = $info;
                   39620:         if (isset($data['packages'][$depchannel][$dep['name']])) {
                   39621:             $found = false;
                   39622:             foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
                   39623:                 if ($p['channel'] == $channel && $p['package'] == $package) {
                   39624:                     $found = true;
                   39625:                     break;
                   39626:                 }
                   39627:             }
                   39628:         } else {
                   39629:             if (!isset($data['packages'])) {
                   39630:                 $data['packages'] = array();
                   39631:             }
                   39632: 
                   39633:             if (!isset($data['packages'][$depchannel])) {
                   39634:                 $data['packages'][$depchannel] = array();
                   39635:             }
                   39636: 
                   39637:             if (!isset($data['packages'][$depchannel][$dep['name']])) {
                   39638:                 $data['packages'][$depchannel][$dep['name']] = array();
                   39639:             }
                   39640: 
                   39641:             $found = false;
                   39642:         }
                   39643: 
                   39644:         if (!$found) {
                   39645:             $data['packages'][$depchannel][$dep['name']][] = array(
                   39646:                 'channel' => $channel,
                   39647:                 'package' => $package
                   39648:             );
                   39649:         }
                   39650:     }
                   39651: }PEAR-1.9.4/PEAR/Dependency2.php0000644000076500000240000014251711605156760014650 0ustar  helgistaff<?php
                   39652: /**
                   39653:  * PEAR_Dependency2, advanced dependency validation
                   39654:  *
                   39655:  * PHP versions 4 and 5
                   39656:  *
                   39657:  * @category   pear
                   39658:  * @package    PEAR
                   39659:  * @author     Greg Beaver <cellog@php.net>
                   39660:  * @copyright  1997-2009 The Authors
                   39661:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39662:  * @version    CVS: $Id: Dependency2.php 313023 2011-07-06 19:17:11Z dufuz $
                   39663:  * @link       http://pear.php.net/package/PEAR
                   39664:  * @since      File available since Release 1.4.0a1
                   39665:  */
                   39666: 
                   39667: /**
                   39668:  * Required for the PEAR_VALIDATE_* constants
                   39669:  */
                   39670: require_once 'PEAR/Validate.php';
                   39671: 
                   39672: /**
                   39673:  * Dependency check for PEAR packages
                   39674:  *
                   39675:  * This class handles both version 1.0 and 2.0 dependencies
                   39676:  * WARNING: *any* changes to this class must be duplicated in the
                   39677:  * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
                   39678:  * or unit tests will not actually validate the changes
                   39679:  * @category   pear
                   39680:  * @package    PEAR
                   39681:  * @author     Greg Beaver <cellog@php.net>
                   39682:  * @copyright  1997-2009 The Authors
                   39683:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39684:  * @version    Release: 1.9.4
                   39685:  * @link       http://pear.php.net/package/PEAR
                   39686:  * @since      Class available since Release 1.4.0a1
                   39687:  */
                   39688: class PEAR_Dependency2
                   39689: {
                   39690:     /**
                   39691:      * One of the PEAR_VALIDATE_* states
                   39692:      * @see PEAR_VALIDATE_NORMAL
                   39693:      * @var integer
                   39694:      */
                   39695:     var $_state;
                   39696: 
                   39697:     /**
                   39698:      * Command-line options to install/upgrade/uninstall commands
                   39699:      * @param array
                   39700:      */
                   39701:     var $_options;
                   39702: 
                   39703:     /**
                   39704:      * @var OS_Guess
                   39705:      */
                   39706:     var $_os;
                   39707: 
                   39708:     /**
                   39709:      * @var PEAR_Registry
                   39710:      */
                   39711:     var $_registry;
                   39712: 
                   39713:     /**
                   39714:      * @var PEAR_Config
                   39715:      */
                   39716:     var $_config;
                   39717: 
                   39718:     /**
                   39719:      * @var PEAR_DependencyDB
                   39720:      */
                   39721:     var $_dependencydb;
                   39722: 
                   39723:     /**
                   39724:      * Output of PEAR_Registry::parsedPackageName()
                   39725:      * @var array
                   39726:      */
                   39727:     var $_currentPackage;
                   39728: 
                   39729:     /**
                   39730:      * @param PEAR_Config
                   39731:      * @param array installation options
                   39732:      * @param array format of PEAR_Registry::parsedPackageName()
                   39733:      * @param int installation state (one of PEAR_VALIDATE_*)
                   39734:      */
                   39735:     function PEAR_Dependency2(&$config, $installoptions, $package,
                   39736:                               $state = PEAR_VALIDATE_INSTALLING)
                   39737:     {
                   39738:         $this->_config = &$config;
                   39739:         if (!class_exists('PEAR_DependencyDB')) {
                   39740:             require_once 'PEAR/DependencyDB.php';
                   39741:         }
                   39742: 
                   39743:         if (isset($installoptions['packagingroot'])) {
                   39744:             // make sure depdb is in the right location
                   39745:             $config->setInstallRoot($installoptions['packagingroot']);
                   39746:         }
                   39747: 
                   39748:         $this->_registry = &$config->getRegistry();
                   39749:         $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
                   39750:         if (isset($installoptions['packagingroot'])) {
                   39751:             $config->setInstallRoot(false);
                   39752:         }
                   39753: 
                   39754:         $this->_options = $installoptions;
                   39755:         $this->_state = $state;
                   39756:         if (!class_exists('OS_Guess')) {
                   39757:             require_once 'OS/Guess.php';
                   39758:         }
                   39759: 
                   39760:         $this->_os = new OS_Guess;
                   39761:         $this->_currentPackage = $package;
                   39762:     }
                   39763: 
                   39764:     function _getExtraString($dep)
                   39765:     {
                   39766:         $extra = ' (';
                   39767:         if (isset($dep['uri'])) {
                   39768:             return '';
                   39769:         }
                   39770: 
                   39771:         if (isset($dep['recommended'])) {
                   39772:             $extra .= 'recommended version ' . $dep['recommended'];
                   39773:         } else {
                   39774:             if (isset($dep['min'])) {
                   39775:                 $extra .= 'version >= ' . $dep['min'];
                   39776:             }
                   39777: 
                   39778:             if (isset($dep['max'])) {
                   39779:                 if ($extra != ' (') {
                   39780:                     $extra .= ', ';
                   39781:                 }
                   39782:                 $extra .= 'version <= ' . $dep['max'];
                   39783:             }
                   39784: 
                   39785:             if (isset($dep['exclude'])) {
                   39786:                 if (!is_array($dep['exclude'])) {
                   39787:                     $dep['exclude'] = array($dep['exclude']);
                   39788:                 }
                   39789: 
                   39790:                 if ($extra != ' (') {
                   39791:                     $extra .= ', ';
                   39792:                 }
                   39793: 
                   39794:                 $extra .= 'excluded versions: ';
                   39795:                 foreach ($dep['exclude'] as $i => $exclude) {
                   39796:                     if ($i) {
                   39797:                         $extra .= ', ';
                   39798:                     }
                   39799:                     $extra .= $exclude;
                   39800:                 }
                   39801:             }
                   39802:         }
                   39803: 
                   39804:         $extra .= ')';
                   39805:         if ($extra == ' ()') {
                   39806:             $extra = '';
                   39807:         }
                   39808: 
                   39809:         return $extra;
                   39810:     }
                   39811: 
                   39812:     /**
                   39813:      * This makes unit-testing a heck of a lot easier
                   39814:      */
                   39815:     function getPHP_OS()
                   39816:     {
                   39817:         return PHP_OS;
                   39818:     }
                   39819: 
                   39820:     /**
                   39821:      * This makes unit-testing a heck of a lot easier
                   39822:      */
                   39823:     function getsysname()
                   39824:     {
                   39825:         return $this->_os->getSysname();
                   39826:     }
                   39827: 
                   39828:     /**
                   39829:      * Specify a dependency on an OS.  Use arch for detailed os/processor information
                   39830:      *
                   39831:      * There are two generic OS dependencies that will be the most common, unix and windows.
                   39832:      * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
                   39833:      */
                   39834:     function validateOsDependency($dep)
                   39835:     {
                   39836:         if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   39837:             return true;
                   39838:         }
                   39839: 
                   39840:         if ($dep['name'] == '*') {
                   39841:             return true;
                   39842:         }
                   39843: 
                   39844:         $not = isset($dep['conflicts']) ? true : false;
                   39845:         switch (strtolower($dep['name'])) {
                   39846:             case 'windows' :
                   39847:                 if ($not) {
                   39848:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
                   39849:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39850:                             return $this->raiseError("Cannot install %s on Windows");
                   39851:                         }
                   39852: 
                   39853:                         return $this->warning("warning: Cannot install %s on Windows");
                   39854:                     }
                   39855:                 } else {
                   39856:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
                   39857:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39858:                             return $this->raiseError("Can only install %s on Windows");
                   39859:                         }
                   39860: 
                   39861:                         return $this->warning("warning: Can only install %s on Windows");
                   39862:                     }
                   39863:                 }
                   39864:             break;
                   39865:             case 'unix' :
                   39866:                 $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
                   39867:                 if ($not) {
                   39868:                     if (in_array($this->getSysname(), $unices)) {
                   39869:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39870:                             return $this->raiseError("Cannot install %s on any Unix system");
                   39871:                         }
                   39872: 
                   39873:                         return $this->warning( "warning: Cannot install %s on any Unix system");
                   39874:                     }
                   39875:                 } else {
                   39876:                     if (!in_array($this->getSysname(), $unices)) {
                   39877:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39878:                             return $this->raiseError("Can only install %s on a Unix system");
                   39879:                         }
                   39880: 
                   39881:                         return $this->warning("warning: Can only install %s on a Unix system");
                   39882:                     }
                   39883:                 }
                   39884:             break;
                   39885:             default :
                   39886:                 if ($not) {
                   39887:                     if (strtolower($dep['name']) == strtolower($this->getSysname())) {
                   39888:                         if (!isset($this->_options['nodeps']) &&
                   39889:                               !isset($this->_options['force'])) {
                   39890:                             return $this->raiseError('Cannot install %s on ' . $dep['name'] .
                   39891:                                 ' operating system');
                   39892:                         }
                   39893: 
                   39894:                         return $this->warning('warning: Cannot install %s on ' .
                   39895:                             $dep['name'] . ' operating system');
                   39896:                     }
                   39897:                 } else {
                   39898:                     if (strtolower($dep['name']) != strtolower($this->getSysname())) {
                   39899:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39900:                             return $this->raiseError('Cannot install %s on ' .
                   39901:                                 $this->getSysname() .
                   39902:                                 ' operating system, can only install on ' . $dep['name']);
                   39903:                         }
                   39904: 
                   39905:                         return $this->warning('warning: Cannot install %s on ' .
                   39906:                             $this->getSysname() .
                   39907:                             ' operating system, can only install on ' . $dep['name']);
                   39908:                     }
                   39909:                 }
                   39910:         }
                   39911:         return true;
                   39912:     }
                   39913: 
                   39914:     /**
                   39915:      * This makes unit-testing a heck of a lot easier
                   39916:      */
                   39917:     function matchSignature($pattern)
                   39918:     {
                   39919:         return $this->_os->matchSignature($pattern);
                   39920:     }
                   39921: 
                   39922:     /**
                   39923:      * Specify a complex dependency on an OS/processor/kernel version,
                   39924:      * Use OS for simple operating system dependency.
                   39925:      *
                   39926:      * This is the only dependency that accepts an eregable pattern.  The pattern
                   39927:      * will be matched against the php_uname() output parsed by OS_Guess
                   39928:      */
                   39929:     function validateArchDependency($dep)
                   39930:     {
                   39931:         if ($this->_state != PEAR_VALIDATE_INSTALLING) {
                   39932:             return true;
                   39933:         }
                   39934: 
                   39935:         $not = isset($dep['conflicts']) ? true : false;
                   39936:         if (!$this->matchSignature($dep['pattern'])) {
                   39937:             if (!$not) {
                   39938:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39939:                     return $this->raiseError('%s Architecture dependency failed, does not ' .
                   39940:                         'match "' . $dep['pattern'] . '"');
                   39941:                 }
                   39942: 
                   39943:                 return $this->warning('warning: %s Architecture dependency failed, does ' .
                   39944:                     'not match "' . $dep['pattern'] . '"');
                   39945:             }
                   39946: 
                   39947:             return true;
                   39948:         }
                   39949: 
                   39950:         if ($not) {
                   39951:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   39952:                 return $this->raiseError('%s Architecture dependency failed, required "' .
                   39953:                     $dep['pattern'] . '"');
                   39954:             }
                   39955: 
                   39956:             return $this->warning('warning: %s Architecture dependency failed, ' .
                   39957:                 'required "' . $dep['pattern'] . '"');
                   39958:         }
                   39959: 
                   39960:         return true;
                   39961:     }
                   39962: 
                   39963:     /**
                   39964:      * This makes unit-testing a heck of a lot easier
                   39965:      */
                   39966:     function extension_loaded($name)
                   39967:     {
                   39968:         return extension_loaded($name);
                   39969:     }
                   39970: 
                   39971:     /**
                   39972:      * This makes unit-testing a heck of a lot easier
                   39973:      */
                   39974:     function phpversion($name = null)
                   39975:     {
                   39976:         if ($name !== null) {
                   39977:             return phpversion($name);
                   39978:         }
                   39979: 
                   39980:         return phpversion();
                   39981:     }
                   39982: 
                   39983:     function validateExtensionDependency($dep, $required = true)
                   39984:     {
                   39985:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   39986:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   39987:             return true;
                   39988:         }
                   39989: 
                   39990:         $loaded = $this->extension_loaded($dep['name']);
                   39991:         $extra  = $this->_getExtraString($dep);
                   39992:         if (isset($dep['exclude'])) {
                   39993:             if (!is_array($dep['exclude'])) {
                   39994:                 $dep['exclude'] = array($dep['exclude']);
                   39995:             }
                   39996:         }
                   39997: 
                   39998:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   39999:             !isset($dep['recommended']) && !isset($dep['exclude'])
                   40000:         ) {
                   40001:             if ($loaded) {
                   40002:                 if (isset($dep['conflicts'])) {
                   40003:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40004:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   40005:                             $dep['name'] . '"' . $extra);
                   40006:                     }
                   40007: 
                   40008:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   40009:                         $dep['name'] . '"' . $extra);
                   40010:                 }
                   40011: 
                   40012:                 return true;
                   40013:             }
                   40014: 
                   40015:             if (isset($dep['conflicts'])) {
                   40016:                 return true;
                   40017:             }
                   40018: 
                   40019:             if ($required) {
                   40020:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40021:                     return $this->raiseError('%s requires PHP extension "' .
                   40022:                         $dep['name'] . '"' . $extra);
                   40023:                 }
                   40024: 
                   40025:                 return $this->warning('warning: %s requires PHP extension "' .
                   40026:                     $dep['name'] . '"' . $extra);
                   40027:             }
                   40028: 
                   40029:             return $this->warning('%s can optionally use PHP extension "' .
                   40030:                 $dep['name'] . '"' . $extra);
                   40031:         }
                   40032: 
                   40033:         if (!$loaded) {
                   40034:             if (isset($dep['conflicts'])) {
                   40035:                 return true;
                   40036:             }
                   40037: 
                   40038:             if (!$required) {
                   40039:                 return $this->warning('%s can optionally use PHP extension "' .
                   40040:                     $dep['name'] . '"' . $extra);
                   40041:             }
                   40042: 
                   40043:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40044:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   40045:                     '"' . $extra);
                   40046:             }
                   40047: 
                   40048:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   40049:                     '"' . $extra);
                   40050:         }
                   40051: 
                   40052:         $version = (string) $this->phpversion($dep['name']);
                   40053:         if (empty($version)) {
                   40054:             $version = '0';
                   40055:         }
                   40056: 
                   40057:         $fail = false;
                   40058:         if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
                   40059:             $fail = true;
                   40060:         }
                   40061: 
                   40062:         if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
                   40063:             $fail = true;
                   40064:         }
                   40065: 
                   40066:         if ($fail && !isset($dep['conflicts'])) {
                   40067:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40068:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   40069:                     '"' . $extra . ', installed version is ' . $version);
                   40070:             }
                   40071: 
                   40072:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   40073:                 '"' . $extra . ', installed version is ' . $version);
                   40074:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
                   40075:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40076:                 return $this->raiseError('%s conflicts with PHP extension "' .
                   40077:                     $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40078:             }
                   40079: 
                   40080:             return $this->warning('warning: %s conflicts with PHP extension "' .
                   40081:                 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40082:         }
                   40083: 
                   40084:         if (isset($dep['exclude'])) {
                   40085:             foreach ($dep['exclude'] as $exclude) {
                   40086:                 if (version_compare($version, $exclude, '==')) {
                   40087:                     if (isset($dep['conflicts'])) {
                   40088:                         continue;
                   40089:                     }
                   40090: 
                   40091:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40092:                         return $this->raiseError('%s is not compatible with PHP extension "' .
                   40093:                             $dep['name'] . '" version ' .
                   40094:                             $exclude);
                   40095:                     }
                   40096: 
                   40097:                     return $this->warning('warning: %s is not compatible with PHP extension "' .
                   40098:                         $dep['name'] . '" version ' .
                   40099:                         $exclude);
                   40100:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   40101:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40102:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   40103:                             $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40104:                     }
                   40105: 
                   40106:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   40107:                         $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40108:                 }
                   40109:             }
                   40110:         }
                   40111: 
                   40112:         if (isset($dep['recommended'])) {
                   40113:             if (version_compare($version, $dep['recommended'], '==')) {
                   40114:                 return true;
                   40115:             }
                   40116: 
                   40117:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40118:                 return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
                   40119:                     ' version "' . $version . '"' .
                   40120:                     ' is not the recommended version "' . $dep['recommended'] .
                   40121:                     '", but may be compatible, use --force to install');
                   40122:             }
                   40123: 
                   40124:             return $this->warning('warning: %s dependency: PHP extension ' .
                   40125:                 $dep['name'] . ' version "' . $version . '"' .
                   40126:                 ' is not the recommended version "' . $dep['recommended'].'"');
                   40127:         }
                   40128: 
                   40129:         return true;
                   40130:     }
                   40131: 
                   40132:     function validatePhpDependency($dep)
                   40133:     {
                   40134:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   40135:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40136:             return true;
                   40137:         }
                   40138: 
                   40139:         $version = $this->phpversion();
                   40140:         $extra   = $this->_getExtraString($dep);
                   40141:         if (isset($dep['exclude'])) {
                   40142:             if (!is_array($dep['exclude'])) {
                   40143:                 $dep['exclude'] = array($dep['exclude']);
                   40144:             }
                   40145:         }
                   40146: 
                   40147:         if (isset($dep['min'])) {
                   40148:             if (!version_compare($version, $dep['min'], '>=')) {
                   40149:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40150:                     return $this->raiseError('%s requires PHP' .
                   40151:                         $extra . ', installed version is ' . $version);
                   40152:                 }
                   40153: 
                   40154:                 return $this->warning('warning: %s requires PHP' .
                   40155:                     $extra . ', installed version is ' . $version);
                   40156:             }
                   40157:         }
                   40158: 
                   40159:         if (isset($dep['max'])) {
                   40160:             if (!version_compare($version, $dep['max'], '<=')) {
                   40161:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40162:                     return $this->raiseError('%s requires PHP' .
                   40163:                         $extra . ', installed version is ' . $version);
                   40164:                 }
                   40165: 
                   40166:                 return $this->warning('warning: %s requires PHP' .
                   40167:                     $extra . ', installed version is ' . $version);
                   40168:             }
                   40169:         }
                   40170: 
                   40171:         if (isset($dep['exclude'])) {
                   40172:             foreach ($dep['exclude'] as $exclude) {
                   40173:                 if (version_compare($version, $exclude, '==')) {
                   40174:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40175:                         return $this->raiseError('%s is not compatible with PHP version ' .
                   40176:                             $exclude);
                   40177:                     }
                   40178: 
                   40179:                     return $this->warning(
                   40180:                         'warning: %s is not compatible with PHP version ' .
                   40181:                         $exclude);
                   40182:                 }
                   40183:             }
                   40184:         }
                   40185: 
                   40186:         return true;
                   40187:     }
                   40188: 
                   40189:     /**
                   40190:      * This makes unit-testing a heck of a lot easier
                   40191:      */
                   40192:     function getPEARVersion()
                   40193:     {
                   40194:         return '1.9.4';
                   40195:     }
                   40196: 
                   40197:     function validatePearinstallerDependency($dep)
                   40198:     {
                   40199:         $pearversion = $this->getPEARVersion();
                   40200:         $extra = $this->_getExtraString($dep);
                   40201:         if (isset($dep['exclude'])) {
                   40202:             if (!is_array($dep['exclude'])) {
                   40203:                 $dep['exclude'] = array($dep['exclude']);
                   40204:             }
                   40205:         }
                   40206: 
                   40207:         if (version_compare($pearversion, $dep['min'], '<')) {
                   40208:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40209:                 return $this->raiseError('%s requires PEAR Installer' . $extra .
                   40210:                     ', installed version is ' . $pearversion);
                   40211:             }
                   40212: 
                   40213:             return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   40214:                 ', installed version is ' . $pearversion);
                   40215:         }
                   40216: 
                   40217:         if (isset($dep['max'])) {
                   40218:             if (version_compare($pearversion, $dep['max'], '>')) {
                   40219:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40220:                     return $this->raiseError('%s requires PEAR Installer' . $extra .
                   40221:                         ', installed version is ' . $pearversion);
                   40222:                 }
                   40223: 
                   40224:                 return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   40225:                     ', installed version is ' . $pearversion);
                   40226:             }
                   40227:         }
                   40228: 
                   40229:         if (isset($dep['exclude'])) {
                   40230:             if (!isset($dep['exclude'][0])) {
                   40231:                 $dep['exclude'] = array($dep['exclude']);
                   40232:             }
                   40233: 
                   40234:             foreach ($dep['exclude'] as $exclude) {
                   40235:                 if (version_compare($exclude, $pearversion, '==')) {
                   40236:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40237:                         return $this->raiseError('%s is not compatible with PEAR Installer ' .
                   40238:                             'version ' . $exclude);
                   40239:                     }
                   40240: 
                   40241:                     return $this->warning('warning: %s is not compatible with PEAR ' .
                   40242:                         'Installer version ' . $exclude);
                   40243:                 }
                   40244:             }
                   40245:         }
                   40246: 
                   40247:         return true;
                   40248:     }
                   40249: 
                   40250:     function validateSubpackageDependency($dep, $required, $params)
                   40251:     {
                   40252:         return $this->validatePackageDependency($dep, $required, $params);
                   40253:     }
                   40254: 
                   40255:     /**
                   40256:      * @param array dependency information (2.0 format)
                   40257:      * @param boolean whether this is a required dependency
                   40258:      * @param array a list of downloaded packages to be installed, if any
                   40259:      * @param boolean if true, then deps on pear.php.net that fail will also check
                   40260:      *                against pecl.php.net packages to accomodate extensions that have
                   40261:      *                moved to pecl.php.net from pear.php.net
                   40262:      */
                   40263:     function validatePackageDependency($dep, $required, $params, $depv1 = false)
                   40264:     {
                   40265:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   40266:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40267:             return true;
                   40268:         }
                   40269: 
                   40270:         if (isset($dep['providesextension'])) {
                   40271:             if ($this->extension_loaded($dep['providesextension'])) {
                   40272:                 $save = $dep;
                   40273:                 $subdep = $dep;
                   40274:                 $subdep['name'] = $subdep['providesextension'];
                   40275:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   40276:                 $ret = $this->validateExtensionDependency($subdep, $required);
                   40277:                 PEAR::popErrorHandling();
                   40278:                 if (!PEAR::isError($ret)) {
                   40279:                     return true;
                   40280:                 }
                   40281:             }
                   40282:         }
                   40283: 
                   40284:         if ($this->_state == PEAR_VALIDATE_INSTALLING) {
                   40285:             return $this->_validatePackageInstall($dep, $required, $depv1);
                   40286:         }
                   40287: 
                   40288:         if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
                   40289:             return $this->_validatePackageDownload($dep, $required, $params, $depv1);
                   40290:         }
                   40291:     }
                   40292: 
                   40293:     function _validatePackageDownload($dep, $required, $params, $depv1 = false)
                   40294:     {
                   40295:         $dep['package'] = $dep['name'];
                   40296:         if (isset($dep['uri'])) {
                   40297:             $dep['channel'] = '__uri';
                   40298:         }
                   40299: 
                   40300:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   40301:         $found = false;
                   40302:         foreach ($params as $param) {
                   40303:             if ($param->isEqual(
                   40304:                   array('package' => $dep['name'],
                   40305:                         'channel' => $dep['channel']))) {
                   40306:                 $found = true;
                   40307:                 break;
                   40308:             }
                   40309: 
                   40310:             if ($depv1 && $dep['channel'] == 'pear.php.net') {
                   40311:                 if ($param->isEqual(
                   40312:                   array('package' => $dep['name'],
                   40313:                         'channel' => 'pecl.php.net'))) {
                   40314:                     $found = true;
                   40315:                     break;
                   40316:                 }
                   40317:             }
                   40318:         }
                   40319: 
                   40320:         if (!$found && isset($dep['providesextension'])) {
                   40321:             foreach ($params as $param) {
                   40322:                 if ($param->isExtension($dep['providesextension'])) {
                   40323:                     $found = true;
                   40324:                     break;
                   40325:                 }
                   40326:             }
                   40327:         }
                   40328: 
                   40329:         if ($found) {
                   40330:             $version = $param->getVersion();
                   40331:             $installed = false;
                   40332:             $downloaded = true;
                   40333:         } else {
                   40334:             if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
                   40335:                 $installed = true;
                   40336:                 $downloaded = false;
                   40337:                 $version = $this->_registry->packageinfo($dep['name'], 'version',
                   40338:                     $dep['channel']);
                   40339:             } else {
                   40340:                 if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
                   40341:                       'pear.php.net')) {
                   40342:                     $installed = true;
                   40343:                     $downloaded = false;
                   40344:                     $version = $this->_registry->packageinfo($dep['name'], 'version',
                   40345:                         'pear.php.net');
                   40346:                 } else {
                   40347:                     $version = 'not installed or downloaded';
                   40348:                     $installed = false;
                   40349:                     $downloaded = false;
                   40350:                 }
                   40351:             }
                   40352:         }
                   40353: 
                   40354:         $extra = $this->_getExtraString($dep);
                   40355:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   40356:             $dep['exclude'] = array($dep['exclude']);
                   40357:         }
                   40358: 
                   40359:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   40360:               !isset($dep['recommended']) && !isset($dep['exclude'])
                   40361:         ) {
                   40362:             if ($installed || $downloaded) {
                   40363:                 $installed = $installed ? 'installed' : 'downloaded';
                   40364:                 if (isset($dep['conflicts'])) {
                   40365:                     $rest = '';
                   40366:                     if ($version) {
                   40367:                         $rest = ", $installed version is " . $version;
                   40368:                     }
                   40369: 
                   40370:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40371:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
                   40372:                     }
                   40373: 
                   40374:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
                   40375:                 }
                   40376: 
                   40377:                 return true;
                   40378:             }
                   40379: 
                   40380:             if (isset($dep['conflicts'])) {
                   40381:                 return true;
                   40382:             }
                   40383: 
                   40384:             if ($required) {
                   40385:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40386:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   40387:                 }
                   40388: 
                   40389:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   40390:             }
                   40391: 
                   40392:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   40393:         }
                   40394: 
                   40395:         if (!$installed && !$downloaded) {
                   40396:             if (isset($dep['conflicts'])) {
                   40397:                 return true;
                   40398:             }
                   40399: 
                   40400:             if ($required) {
                   40401:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40402:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   40403:                 }
                   40404: 
                   40405:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   40406:             }
                   40407: 
                   40408:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   40409:         }
                   40410: 
                   40411:         $fail = false;
                   40412:         if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
                   40413:             $fail = true;
                   40414:         }
                   40415: 
                   40416:         if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
                   40417:             $fail = true;
                   40418:         }
                   40419: 
                   40420:         if ($fail && !isset($dep['conflicts'])) {
                   40421:             $installed = $installed ? 'installed' : 'downloaded';
                   40422:             $dep['package'] = $dep['name'];
                   40423:             $dep = $this->_registry->parsedPackageNameToString($dep, true);
                   40424:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40425:                 return $this->raiseError('%s requires package "' . $depname . '"' .
                   40426:                     $extra . ", $installed version is " . $version);
                   40427:             }
                   40428: 
                   40429:             return $this->warning('warning: %s requires package "' . $depname . '"' .
                   40430:                 $extra . ", $installed version is " . $version);
                   40431:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
                   40432:               isset($dep['conflicts']) && !isset($dep['exclude'])) {
                   40433:             $installed = $installed ? 'installed' : 'downloaded';
                   40434:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40435:                 return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
                   40436:                     ", $installed version is " . $version);
                   40437:             }
                   40438: 
                   40439:             return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   40440:                 $extra . ", $installed version is " . $version);
                   40441:         }
                   40442: 
                   40443:         if (isset($dep['exclude'])) {
                   40444:             $installed = $installed ? 'installed' : 'downloaded';
                   40445:             foreach ($dep['exclude'] as $exclude) {
                   40446:                 if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
                   40447:                     if (!isset($this->_options['nodeps']) &&
                   40448:                           !isset($this->_options['force'])
                   40449:                     ) {
                   40450:                         return $this->raiseError('%s is not compatible with ' .
                   40451:                             $installed . ' package "' .
                   40452:                             $depname . '" version ' .
                   40453:                             $exclude);
                   40454:                     }
                   40455: 
                   40456:                     return $this->warning('warning: %s is not compatible with ' .
                   40457:                         $installed . ' package "' .
                   40458:                         $depname . '" version ' .
                   40459:                         $exclude);
                   40460:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   40461:                     $installed = $installed ? 'installed' : 'downloaded';
                   40462:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40463:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' .
                   40464:                             $extra . ", $installed version is " . $version);
                   40465:                     }
                   40466: 
                   40467:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   40468:                         $extra . ", $installed version is " . $version);
                   40469:                 }
                   40470:             }
                   40471:         }
                   40472: 
                   40473:         if (isset($dep['recommended'])) {
                   40474:             $installed = $installed ? 'installed' : 'downloaded';
                   40475:             if (version_compare($version, $dep['recommended'], '==')) {
                   40476:                 return true;
                   40477:             }
                   40478: 
                   40479:             if (!$found && $installed) {
                   40480:                 $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
                   40481:             }
                   40482: 
                   40483:             if ($param) {
                   40484:                 $found = false;
                   40485:                 foreach ($params as $parent) {
                   40486:                     if ($parent->isEqual($this->_currentPackage)) {
                   40487:                         $found = true;
                   40488:                         break;
                   40489:                     }
                   40490:                 }
                   40491: 
                   40492:                 if ($found) {
                   40493:                     if ($param->isCompatible($parent)) {
                   40494:                         return true;
                   40495:                     }
                   40496:                 } else { // this is for validPackage() calls
                   40497:                     $parent = $this->_registry->getPackage($this->_currentPackage['package'],
                   40498:                         $this->_currentPackage['channel']);
                   40499:                     if ($parent !== null && $param->isCompatible($parent)) {
                   40500:                         return true;
                   40501:                     }
                   40502:                 }
                   40503:             }
                   40504: 
                   40505:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
                   40506:                   !isset($this->_options['loose'])
                   40507:             ) {
                   40508:                 return $this->raiseError('%s dependency package "' . $depname .
                   40509:                     '" ' . $installed . ' version ' . $version .
                   40510:                     ' is not the recommended version ' . $dep['recommended'] .
                   40511:                     ', but may be compatible, use --force to install');
                   40512:             }
                   40513: 
                   40514:             return $this->warning('warning: %s dependency package "' . $depname .
                   40515:                 '" ' . $installed . ' version ' . $version .
                   40516:                 ' is not the recommended version ' . $dep['recommended']);
                   40517:         }
                   40518: 
                   40519:         return true;
                   40520:     }
                   40521: 
                   40522:     function _validatePackageInstall($dep, $required, $depv1 = false)
                   40523:     {
                   40524:         return $this->_validatePackageDownload($dep, $required, array(), $depv1);
                   40525:     }
                   40526: 
                   40527:     /**
                   40528:      * Verify that uninstalling packages passed in to command line is OK.
                   40529:      *
                   40530:      * @param PEAR_Installer $dl
                   40531:      * @return PEAR_Error|true
                   40532:      */
                   40533:     function validatePackageUninstall(&$dl)
                   40534:     {
                   40535:         if (PEAR::isError($this->_dependencydb)) {
                   40536:             return $this->_dependencydb;
                   40537:         }
                   40538: 
                   40539:         $params = array();
                   40540:         // construct an array of "downloaded" packages to fool the package dependency checker
                   40541:         // into using these to validate uninstalls of circular dependencies
                   40542:         $downloaded = &$dl->getUninstallPackages();
                   40543:         foreach ($downloaded as $i => $pf) {
                   40544:             if (!class_exists('PEAR_Downloader_Package')) {
                   40545:                 require_once 'PEAR/Downloader/Package.php';
                   40546:             }
                   40547:             $dp = &new PEAR_Downloader_Package($dl);
                   40548:             $dp->setPackageFile($downloaded[$i]);
                   40549:             $params[$i] = &$dp;
                   40550:         }
                   40551: 
                   40552:         // check cache
                   40553:         $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
                   40554:             strtolower($this->_currentPackage['package']);
                   40555:         if (isset($dl->___uninstall_package_cache)) {
                   40556:             $badpackages = $dl->___uninstall_package_cache;
                   40557:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   40558:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   40559:                     $dl->log(0, $warning[0]);
                   40560:                 }
                   40561:             }
                   40562: 
                   40563:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   40564:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   40565:                     if (is_array($error)) {
                   40566:                         $dl->log(0, $error[0]);
                   40567:                     } else {
                   40568:                         $dl->log(0, $error->getMessage());
                   40569:                     }
                   40570:                 }
                   40571: 
                   40572:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   40573:                     return $this->warning(
                   40574:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   40575:                         'on this package');
                   40576:                 }
                   40577: 
                   40578:                 return $this->raiseError(
                   40579:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   40580:             }
                   40581: 
                   40582:             return true;
                   40583:         }
                   40584: 
                   40585:         // first, list the immediate parents of each package to be uninstalled
                   40586:         $perpackagelist = array();
                   40587:         $allparents = array();
                   40588:         foreach ($params as $i => $param) {
                   40589:             $a = array(
                   40590:                 'channel' => strtolower($param->getChannel()),
                   40591:                 'package' => strtolower($param->getPackage())
                   40592:             );
                   40593: 
                   40594:             $deps = $this->_dependencydb->getDependentPackages($a);
                   40595:             if ($deps) {
                   40596:                 foreach ($deps as $d) {
                   40597:                     $pardeps = $this->_dependencydb->getDependencies($d);
                   40598:                     foreach ($pardeps as $dep) {
                   40599:                         if (strtolower($dep['dep']['channel']) == $a['channel'] &&
                   40600:                               strtolower($dep['dep']['name']) == $a['package']) {
                   40601:                             if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
                   40602:                                 $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
                   40603:                             }
                   40604:                             $perpackagelist[$a['channel'] . '/' . $a['package']][]
                   40605:                                 = array($d['channel'] . '/' . $d['package'], $dep);
                   40606:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
                   40607:                                 $allparents[$d['channel'] . '/' . $d['package']] = array();
                   40608:                             }
                   40609:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
                   40610:                                 $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
                   40611:                             }
                   40612:                             $allparents[$d['channel'] . '/' . $d['package']]
                   40613:                                        [$a['channel'] . '/' . $a['package']][]
                   40614:                                 = array($d, $dep);
                   40615:                         }
                   40616:                     }
                   40617:                 }
                   40618:             }
                   40619:         }
                   40620: 
                   40621:         // next, remove any packages from the parents list that are not installed
                   40622:         $remove = array();
                   40623:         foreach ($allparents as $parent => $d1) {
                   40624:             foreach ($d1 as $d) {
                   40625:                 if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
                   40626:                     continue;
                   40627:                 }
                   40628:                 $remove[$parent] = true;
                   40629:             }
                   40630:         }
                   40631: 
                   40632:         // next remove any packages from the parents list that are not passed in for
                   40633:         // uninstallation
                   40634:         foreach ($allparents as $parent => $d1) {
                   40635:             foreach ($d1 as $d) {
                   40636:                 foreach ($params as $param) {
                   40637:                     if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
                   40638:                           strtolower($param->getPackage()) == $d[0][0]['package']) {
                   40639:                         // found it
                   40640:                         continue 3;
                   40641:                     }
                   40642:                 }
                   40643:                 $remove[$parent] = true;
                   40644:             }
                   40645:         }
                   40646: 
                   40647:         // remove all packages whose dependencies fail
                   40648:         // save which ones failed for error reporting
                   40649:         $badchildren = array();
                   40650:         do {
                   40651:             $fail = false;
                   40652:             foreach ($remove as $package => $unused) {
                   40653:                 if (!isset($allparents[$package])) {
                   40654:                     continue;
                   40655:                 }
                   40656: 
                   40657:                 foreach ($allparents[$package] as $kid => $d1) {
                   40658:                     foreach ($d1 as $depinfo) {
                   40659:                         if ($depinfo[1]['type'] != 'optional') {
                   40660:                             if (isset($badchildren[$kid])) {
                   40661:                                 continue;
                   40662:                             }
                   40663:                             $badchildren[$kid] = true;
                   40664:                             $remove[$kid] = true;
                   40665:                             $fail = true;
                   40666:                             continue 2;
                   40667:                         }
                   40668:                     }
                   40669:                 }
                   40670:                 if ($fail) {
                   40671:                     // start over, we removed some children
                   40672:                     continue 2;
                   40673:                 }
                   40674:             }
                   40675:         } while ($fail);
                   40676: 
                   40677:         // next, construct the list of packages that can't be uninstalled
                   40678:         $badpackages = array();
                   40679:         $save = $this->_currentPackage;
                   40680:         foreach ($perpackagelist as $package => $packagedeps) {
                   40681:             foreach ($packagedeps as $parent) {
                   40682:                 if (!isset($remove[$parent[0]])) {
                   40683:                     continue;
                   40684:                 }
                   40685: 
                   40686:                 $packagename = $this->_registry->parsePackageName($parent[0]);
                   40687:                 $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
                   40688:                 $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
                   40689:                 $packagename['package'] = $pa->getPackage();
                   40690:                 $this->_currentPackage = $packagename;
                   40691:                 // parent is not present in uninstall list, make sure we can actually
                   40692:                 // uninstall it (parent dep is optional)
                   40693:                 $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
                   40694:                 $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
                   40695:                 $parentname['package'] = $pa->getPackage();
                   40696:                 $parent[1]['dep']['package'] = $parentname['package'];
                   40697:                 $parent[1]['dep']['channel'] = $parentname['channel'];
                   40698:                 if ($parent[1]['type'] == 'optional') {
                   40699:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
                   40700:                     if ($test !== true) {
                   40701:                         $badpackages[$package]['warnings'][] = $test;
                   40702:                     }
                   40703:                 } else {
                   40704:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
                   40705:                     if ($test !== true) {
                   40706:                         $badpackages[$package]['errors'][] = $test;
                   40707:                     }
                   40708:                 }
                   40709:             }
                   40710:         }
                   40711: 
                   40712:         $this->_currentPackage          = $save;
                   40713:         $dl->___uninstall_package_cache = $badpackages;
                   40714:         if (isset($badpackages[$memyselfandI])) {
                   40715:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   40716:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   40717:                     $dl->log(0, $warning[0]);
                   40718:                 }
                   40719:             }
                   40720: 
                   40721:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   40722:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   40723:                     if (is_array($error)) {
                   40724:                         $dl->log(0, $error[0]);
                   40725:                     } else {
                   40726:                         $dl->log(0, $error->getMessage());
                   40727:                     }
                   40728:                 }
                   40729: 
                   40730:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   40731:                     return $this->warning(
                   40732:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   40733:                         'on this package');
                   40734:                 }
                   40735: 
                   40736:                 return $this->raiseError(
                   40737:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   40738:             }
                   40739:         }
                   40740: 
                   40741:         return true;
                   40742:     }
                   40743: 
                   40744:     function _validatePackageUninstall($dep, $required, $dl)
                   40745:     {
                   40746:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   40747:         $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
                   40748:         if (!$version) {
                   40749:             return true;
                   40750:         }
                   40751: 
                   40752:         $extra = $this->_getExtraString($dep);
                   40753:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   40754:             $dep['exclude'] = array($dep['exclude']);
                   40755:         }
                   40756: 
                   40757:         if (isset($dep['conflicts'])) {
                   40758:             return true; // uninstall OK - these packages conflict (probably installed with --force)
                   40759:         }
                   40760: 
                   40761:         if (!isset($dep['min']) && !isset($dep['max'])) {
                   40762:             if (!$required) {
                   40763:                 return $this->warning('"' . $depname . '" can be optionally used by ' .
                   40764:                         'installed package %s' . $extra);
                   40765:             }
                   40766: 
                   40767:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40768:                 return $this->raiseError('"' . $depname . '" is required by ' .
                   40769:                     'installed package %s' . $extra);
                   40770:             }
                   40771: 
                   40772:             return $this->warning('warning: "' . $depname . '" is required by ' .
                   40773:                 'installed package %s' . $extra);
                   40774:         }
                   40775: 
                   40776:         $fail = false;
                   40777:         if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
                   40778:             $fail = true;
                   40779:         }
                   40780: 
                   40781:         if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
                   40782:             $fail = true;
                   40783:         }
                   40784: 
                   40785:         // we re-use this variable, preserve the original value
                   40786:         $saverequired = $required;
                   40787:         if (!$required) {
                   40788:             return $this->warning($depname . $extra . ' can be optionally used by installed package' .
                   40789:                     ' "%s"');
                   40790:         }
                   40791: 
                   40792:         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40793:             return $this->raiseError($depname . $extra . ' is required by installed package' .
                   40794:                 ' "%s"');
                   40795:         }
                   40796: 
                   40797:         return $this->raiseError('warning: ' . $depname . $extra .
                   40798:             ' is required by installed package "%s"');
                   40799:     }
                   40800: 
                   40801:     /**
                   40802:      * validate a downloaded package against installed packages
                   40803:      *
                   40804:      * As of PEAR 1.4.3, this will only validate
                   40805:      *
                   40806:      * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   40807:      *              $pkg package identifier (either
                   40808:      *                   array('package' => blah, 'channel' => blah) or an array with
                   40809:      *                   index 'info' referencing an object)
                   40810:      * @param PEAR_Downloader $dl
                   40811:      * @param array $params full list of packages to install
                   40812:      * @return true|PEAR_Error
                   40813:      */
                   40814:     function validatePackage($pkg, &$dl, $params = array())
                   40815:     {
                   40816:         if (is_array($pkg) && isset($pkg['info'])) {
                   40817:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
                   40818:         } else {
                   40819:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
                   40820:         }
                   40821: 
                   40822:         $fail = false;
                   40823:         if ($deps) {
                   40824:             if (!class_exists('PEAR_Downloader_Package')) {
                   40825:                 require_once 'PEAR/Downloader/Package.php';
                   40826:             }
                   40827: 
                   40828:             $dp = &new PEAR_Downloader_Package($dl);
                   40829:             if (is_object($pkg)) {
                   40830:                 $dp->setPackageFile($pkg);
                   40831:             } else {
                   40832:                 $dp->setDownloadURL($pkg);
                   40833:             }
                   40834: 
                   40835:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   40836:             foreach ($deps as $channel => $info) {
                   40837:                 foreach ($info as $package => $ds) {
                   40838:                     foreach ($params as $packd) {
                   40839:                         if (strtolower($packd->getPackage()) == strtolower($package) &&
                   40840:                               $packd->getChannel() == $channel) {
                   40841:                             $dl->log(3, 'skipping installed package check of "' .
                   40842:                                         $this->_registry->parsedPackageNameToString(
                   40843:                                             array('channel' => $channel, 'package' => $package),
                   40844:                                             true) .
                   40845:                                         '", version "' . $packd->getVersion() . '" will be ' .
                   40846:                                         'downloaded and installed');
                   40847:                             continue 2; // jump to next package
                   40848:                         }
                   40849:                     }
                   40850: 
                   40851:                     foreach ($ds as $d) {
                   40852:                         $checker = &new PEAR_Dependency2($this->_config, $this->_options,
                   40853:                             array('channel' => $channel, 'package' => $package), $this->_state);
                   40854:                         $dep = $d['dep'];
                   40855:                         $required = $d['type'] == 'required';
                   40856:                         $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
                   40857:                         if (is_array($ret)) {
                   40858:                             $dl->log(0, $ret[0]);
                   40859:                         } elseif (PEAR::isError($ret)) {
                   40860:                             $dl->log(0, $ret->getMessage());
                   40861:                             $fail = true;
                   40862:                         }
                   40863:                     }
                   40864:                 }
                   40865:             }
                   40866:             PEAR::popErrorHandling();
                   40867:         }
                   40868: 
                   40869:         if ($fail) {
                   40870:             return $this->raiseError(
                   40871:                 '%s cannot be installed, conflicts with installed packages');
                   40872:         }
                   40873: 
                   40874:         return true;
                   40875:     }
                   40876: 
                   40877:     /**
                   40878:      * validate a package.xml 1.0 dependency
                   40879:      */
                   40880:     function validateDependency1($dep, $params = array())
                   40881:     {
                   40882:         if (!isset($dep['optional'])) {
                   40883:             $dep['optional'] = 'no';
                   40884:         }
                   40885: 
                   40886:         list($newdep, $type) = $this->normalizeDep($dep);
                   40887:         if (!$newdep) {
                   40888:             return $this->raiseError("Invalid Dependency");
                   40889:         }
                   40890: 
                   40891:         if (method_exists($this, "validate{$type}Dependency")) {
                   40892:             return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
                   40893:                 $params, true);
                   40894:         }
                   40895:     }
                   40896: 
                   40897:     /**
                   40898:      * Convert a 1.0 dep into a 2.0 dep
                   40899:      */
                   40900:     function normalizeDep($dep)
                   40901:     {
                   40902:         $types = array(
                   40903:             'pkg' => 'Package',
                   40904:             'ext' => 'Extension',
                   40905:             'os' => 'Os',
                   40906:             'php' => 'Php'
                   40907:         );
                   40908: 
                   40909:         if (!isset($types[$dep['type']])) {
                   40910:             return array(false, false);
                   40911:         }
                   40912: 
                   40913:         $type = $types[$dep['type']];
                   40914: 
                   40915:         $newdep = array();
                   40916:         switch ($type) {
                   40917:             case 'Package' :
                   40918:                 $newdep['channel'] = 'pear.php.net';
                   40919:             case 'Extension' :
                   40920:             case 'Os' :
                   40921:                 $newdep['name'] = $dep['name'];
                   40922:             break;
                   40923:         }
                   40924: 
                   40925:         $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
                   40926:         switch ($dep['rel']) {
                   40927:             case 'has' :
                   40928:                 return array($newdep, $type);
                   40929:             break;
                   40930:             case 'not' :
                   40931:                 $newdep['conflicts'] = true;
                   40932:             break;
                   40933:             case '>=' :
                   40934:             case '>' :
                   40935:                 $newdep['min'] = $dep['version'];
                   40936:                 if ($dep['rel'] == '>') {
                   40937:                     $newdep['exclude'] = $dep['version'];
                   40938:                 }
                   40939:             break;
                   40940:             case '<=' :
                   40941:             case '<' :
                   40942:                 $newdep['max'] = $dep['version'];
                   40943:                 if ($dep['rel'] == '<') {
                   40944:                     $newdep['exclude'] = $dep['version'];
                   40945:                 }
                   40946:             break;
                   40947:             case 'ne' :
                   40948:             case '!=' :
                   40949:                 $newdep['min'] = '0';
                   40950:                 $newdep['max'] = '100000';
                   40951:                 $newdep['exclude'] = $dep['version'];
                   40952:             break;
                   40953:             case '==' :
                   40954:                 $newdep['min'] = $dep['version'];
                   40955:                 $newdep['max'] = $dep['version'];
                   40956:             break;
                   40957:         }
                   40958:         if ($type == 'Php') {
                   40959:             if (!isset($newdep['min'])) {
                   40960:                 $newdep['min'] = '4.4.0';
                   40961:             }
                   40962: 
                   40963:             if (!isset($newdep['max'])) {
                   40964:                 $newdep['max'] = '6.0.0';
                   40965:             }
                   40966:         }
                   40967:         return array($newdep, $type);
                   40968:     }
                   40969: 
                   40970:     /**
                   40971:      * Converts text comparing operators to them sign equivalents
                   40972:      *
                   40973:      * Example: 'ge' to '>='
                   40974:      *
                   40975:      * @access public
                   40976:      * @param  string Operator
                   40977:      * @return string Sign equivalent
                   40978:      */
                   40979:     function signOperator($operator)
                   40980:     {
                   40981:         switch($operator) {
                   40982:             case 'lt': return '<';
                   40983:             case 'le': return '<=';
                   40984:             case 'gt': return '>';
                   40985:             case 'ge': return '>=';
                   40986:             case 'eq': return '==';
                   40987:             case 'ne': return '!=';
                   40988:             default:
                   40989:                 return $operator;
                   40990:         }
                   40991:     }
                   40992: 
                   40993:     function raiseError($msg)
                   40994:     {
                   40995:         if (isset($this->_options['ignore-errors'])) {
                   40996:             return $this->warning($msg);
                   40997:         }
                   40998: 
                   40999:         return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   41000:             $this->_currentPackage, true)));
                   41001:     }
                   41002: 
                   41003:     function warning($msg)
                   41004:     {
                   41005:         return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   41006:             $this->_currentPackage, true)));
                   41007:     }
                   41008: }PEAR-1.9.4/PEAR/Downloader.php0000644000076500000240000020203111605156760014572 0ustar  helgistaff<?php
                   41009: /**
                   41010:  * PEAR_Downloader, the PEAR Installer's download utility class
                   41011:  *
                   41012:  * PHP versions 4 and 5
                   41013:  *
                   41014:  * @category   pear
                   41015:  * @package    PEAR
                   41016:  * @author     Greg Beaver <cellog@php.net>
                   41017:  * @author     Stig Bakken <ssb@php.net>
                   41018:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   41019:  * @author     Martin Jansen <mj@php.net>
                   41020:  * @copyright  1997-2009 The Authors
                   41021:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   41022:  * @version    CVS: $Id: Downloader.php 313024 2011-07-06 19:51:24Z dufuz $
                   41023:  * @link       http://pear.php.net/package/PEAR
                   41024:  * @since      File available since Release 1.3.0
                   41025:  */
                   41026: 
                   41027: /**
                   41028:  * Needed for constants, extending
                   41029:  */
                   41030: require_once 'PEAR/Common.php';
                   41031: 
                   41032: define('PEAR_INSTALLER_OK',       1);
                   41033: define('PEAR_INSTALLER_FAILED',   0);
                   41034: define('PEAR_INSTALLER_SKIPPED', -1);
                   41035: define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
                   41036: 
                   41037: /**
                   41038:  * Administration class used to download anything from the internet (PEAR Packages,
                   41039:  * static URLs, xml files)
                   41040:  *
                   41041:  * @category   pear
                   41042:  * @package    PEAR
                   41043:  * @author     Greg Beaver <cellog@php.net>
                   41044:  * @author     Stig Bakken <ssb@php.net>
                   41045:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   41046:  * @author     Martin Jansen <mj@php.net>
                   41047:  * @copyright  1997-2009 The Authors
                   41048:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   41049:  * @version    Release: 1.9.4
                   41050:  * @link       http://pear.php.net/package/PEAR
                   41051:  * @since      Class available since Release 1.3.0
                   41052:  */
                   41053: class PEAR_Downloader extends PEAR_Common
                   41054: {
                   41055:     /**
                   41056:      * @var PEAR_Registry
                   41057:      * @access private
                   41058:      */
                   41059:     var $_registry;
                   41060: 
                   41061:     /**
                   41062:      * Preferred Installation State (snapshot, devel, alpha, beta, stable)
                   41063:      * @var string|null
                   41064:      * @access private
                   41065:      */
                   41066:     var $_preferredState;
                   41067: 
                   41068:     /**
                   41069:      * Options from command-line passed to Install.
                   41070:      *
                   41071:      * Recognized options:<br />
                   41072:      *  - onlyreqdeps   : install all required dependencies as well
                   41073:      *  - alldeps       : install all dependencies, including optional
                   41074:      *  - installroot   : base relative path to install files in
                   41075:      *  - force         : force a download even if warnings would prevent it
                   41076:      *  - nocompress    : download uncompressed tarballs
                   41077:      * @see PEAR_Command_Install
                   41078:      * @access private
                   41079:      * @var array
                   41080:      */
                   41081:     var $_options;
                   41082: 
                   41083:     /**
                   41084:      * Downloaded Packages after a call to download().
                   41085:      *
                   41086:      * Format of each entry:
                   41087:      *
                   41088:      * <code>
                   41089:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   41090:      *    'info' => array() // parsed package.xml
                   41091:      * );
                   41092:      * </code>
                   41093:      * @access private
                   41094:      * @var array
                   41095:      */
                   41096:     var $_downloadedPackages = array();
                   41097: 
                   41098:     /**
                   41099:      * Packages slated for download.
                   41100:      *
                   41101:      * This is used to prevent downloading a package more than once should it be a dependency
                   41102:      * for two packages to be installed.
                   41103:      * Format of each entry:
                   41104:      *
                   41105:      * <pre>
                   41106:      * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
                   41107:      * );
                   41108:      * </pre>
                   41109:      * @access private
                   41110:      * @var array
                   41111:      */
                   41112:     var $_toDownload = array();
                   41113: 
                   41114:     /**
                   41115:      * Array of every package installed, with names lower-cased.
                   41116:      *
                   41117:      * Format:
                   41118:      * <code>
                   41119:      * array('package1' => 0, 'package2' => 1, );
                   41120:      * </code>
                   41121:      * @var array
                   41122:      */
                   41123:     var $_installed = array();
                   41124: 
                   41125:     /**
                   41126:      * @var array
                   41127:      * @access private
                   41128:      */
                   41129:     var $_errorStack = array();
                   41130: 
                   41131:     /**
                   41132:      * @var boolean
                   41133:      * @access private
                   41134:      */
                   41135:     var $_internalDownload = false;
                   41136: 
                   41137:     /**
                   41138:      * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
                   41139:      * @var array
                   41140:      * @access private
                   41141:      */
                   41142:     var $_packageSortTree;
                   41143: 
                   41144:     /**
                   41145:      * Temporary directory, or configuration value where downloads will occur
                   41146:      * @var string
                   41147:      */
                   41148:     var $_downloadDir;
                   41149: 
                   41150:     /**
                   41151:      * @param PEAR_Frontend_*
                   41152:      * @param array
                   41153:      * @param PEAR_Config
                   41154:      */
                   41155:     function PEAR_Downloader(&$ui, $options, &$config)
                   41156:     {
                   41157:         parent::PEAR_Common();
                   41158:         $this->_options = $options;
                   41159:         $this->config = &$config;
                   41160:         $this->_preferredState = $this->config->get('preferred_state');
                   41161:         $this->ui = &$ui;
                   41162:         if (!$this->_preferredState) {
                   41163:             // don't inadvertantly use a non-set preferred_state
                   41164:             $this->_preferredState = null;
                   41165:         }
                   41166: 
                   41167:         if (isset($this->_options['installroot'])) {
                   41168:             $this->config->setInstallRoot($this->_options['installroot']);
                   41169:         }
                   41170:         $this->_registry = &$config->getRegistry();
                   41171: 
                   41172:         if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
                   41173:             $this->_installed = $this->_registry->listAllPackages();
                   41174:             foreach ($this->_installed as $key => $unused) {
                   41175:                 if (!count($unused)) {
                   41176:                     continue;
                   41177:                 }
                   41178:                 $strtolower = create_function('$a','return strtolower($a);');
                   41179:                 array_walk($this->_installed[$key], $strtolower);
                   41180:             }
                   41181:         }
                   41182:     }
                   41183: 
                   41184:     /**
                   41185:      * Attempt to discover a channel's remote capabilities from
                   41186:      * its server name
                   41187:      * @param string
                   41188:      * @return boolean
                   41189:      */
                   41190:     function discover($channel)
                   41191:     {
                   41192:         $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
                   41193:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41194:         $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
                   41195:         if (!class_exists('System')) {
                   41196:             require_once 'System.php';
                   41197:         }
                   41198: 
                   41199:         $tmpdir = $this->config->get('temp_dir');
                   41200:         $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
                   41201:         $a   = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   41202:         PEAR::popErrorHandling();
                   41203:         if (PEAR::isError($a)) {
                   41204:             // Attempt to fallback to https automatically.
                   41205:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41206:             $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
                   41207:             $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   41208:             PEAR::popErrorHandling();
                   41209:             if (PEAR::isError($a)) {
                   41210:                 return false;
                   41211:             }
                   41212:         }
                   41213: 
                   41214:         list($a, $lastmodified) = $a;
                   41215:         if (!class_exists('PEAR_ChannelFile')) {
                   41216:             require_once 'PEAR/ChannelFile.php';
                   41217:         }
                   41218: 
                   41219:         $b = new PEAR_ChannelFile;
                   41220:         if ($b->fromXmlFile($a)) {
                   41221:             unlink($a);
                   41222:             if ($this->config->get('auto_discover')) {
                   41223:                 $this->_registry->addChannel($b, $lastmodified);
                   41224:                 $alias = $b->getName();
                   41225:                 if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
                   41226:                     $alias = $b->getAlias();
                   41227:                 }
                   41228: 
                   41229:                 $this->log(1, 'Auto-discovered channel "' . $channel .
                   41230:                     '", alias "' . $alias . '", adding to registry');
                   41231:             }
                   41232: 
                   41233:             return true;
                   41234:         }
                   41235: 
                   41236:         unlink($a);
                   41237:         return false;
                   41238:     }
                   41239: 
                   41240:     /**
                   41241:      * For simpler unit-testing
                   41242:      * @param PEAR_Downloader
                   41243:      * @return PEAR_Downloader_Package
                   41244:      */
                   41245:     function &newDownloaderPackage(&$t)
                   41246:     {
                   41247:         if (!class_exists('PEAR_Downloader_Package')) {
                   41248:             require_once 'PEAR/Downloader/Package.php';
                   41249:         }
                   41250:         $a = &new PEAR_Downloader_Package($t);
                   41251:         return $a;
                   41252:     }
                   41253: 
                   41254:     /**
                   41255:      * For simpler unit-testing
                   41256:      * @param PEAR_Config
                   41257:      * @param array
                   41258:      * @param array
                   41259:      * @param int
                   41260:      */
                   41261:     function &getDependency2Object(&$c, $i, $p, $s)
                   41262:     {
                   41263:         if (!class_exists('PEAR_Dependency2')) {
                   41264:             require_once 'PEAR/Dependency2.php';
                   41265:         }
                   41266:         $z = &new PEAR_Dependency2($c, $i, $p, $s);
                   41267:         return $z;
                   41268:     }
                   41269: 
                   41270:     function &download($params)
                   41271:     {
                   41272:         if (!count($params)) {
                   41273:             $a = array();
                   41274:             return $a;
                   41275:         }
                   41276: 
                   41277:         if (!isset($this->_registry)) {
                   41278:             $this->_registry = &$this->config->getRegistry();
                   41279:         }
                   41280: 
                   41281:         $channelschecked = array();
                   41282:         // convert all parameters into PEAR_Downloader_Package objects
                   41283:         foreach ($params as $i => $param) {
                   41284:             $params[$i] = &$this->newDownloaderPackage($this);
                   41285:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41286:             $err = $params[$i]->initialize($param);
                   41287:             PEAR::staticPopErrorHandling();
                   41288:             if (!$err) {
                   41289:                 // skip parameters that were missed by preferred_state
                   41290:                 continue;
                   41291:             }
                   41292: 
                   41293:             if (PEAR::isError($err)) {
                   41294:                 if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
                   41295:                     $this->log(0, $err->getMessage());
                   41296:                 }
                   41297: 
                   41298:                 $params[$i] = false;
                   41299:                 if (is_object($param)) {
                   41300:                     $param = $param->getChannel() . '/' . $param->getPackage();
                   41301:                 }
                   41302: 
                   41303:                 if (!isset($this->_options['soft'])) {
                   41304:                     $this->log(2, 'Package "' . $param . '" is not valid');
                   41305:                 }
                   41306: 
                   41307:                 // Message logged above in a specific verbose mode, passing null to not show up on CLI
                   41308:                 $this->pushError(null, PEAR_INSTALLER_SKIPPED);
                   41309:             } else {
                   41310:                 do {
                   41311:                     if ($params[$i] && $params[$i]->getType() == 'local') {
                   41312:                         // bug #7090 skip channel.xml check for local packages
                   41313:                         break;
                   41314:                     }
                   41315: 
                   41316:                     if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
                   41317:                           !isset($this->_options['offline'])
                   41318:                     ) {
                   41319:                         $channelschecked[$params[$i]->getChannel()] = true;
                   41320:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41321:                         if (!class_exists('System')) {
                   41322:                             require_once 'System.php';
                   41323:                         }
                   41324: 
                   41325:                         $curchannel = &$this->_registry->getChannel($params[$i]->getChannel());
                   41326:                         if (PEAR::isError($curchannel)) {
                   41327:                             PEAR::staticPopErrorHandling();
                   41328:                             return $this->raiseError($curchannel);
                   41329:                         }
                   41330: 
                   41331:                         if (PEAR::isError($dir = $this->getDownloadDir())) {
                   41332:                             PEAR::staticPopErrorHandling();
                   41333:                             break;
                   41334:                         }
                   41335: 
                   41336:                         $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
                   41337:                         $url    = 'http://' . $mirror . '/channel.xml';
                   41338:                         $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());
                   41339: 
                   41340:                         PEAR::staticPopErrorHandling();
                   41341:                         if (PEAR::isError($a) || !$a) {
                   41342:                             // Attempt fallback to https automatically
                   41343:                             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41344:                             $a = $this->downloadHttp('https://' . $mirror .
                   41345:                                 '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());
                   41346: 
                   41347:                             PEAR::staticPopErrorHandling();
                   41348:                             if (PEAR::isError($a) || !$a) {
                   41349:                                 break;
                   41350:                             }
                   41351:                         }
                   41352:                         $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
                   41353:                             'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
                   41354:                             '" to update');
                   41355:                     }
                   41356:                 } while (false);
                   41357: 
                   41358:                 if ($params[$i] && !isset($this->_options['downloadonly'])) {
                   41359:                     if (isset($this->_options['packagingroot'])) {
                   41360:                         $checkdir = $this->_prependPath(
                   41361:                             $this->config->get('php_dir', null, $params[$i]->getChannel()),
                   41362:                             $this->_options['packagingroot']);
                   41363:                     } else {
                   41364:                         $checkdir = $this->config->get('php_dir',
                   41365:                             null, $params[$i]->getChannel());
                   41366:                     }
                   41367: 
                   41368:                     while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
                   41369:                         $checkdir = dirname($checkdir);
                   41370:                     }
                   41371: 
                   41372:                     if ($checkdir == '.') {
                   41373:                         $checkdir = '/';
                   41374:                     }
                   41375: 
                   41376:                     if (!is_writeable($checkdir)) {
                   41377:                         return PEAR::raiseError('Cannot install, php_dir for channel "' .
                   41378:                             $params[$i]->getChannel() . '" is not writeable by the current user');
                   41379:                     }
                   41380:                 }
                   41381:             }
                   41382:         }
                   41383: 
                   41384:         unset($channelschecked);
                   41385:         PEAR_Downloader_Package::removeDuplicates($params);
                   41386:         if (!count($params)) {
                   41387:             $a = array();
                   41388:             return $a;
                   41389:         }
                   41390: 
                   41391:         if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
                   41392:             $reverify = true;
                   41393:             while ($reverify) {
                   41394:                 $reverify = false;
                   41395:                 foreach ($params as $i => $param) {
                   41396:                     //PHP Bug 40768 / PEAR Bug #10944
                   41397:                     //Nested foreaches fail in PHP 5.2.1
                   41398:                     key($params);
                   41399:                     $ret = $params[$i]->detectDependencies($params);
                   41400:                     if (PEAR::isError($ret)) {
                   41401:                         $reverify = true;
                   41402:                         $params[$i] = false;
                   41403:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41404:                         if (!isset($this->_options['soft'])) {
                   41405:                             $this->log(0, $ret->getMessage());
                   41406:                         }
                   41407:                         continue 2;
                   41408:                     }
                   41409:                 }
                   41410:             }
                   41411:         }
                   41412: 
                   41413:         if (isset($this->_options['offline'])) {
                   41414:             $this->log(3, 'Skipping dependency download check, --offline specified');
                   41415:         }
                   41416: 
                   41417:         if (!count($params)) {
                   41418:             $a = array();
                   41419:             return $a;
                   41420:         }
                   41421: 
                   41422:         while (PEAR_Downloader_Package::mergeDependencies($params));
                   41423:         PEAR_Downloader_Package::removeDuplicates($params, true);
                   41424:         $errorparams = array();
                   41425:         if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
                   41426:             if (count($errorparams)) {
                   41427:                 foreach ($errorparams as $param) {
                   41428:                     $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
                   41429:                     $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
                   41430:                 }
                   41431:                 $a = array();
                   41432:                 return $a;
                   41433:             }
                   41434:         }
                   41435: 
                   41436:         PEAR_Downloader_Package::removeInstalled($params);
                   41437:         if (!count($params)) {
                   41438:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   41439:             $a = array();
                   41440:             return $a;
                   41441:         }
                   41442: 
                   41443:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41444:         $err = $this->analyzeDependencies($params);
                   41445:         PEAR::popErrorHandling();
                   41446:         if (!count($params)) {
                   41447:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   41448:             $a = array();
                   41449:             return $a;
                   41450:         }
                   41451: 
                   41452:         $ret = array();
                   41453:         $newparams = array();
                   41454:         if (isset($this->_options['pretend'])) {
                   41455:             return $params;
                   41456:         }
                   41457: 
                   41458:         $somefailed = false;
                   41459:         foreach ($params as $i => $package) {
                   41460:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41461:             $pf = &$params[$i]->download();
                   41462:             PEAR::staticPopErrorHandling();
                   41463:             if (PEAR::isError($pf)) {
                   41464:                 if (!isset($this->_options['soft'])) {
                   41465:                     $this->log(1, $pf->getMessage());
                   41466:                     $this->log(0, 'Error: cannot download "' .
                   41467:                         $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
                   41468:                             true) .
                   41469:                         '"');
                   41470:                 }
                   41471:                 $somefailed = true;
                   41472:                 continue;
                   41473:             }
                   41474: 
                   41475:             $newparams[] = &$params[$i];
                   41476:             $ret[] = array(
                   41477:                 'file' => $pf->getArchiveFile(),
                   41478:                 'info' => &$pf,
                   41479:                 'pkg'  => $pf->getPackage()
                   41480:             );
                   41481:         }
                   41482: 
                   41483:         if ($somefailed) {
                   41484:             // remove params that did not download successfully
                   41485:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41486:             $err = $this->analyzeDependencies($newparams, true);
                   41487:             PEAR::popErrorHandling();
                   41488:             if (!count($newparams)) {
                   41489:                 $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
                   41490:                 $a = array();
                   41491:                 return $a;
                   41492:             }
                   41493:         }
                   41494: 
                   41495:         $this->_downloadedPackages = $ret;
                   41496:         return $newparams;
                   41497:     }
                   41498: 
                   41499:     /**
                   41500:      * @param array all packages to be installed
                   41501:      */
                   41502:     function analyzeDependencies(&$params, $force = false)
                   41503:     {
                   41504:         if (isset($this->_options['downloadonly'])) {
                   41505:             return;
                   41506:         }
                   41507: 
                   41508:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41509:         $redo  = true;
                   41510:         $reset = $hasfailed = $failed = false;
                   41511:         while ($redo) {
                   41512:             $redo = false;
                   41513:             foreach ($params as $i => $param) {
                   41514:                 $deps = $param->getDeps();
                   41515:                 if (!$deps) {
                   41516:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   41517:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   41518:                     $send = $param->getPackageFile();
                   41519: 
                   41520:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   41521:                     if (PEAR::isError($installcheck)) {
                   41522:                         if (!isset($this->_options['soft'])) {
                   41523:                             $this->log(0, $installcheck->getMessage());
                   41524:                         }
                   41525:                         $hasfailed  = true;
                   41526:                         $params[$i] = false;
                   41527:                         $reset      = true;
                   41528:                         $redo       = true;
                   41529:                         $failed     = false;
                   41530:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41531:                         continue 2;
                   41532:                     }
                   41533:                     continue;
                   41534:                 }
                   41535: 
                   41536:                 if (!$reset && $param->alreadyValidated() && !$force) {
                   41537:                     continue;
                   41538:                 }
                   41539: 
                   41540:                 if (count($deps)) {
                   41541:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   41542:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   41543:                     $send = $param->getPackageFile();
                   41544:                     if ($send === null) {
                   41545:                         $send = $param->getDownloadURL();
                   41546:                     }
                   41547: 
                   41548:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   41549:                     if (PEAR::isError($installcheck)) {
                   41550:                         if (!isset($this->_options['soft'])) {
                   41551:                             $this->log(0, $installcheck->getMessage());
                   41552:                         }
                   41553:                         $hasfailed  = true;
                   41554:                         $params[$i] = false;
                   41555:                         $reset      = true;
                   41556:                         $redo       = true;
                   41557:                         $failed     = false;
                   41558:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41559:                         continue 2;
                   41560:                     }
                   41561: 
                   41562:                     $failed = false;
                   41563:                     if (isset($deps['required']) && is_array($deps['required'])) {
                   41564:                         foreach ($deps['required'] as $type => $dep) {
                   41565:                             // note: Dependency2 will never return a PEAR_Error if ignore-errors
                   41566:                             // is specified, so soft is needed to turn off logging
                   41567:                             if (!isset($dep[0])) {
                   41568:                                 if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
                   41569:                                       true, $params))) {
                   41570:                                     $failed = true;
                   41571:                                     if (!isset($this->_options['soft'])) {
                   41572:                                         $this->log(0, $e->getMessage());
                   41573:                                     }
                   41574:                                 } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41575:                                     if (!isset($this->_options['soft'])) {
                   41576:                                         $this->log(0, $e[0]);
                   41577:                                     }
                   41578:                                 }
                   41579:                             } else {
                   41580:                                 foreach ($dep as $d) {
                   41581:                                     if (PEAR::isError($e =
                   41582:                                           $depchecker->{"validate{$type}Dependency"}($d,
                   41583:                                           true, $params))) {
                   41584:                                         $failed = true;
                   41585:                                         if (!isset($this->_options['soft'])) {
                   41586:                                             $this->log(0, $e->getMessage());
                   41587:                                         }
                   41588:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41589:                                         if (!isset($this->_options['soft'])) {
                   41590:                                             $this->log(0, $e[0]);
                   41591:                                         }
                   41592:                                     }
                   41593:                                 }
                   41594:                             }
                   41595:                         }
                   41596: 
                   41597:                         if (isset($deps['optional']) && is_array($deps['optional'])) {
                   41598:                             foreach ($deps['optional'] as $type => $dep) {
                   41599:                                 if (!isset($dep[0])) {
                   41600:                                     if (PEAR::isError($e =
                   41601:                                           $depchecker->{"validate{$type}Dependency"}($dep,
                   41602:                                           false, $params))) {
                   41603:                                         $failed = true;
                   41604:                                         if (!isset($this->_options['soft'])) {
                   41605:                                             $this->log(0, $e->getMessage());
                   41606:                                         }
                   41607:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41608:                                         if (!isset($this->_options['soft'])) {
                   41609:                                             $this->log(0, $e[0]);
                   41610:                                         }
                   41611:                                     }
                   41612:                                 } else {
                   41613:                                     foreach ($dep as $d) {
                   41614:                                         if (PEAR::isError($e =
                   41615:                                               $depchecker->{"validate{$type}Dependency"}($d,
                   41616:                                               false, $params))) {
                   41617:                                             $failed = true;
                   41618:                                             if (!isset($this->_options['soft'])) {
                   41619:                                                 $this->log(0, $e->getMessage());
                   41620:                                             }
                   41621:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41622:                                             if (!isset($this->_options['soft'])) {
                   41623:                                                 $this->log(0, $e[0]);
                   41624:                                             }
                   41625:                                         }
                   41626:                                     }
                   41627:                                 }
                   41628:                             }
                   41629:                         }
                   41630: 
                   41631:                         $groupname = $param->getGroup();
                   41632:                         if (isset($deps['group']) && $groupname) {
                   41633:                             if (!isset($deps['group'][0])) {
                   41634:                                 $deps['group'] = array($deps['group']);
                   41635:                             }
                   41636: 
                   41637:                             $found = false;
                   41638:                             foreach ($deps['group'] as $group) {
                   41639:                                 if ($group['attribs']['name'] == $groupname) {
                   41640:                                     $found = true;
                   41641:                                     break;
                   41642:                                 }
                   41643:                             }
                   41644: 
                   41645:                             if ($found) {
                   41646:                                 unset($group['attribs']);
                   41647:                                 foreach ($group as $type => $dep) {
                   41648:                                     if (!isset($dep[0])) {
                   41649:                                         if (PEAR::isError($e =
                   41650:                                               $depchecker->{"validate{$type}Dependency"}($dep,
                   41651:                                               false, $params))) {
                   41652:                                             $failed = true;
                   41653:                                             if (!isset($this->_options['soft'])) {
                   41654:                                                 $this->log(0, $e->getMessage());
                   41655:                                             }
                   41656:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41657:                                             if (!isset($this->_options['soft'])) {
                   41658:                                                 $this->log(0, $e[0]);
                   41659:                                             }
                   41660:                                         }
                   41661:                                     } else {
                   41662:                                         foreach ($dep as $d) {
                   41663:                                             if (PEAR::isError($e =
                   41664:                                                   $depchecker->{"validate{$type}Dependency"}($d,
                   41665:                                                   false, $params))) {
                   41666:                                                 $failed = true;
                   41667:                                                 if (!isset($this->_options['soft'])) {
                   41668:                                                     $this->log(0, $e->getMessage());
                   41669:                                                 }
                   41670:                                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41671:                                                 if (!isset($this->_options['soft'])) {
                   41672:                                                     $this->log(0, $e[0]);
                   41673:                                                 }
                   41674:                                             }
                   41675:                                         }
                   41676:                                     }
                   41677:                                 }
                   41678:                             }
                   41679:                         }
                   41680:                     } else {
                   41681:                         foreach ($deps as $dep) {
                   41682:                             if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
                   41683:                                 $failed = true;
                   41684:                                 if (!isset($this->_options['soft'])) {
                   41685:                                     $this->log(0, $e->getMessage());
                   41686:                                 }
                   41687:                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41688:                                 if (!isset($this->_options['soft'])) {
                   41689:                                     $this->log(0, $e[0]);
                   41690:                                 }
                   41691:                             }
                   41692:                         }
                   41693:                     }
                   41694:                     $params[$i]->setValidated();
                   41695:                 }
                   41696: 
                   41697:                 if ($failed) {
                   41698:                     $hasfailed  = true;
                   41699:                     $params[$i] = false;
                   41700:                     $reset      = true;
                   41701:                     $redo       = true;
                   41702:                     $failed     = false;
                   41703:                     PEAR_Downloader_Package::removeDuplicates($params);
                   41704:                     continue 2;
                   41705:                 }
                   41706:             }
                   41707:         }
                   41708: 
                   41709:         PEAR::staticPopErrorHandling();
                   41710:         if ($hasfailed && (isset($this->_options['ignore-errors']) ||
                   41711:               isset($this->_options['nodeps']))) {
                   41712:             // this is probably not needed, but just in case
                   41713:             if (!isset($this->_options['soft'])) {
                   41714:                 $this->log(0, 'WARNING: dependencies failed');
                   41715:             }
                   41716:         }
                   41717:     }
                   41718: 
                   41719:     /**
                   41720:      * Retrieve the directory that downloads will happen in
                   41721:      * @access private
                   41722:      * @return string
                   41723:      */
                   41724:     function getDownloadDir()
                   41725:     {
                   41726:         if (isset($this->_downloadDir)) {
                   41727:             return $this->_downloadDir;
                   41728:         }
                   41729: 
                   41730:         $downloaddir = $this->config->get('download_dir');
                   41731:         if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
                   41732:             if  (is_dir($downloaddir) && !is_writable($downloaddir)) {
                   41733:                 $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
                   41734:                     '" is not writeable.  Change download_dir config variable to ' .
                   41735:                     'a writeable dir to avoid this warning');
                   41736:             }
                   41737: 
                   41738:             if (!class_exists('System')) {
                   41739:                 require_once 'System.php';
                   41740:             }
                   41741: 
                   41742:             if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
                   41743:                 return $downloaddir;
                   41744:             }
                   41745:             $this->log(3, '+ tmp dir created at ' . $downloaddir);
                   41746:         }
                   41747: 
                   41748:         if (!is_writable($downloaddir)) {
                   41749:             if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
                   41750:                   !is_writable($downloaddir)) {
                   41751:                 return PEAR::raiseError('download directory "' . $downloaddir .
                   41752:                     '" is not writeable.  Change download_dir config variable to ' .
                   41753:                     'a writeable dir');
                   41754:             }
                   41755:         }
                   41756: 
                   41757:         return $this->_downloadDir = $downloaddir;
                   41758:     }
                   41759: 
                   41760:     function setDownloadDir($dir)
                   41761:     {
                   41762:         if (!@is_writable($dir)) {
                   41763:             if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
                   41764:                 return PEAR::raiseError('download directory "' . $dir .
                   41765:                     '" is not writeable.  Change download_dir config variable to ' .
                   41766:                     'a writeable dir');
                   41767:             }
                   41768:         }
                   41769:         $this->_downloadDir = $dir;
                   41770:     }
                   41771: 
                   41772:     function configSet($key, $value, $layer = 'user', $channel = false)
                   41773:     {
                   41774:         $this->config->set($key, $value, $layer, $channel);
                   41775:         $this->_preferredState = $this->config->get('preferred_state', null, $channel);
                   41776:         if (!$this->_preferredState) {
                   41777:             // don't inadvertantly use a non-set preferred_state
                   41778:             $this->_preferredState = null;
                   41779:         }
                   41780:     }
                   41781: 
                   41782:     function setOptions($options)
                   41783:     {
                   41784:         $this->_options = $options;
                   41785:     }
                   41786: 
                   41787:     function getOptions()
                   41788:     {
                   41789:         return $this->_options;
                   41790:     }
                   41791: 
                   41792: 
                   41793:     /**
                   41794:      * @param array output of {@link parsePackageName()}
                   41795:      * @access private
                   41796:      */
                   41797:     function _getPackageDownloadUrl($parr)
                   41798:     {
                   41799:         $curchannel = $this->config->get('default_channel');
                   41800:         $this->configSet('default_channel', $parr['channel']);
                   41801:         // getDownloadURL returns an array.  On error, it only contains information
                   41802:         // on the latest release as array(version, info).  On success it contains
                   41803:         // array(version, info, download url string)
                   41804:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   41805:         if (!$this->_registry->channelExists($parr['channel'])) {
                   41806:             do {
                   41807:                 if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
                   41808:                     break;
                   41809:                 }
                   41810: 
                   41811:                 $this->configSet('default_channel', $curchannel);
                   41812:                 return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
                   41813:             } while (false);
                   41814:         }
                   41815: 
                   41816:         $chan = &$this->_registry->getChannel($parr['channel']);
                   41817:         if (PEAR::isError($chan)) {
                   41818:             return $chan;
                   41819:         }
                   41820: 
                   41821:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41822:         $version   = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
                   41823:         $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
                   41824:         // package is installed - use the installed release stability level
                   41825:         if (!isset($parr['state']) && $stability !== null) {
                   41826:             $state = $stability['release'];
                   41827:         }
                   41828:         PEAR::staticPopErrorHandling();
                   41829:         $base2 = false;
                   41830: 
                   41831:         $preferred_mirror = $this->config->get('preferred_mirror');
                   41832:         if (!$chan->supportsREST($preferred_mirror) ||
                   41833:               (
                   41834:                !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
                   41835:                &&
                   41836:                !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   41837:               )
                   41838:         ) {
                   41839:             return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   41840:         }
                   41841: 
                   41842:         if ($base2) {
                   41843:             $rest = &$this->config->getREST('1.3', $this->_options);
                   41844:             $base = $base2;
                   41845:         } else {
                   41846:             $rest = &$this->config->getREST('1.0', $this->_options);
                   41847:         }
                   41848: 
                   41849:         $downloadVersion = false;
                   41850:         if (!isset($parr['version']) && !isset($parr['state']) && $version
                   41851:               && !PEAR::isError($version)
                   41852:               && !isset($this->_options['downloadonly'])
                   41853:         ) {
                   41854:             $downloadVersion = $version;
                   41855:         }
                   41856: 
                   41857:         $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
                   41858:         if (PEAR::isError($url)) {
                   41859:             $this->configSet('default_channel', $curchannel);
                   41860:             return $url;
                   41861:         }
                   41862: 
                   41863:         if ($parr['channel'] != $curchannel) {
                   41864:             $this->configSet('default_channel', $curchannel);
                   41865:         }
                   41866: 
                   41867:         if (!is_array($url)) {
                   41868:             return $url;
                   41869:         }
                   41870: 
                   41871:         $url['raw'] = false; // no checking is necessary for REST
                   41872:         if (!is_array($url['info'])) {
                   41873:             return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   41874:                 'this should never happen');
                   41875:         }
                   41876: 
                   41877:         if (!isset($this->_options['force']) &&
                   41878:               !isset($this->_options['downloadonly']) &&
                   41879:               $version &&
                   41880:               !PEAR::isError($version) &&
                   41881:               !isset($parr['group'])
                   41882:         ) {
                   41883:             if (version_compare($version, $url['version'], '=')) {
                   41884:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   41885:                     $parr, true) . ' is already installed and is the same as the ' .
                   41886:                     'released version ' . $url['version'], -976);
                   41887:             }
                   41888: 
                   41889:             if (version_compare($version, $url['version'], '>')) {
                   41890:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   41891:                     $parr, true) . ' is already installed and is newer than detected ' .
                   41892:                     'released version ' . $url['version'], -976);
                   41893:             }
                   41894:         }
                   41895: 
                   41896:         if (isset($url['info']['required']) || $url['compatible']) {
                   41897:             require_once 'PEAR/PackageFile/v2.php';
                   41898:             $pf = new PEAR_PackageFile_v2;
                   41899:             $pf->setRawChannel($parr['channel']);
                   41900:             if ($url['compatible']) {
                   41901:                 $pf->setRawCompatible($url['compatible']);
                   41902:             }
                   41903:         } else {
                   41904:             require_once 'PEAR/PackageFile/v1.php';
                   41905:             $pf = new PEAR_PackageFile_v1;
                   41906:         }
                   41907: 
                   41908:         $pf->setRawPackage($url['package']);
                   41909:         $pf->setDeps($url['info']);
                   41910:         if ($url['compatible']) {
                   41911:             $pf->setCompatible($url['compatible']);
                   41912:         }
                   41913: 
                   41914:         $pf->setRawState($url['stability']);
                   41915:         $url['info'] = &$pf;
                   41916:         if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   41917:             $ext = '.tar';
                   41918:         } else {
                   41919:             $ext = '.tgz';
                   41920:         }
                   41921: 
                   41922:         if (is_array($url) && isset($url['url'])) {
                   41923:             $url['url'] .= $ext;
                   41924:         }
                   41925: 
                   41926:         return $url;
                   41927:     }
                   41928: 
                   41929:     /**
                   41930:      * @param array dependency array
                   41931:      * @access private
                   41932:      */
                   41933:     function _getDepPackageDownloadUrl($dep, $parr)
                   41934:     {
                   41935:         $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
                   41936:         $curchannel = $this->config->get('default_channel');
                   41937:         if (isset($dep['uri'])) {
                   41938:             $xsdversion = '2.0';
                   41939:             $chan = &$this->_registry->getChannel('__uri');
                   41940:             if (PEAR::isError($chan)) {
                   41941:                 return $chan;
                   41942:             }
                   41943: 
                   41944:             $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
                   41945:             $this->configSet('default_channel', '__uri');
                   41946:         } else {
                   41947:             if (isset($dep['channel'])) {
                   41948:                 $remotechannel = $dep['channel'];
                   41949:             } else {
                   41950:                 $remotechannel = 'pear.php.net';
                   41951:             }
                   41952: 
                   41953:             if (!$this->_registry->channelExists($remotechannel)) {
                   41954:                 do {
                   41955:                     if ($this->config->get('auto_discover')) {
                   41956:                         if ($this->discover($remotechannel)) {
                   41957:                             break;
                   41958:                         }
                   41959:                     }
                   41960:                     return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
                   41961:                 } while (false);
                   41962:             }
                   41963: 
                   41964:             $chan = &$this->_registry->getChannel($remotechannel);
                   41965:             if (PEAR::isError($chan)) {
                   41966:                 return $chan;
                   41967:             }
                   41968: 
                   41969:             $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
                   41970:             $this->configSet('default_channel', $remotechannel);
                   41971:         }
                   41972: 
                   41973:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   41974:         if (isset($parr['state']) && isset($parr['version'])) {
                   41975:             unset($parr['state']);
                   41976:         }
                   41977: 
                   41978:         if (isset($dep['uri'])) {
                   41979:             $info = &$this->newDownloaderPackage($this);
                   41980:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41981:             $err = $info->initialize($dep);
                   41982:             PEAR::staticPopErrorHandling();
                   41983:             if (!$err) {
                   41984:                 // skip parameters that were missed by preferred_state
                   41985:                 return PEAR::raiseError('Cannot initialize dependency');
                   41986:             }
                   41987: 
                   41988:             if (PEAR::isError($err)) {
                   41989:                 if (!isset($this->_options['soft'])) {
                   41990:                     $this->log(0, $err->getMessage());
                   41991:                 }
                   41992: 
                   41993:                 if (is_object($info)) {
                   41994:                     $param = $info->getChannel() . '/' . $info->getPackage();
                   41995:                 }
                   41996:                 return PEAR::raiseError('Package "' . $param . '" is not valid');
                   41997:             }
                   41998:             return $info;
                   41999:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
                   42000:               &&
                   42001:                 (
                   42002:                   ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
                   42003:                     ||
                   42004:                   ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
                   42005:                 )
                   42006:         ) {
                   42007:             if ($base2) {
                   42008:                 $base = $base2;
                   42009:                 $rest = &$this->config->getREST('1.3', $this->_options);
                   42010:             } else {
                   42011:                 $rest = &$this->config->getREST('1.0', $this->_options);
                   42012:             }
                   42013: 
                   42014:             $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
                   42015:                     $state, $version, $chan->getName());
                   42016:             if (PEAR::isError($url)) {
                   42017:                 return $url;
                   42018:             }
                   42019: 
                   42020:             if ($parr['channel'] != $curchannel) {
                   42021:                 $this->configSet('default_channel', $curchannel);
                   42022:             }
                   42023: 
                   42024:             if (!is_array($url)) {
                   42025:                 return $url;
                   42026:             }
                   42027: 
                   42028:             $url['raw'] = false; // no checking is necessary for REST
                   42029:             if (!is_array($url['info'])) {
                   42030:                 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   42031:                     'this should never happen');
                   42032:             }
                   42033: 
                   42034:             if (isset($url['info']['required'])) {
                   42035:                 if (!class_exists('PEAR_PackageFile_v2')) {
                   42036:                     require_once 'PEAR/PackageFile/v2.php';
                   42037:                 }
                   42038:                 $pf = new PEAR_PackageFile_v2;
                   42039:                 $pf->setRawChannel($remotechannel);
                   42040:             } else {
                   42041:                 if (!class_exists('PEAR_PackageFile_v1')) {
                   42042:                     require_once 'PEAR/PackageFile/v1.php';
                   42043:                 }
                   42044:                 $pf = new PEAR_PackageFile_v1;
                   42045: 
                   42046:             }
                   42047:             $pf->setRawPackage($url['package']);
                   42048:             $pf->setDeps($url['info']);
                   42049:             if ($url['compatible']) {
                   42050:                 $pf->setCompatible($url['compatible']);
                   42051:             }
                   42052: 
                   42053:             $pf->setRawState($url['stability']);
                   42054:             $url['info'] = &$pf;
                   42055:             if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   42056:                 $ext = '.tar';
                   42057:             } else {
                   42058:                 $ext = '.tgz';
                   42059:             }
                   42060: 
                   42061:             if (is_array($url) && isset($url['url'])) {
                   42062:                 $url['url'] .= $ext;
                   42063:             }
                   42064: 
                   42065:             return $url;
                   42066:         }
                   42067: 
                   42068:         return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   42069:     }
                   42070: 
                   42071:     /**
                   42072:      * @deprecated in favor of _getPackageDownloadUrl
                   42073:      */
                   42074:     function getPackageDownloadUrl($package, $version = null, $channel = false)
                   42075:     {
                   42076:         if ($version) {
                   42077:             $package .= "-$version";
                   42078:         }
                   42079:         if ($this === null || $this->_registry === null) {
                   42080:             $package = "http://pear.php.net/get/$package";
                   42081:         } else {
                   42082:             $chan = $this->_registry->getChannel($channel);
                   42083:             if (PEAR::isError($chan)) {
                   42084:                 return '';
                   42085:             }
                   42086:             $package = "http://" . $chan->getServer() . "/get/$package";
                   42087:         }
                   42088:         if (!extension_loaded("zlib")) {
                   42089:             $package .= '?uncompress=yes';
                   42090:         }
                   42091:         return $package;
                   42092:     }
                   42093: 
                   42094:     /**
                   42095:      * Retrieve a list of downloaded packages after a call to {@link download()}.
                   42096:      *
                   42097:      * Also resets the list of downloaded packages.
                   42098:      * @return array
                   42099:      */
                   42100:     function getDownloadedPackages()
                   42101:     {
                   42102:         $ret = $this->_downloadedPackages;
                   42103:         $this->_downloadedPackages = array();
                   42104:         $this->_toDownload = array();
                   42105:         return $ret;
                   42106:     }
                   42107: 
                   42108:     function _downloadCallback($msg, $params = null)
                   42109:     {
                   42110:         switch ($msg) {
                   42111:             case 'saveas':
                   42112:                 $this->log(1, "downloading $params ...");
                   42113:                 break;
                   42114:             case 'done':
                   42115:                 $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
                   42116:                 break;
                   42117:             case 'bytesread':
                   42118:                 static $bytes;
                   42119:                 if (empty($bytes)) {
                   42120:                     $bytes = 0;
                   42121:                 }
                   42122:                 if (!($bytes % 10240)) {
                   42123:                     $this->log(1, '.', false);
                   42124:                 }
                   42125:                 $bytes += $params;
                   42126:                 break;
                   42127:             case 'start':
                   42128:                 if($params[1] == -1) {
                   42129:                     $length = "Unknown size";
                   42130:                 } else {
                   42131:                     $length = number_format($params[1], 0, '', ',')." bytes";
                   42132:                 }
                   42133:                 $this->log(1, "Starting to download {$params[0]} ($length)");
                   42134:                 break;
                   42135:         }
                   42136:         if (method_exists($this->ui, '_downloadCallback'))
                   42137:             $this->ui->_downloadCallback($msg, $params);
                   42138:     }
                   42139: 
                   42140:     function _prependPath($path, $prepend)
                   42141:     {
                   42142:         if (strlen($prepend) > 0) {
                   42143:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   42144:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   42145:                     $prepend = substr($prepend, 2);
                   42146:                 } elseif ($prepend{0} != '\\') {
                   42147:                     $prepend = "\\$prepend";
                   42148:                 }
                   42149:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   42150:             } else {
                   42151:                 $path = $prepend . $path;
                   42152:             }
                   42153:         }
                   42154:         return $path;
                   42155:     }
                   42156: 
                   42157:     /**
                   42158:      * @param string
                   42159:      * @param integer
                   42160:      */
                   42161:     function pushError($errmsg, $code = -1)
                   42162:     {
                   42163:         array_push($this->_errorStack, array($errmsg, $code));
                   42164:     }
                   42165: 
                   42166:     function getErrorMsgs()
                   42167:     {
                   42168:         $msgs = array();
                   42169:         $errs = $this->_errorStack;
                   42170:         foreach ($errs as $err) {
                   42171:             $msgs[] = $err[0];
                   42172:         }
                   42173:         $this->_errorStack = array();
                   42174:         return $msgs;
                   42175:     }
                   42176: 
                   42177:     /**
                   42178:      * for BC
                   42179:      *
                   42180:      * @deprecated
                   42181:      */
                   42182:     function sortPkgDeps(&$packages, $uninstall = false)
                   42183:     {
                   42184:         $uninstall ?
                   42185:             $this->sortPackagesForUninstall($packages) :
                   42186:             $this->sortPackagesForInstall($packages);
                   42187:     }
                   42188: 
                   42189:     /**
                   42190:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   42191:      *
                   42192:      * This uses the topological sort method from graph theory, and the
                   42193:      * Structures_Graph package to properly sort dependencies for installation.
                   42194:      * @param array an array of downloaded PEAR_Downloader_Packages
                   42195:      * @return array array of array(packagefilename, package.xml contents)
                   42196:      */
                   42197:     function sortPackagesForInstall(&$packages)
                   42198:     {
                   42199:         require_once 'Structures/Graph.php';
                   42200:         require_once 'Structures/Graph/Node.php';
                   42201:         require_once 'Structures/Graph/Manipulator/TopologicalSorter.php';
                   42202:         $depgraph = new Structures_Graph(true);
                   42203:         $nodes = array();
                   42204:         $reg = &$this->config->getRegistry();
                   42205:         foreach ($packages as $i => $package) {
                   42206:             $pname = $reg->parsedPackageNameToString(
                   42207:                 array(
                   42208:                     'channel' => $package->getChannel(),
                   42209:                     'package' => strtolower($package->getPackage()),
                   42210:                 ));
                   42211:             $nodes[$pname] = new Structures_Graph_Node;
                   42212:             $nodes[$pname]->setData($packages[$i]);
                   42213:             $depgraph->addNode($nodes[$pname]);
                   42214:         }
                   42215: 
                   42216:         $deplinks = array();
                   42217:         foreach ($nodes as $package => $node) {
                   42218:             $pf = &$node->getData();
                   42219:             $pdeps = $pf->getDeps(true);
                   42220:             if (!$pdeps) {
                   42221:                 continue;
                   42222:             }
                   42223: 
                   42224:             if ($pf->getPackagexmlVersion() == '1.0') {
                   42225:                 foreach ($pdeps as $dep) {
                   42226:                     if ($dep['type'] != 'pkg' ||
                   42227:                           (isset($dep['optional']) && $dep['optional'] == 'yes')) {
                   42228:                         continue;
                   42229:                     }
                   42230: 
                   42231:                     $dname = $reg->parsedPackageNameToString(
                   42232:                           array(
                   42233:                               'channel' => 'pear.php.net',
                   42234:                               'package' => strtolower($dep['name']),
                   42235:                           ));
                   42236: 
                   42237:                     if (isset($nodes[$dname])) {
                   42238:                         if (!isset($deplinks[$dname])) {
                   42239:                             $deplinks[$dname] = array();
                   42240:                         }
                   42241: 
                   42242:                         $deplinks[$dname][$package] = 1;
                   42243:                         // dependency is in installed packages
                   42244:                         continue;
                   42245:                     }
                   42246: 
                   42247:                     $dname = $reg->parsedPackageNameToString(
                   42248:                           array(
                   42249:                               'channel' => 'pecl.php.net',
                   42250:                               'package' => strtolower($dep['name']),
                   42251:                           ));
                   42252: 
                   42253:                     if (isset($nodes[$dname])) {
                   42254:                         if (!isset($deplinks[$dname])) {
                   42255:                             $deplinks[$dname] = array();
                   42256:                         }
                   42257: 
                   42258:                         $deplinks[$dname][$package] = 1;
                   42259:                         // dependency is in installed packages
                   42260:                         continue;
                   42261:                     }
                   42262:                 }
                   42263:             } else {
                   42264:                 // the only ordering we care about is:
                   42265:                 // 1) subpackages must be installed before packages that depend on them
                   42266:                 // 2) required deps must be installed before packages that depend on them
                   42267:                 if (isset($pdeps['required']['subpackage'])) {
                   42268:                     $t = $pdeps['required']['subpackage'];
                   42269:                     if (!isset($t[0])) {
                   42270:                         $t = array($t);
                   42271:                     }
                   42272: 
                   42273:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42274:                 }
                   42275: 
                   42276:                 if (isset($pdeps['group'])) {
                   42277:                     if (!isset($pdeps['group'][0])) {
                   42278:                         $pdeps['group'] = array($pdeps['group']);
                   42279:                     }
                   42280: 
                   42281:                     foreach ($pdeps['group'] as $group) {
                   42282:                         if (isset($group['subpackage'])) {
                   42283:                             $t = $group['subpackage'];
                   42284:                             if (!isset($t[0])) {
                   42285:                                 $t = array($t);
                   42286:                             }
                   42287: 
                   42288:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42289:                         }
                   42290:                     }
                   42291:                 }
                   42292: 
                   42293:                 if (isset($pdeps['optional']['subpackage'])) {
                   42294:                     $t = $pdeps['optional']['subpackage'];
                   42295:                     if (!isset($t[0])) {
                   42296:                         $t = array($t);
                   42297:                     }
                   42298: 
                   42299:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42300:                 }
                   42301: 
                   42302:                 if (isset($pdeps['required']['package'])) {
                   42303:                     $t = $pdeps['required']['package'];
                   42304:                     if (!isset($t[0])) {
                   42305:                         $t = array($t);
                   42306:                     }
                   42307: 
                   42308:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42309:                 }
                   42310: 
                   42311:                 if (isset($pdeps['group'])) {
                   42312:                     if (!isset($pdeps['group'][0])) {
                   42313:                         $pdeps['group'] = array($pdeps['group']);
                   42314:                     }
                   42315: 
                   42316:                     foreach ($pdeps['group'] as $group) {
                   42317:                         if (isset($group['package'])) {
                   42318:                             $t = $group['package'];
                   42319:                             if (!isset($t[0])) {
                   42320:                                 $t = array($t);
                   42321:                             }
                   42322: 
                   42323:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42324:                         }
                   42325:                     }
                   42326:                 }
                   42327:             }
                   42328:         }
                   42329: 
                   42330:         $this->_detectDepCycle($deplinks);
                   42331:         foreach ($deplinks as $dependent => $parents) {
                   42332:             foreach ($parents as $parent => $unused) {
                   42333:                 $nodes[$dependent]->connectTo($nodes[$parent]);
                   42334:             }
                   42335:         }
                   42336: 
                   42337:         $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph);
                   42338:         $ret = array();
                   42339:         for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
                   42340:             foreach ($installOrder[$i] as $index => $sortedpackage) {
                   42341:                 $data = &$installOrder[$i][$index]->getData();
                   42342:                 $ret[] = &$nodes[$reg->parsedPackageNameToString(
                   42343:                           array(
                   42344:                               'channel' => $data->getChannel(),
                   42345:                               'package' => strtolower($data->getPackage()),
                   42346:                           ))]->getData();
                   42347:             }
                   42348:         }
                   42349: 
                   42350:         $packages = $ret;
                   42351:         return;
                   42352:     }
                   42353: 
                   42354:     /**
                   42355:      * Detect recursive links between dependencies and break the cycles
                   42356:      *
                   42357:      * @param array
                   42358:      * @access private
                   42359:      */
                   42360:     function _detectDepCycle(&$deplinks)
                   42361:     {
                   42362:         do {
                   42363:             $keepgoing = false;
                   42364:             foreach ($deplinks as $dep => $parents) {
                   42365:                 foreach ($parents as $parent => $unused) {
                   42366:                     // reset the parent cycle detector
                   42367:                     $this->_testCycle(null, null, null);
                   42368:                     if ($this->_testCycle($dep, $deplinks, $parent)) {
                   42369:                         $keepgoing = true;
                   42370:                         unset($deplinks[$dep][$parent]);
                   42371:                         if (count($deplinks[$dep]) == 0) {
                   42372:                             unset($deplinks[$dep]);
                   42373:                         }
                   42374: 
                   42375:                         continue 3;
                   42376:                     }
                   42377:                 }
                   42378:             }
                   42379:         } while ($keepgoing);
                   42380:     }
                   42381: 
                   42382:     function _testCycle($test, $deplinks, $dep)
                   42383:     {
                   42384:         static $visited = array();
                   42385:         if ($test === null) {
                   42386:             $visited = array();
                   42387:             return;
                   42388:         }
                   42389: 
                   42390:         // this happens when a parent has a dep cycle on another dependency
                   42391:         // but the child is not part of the cycle
                   42392:         if (isset($visited[$dep])) {
                   42393:             return false;
                   42394:         }
                   42395: 
                   42396:         $visited[$dep] = 1;
                   42397:         if ($test == $dep) {
                   42398:             return true;
                   42399:         }
                   42400: 
                   42401:         if (isset($deplinks[$dep])) {
                   42402:             if (in_array($test, array_keys($deplinks[$dep]), true)) {
                   42403:                 return true;
                   42404:             }
                   42405: 
                   42406:             foreach ($deplinks[$dep] as $parent => $unused) {
                   42407:                 if ($this->_testCycle($test, $deplinks, $parent)) {
                   42408:                     return true;
                   42409:                 }
                   42410:             }
                   42411:         }
                   42412: 
                   42413:         return false;
                   42414:     }
                   42415: 
                   42416:     /**
                   42417:      * Set up the dependency for installation parsing
                   42418:      *
                   42419:      * @param array $t dependency information
                   42420:      * @param PEAR_Registry $reg
                   42421:      * @param array $deplinks list of dependency links already established
                   42422:      * @param array $nodes all existing package nodes
                   42423:      * @param string $package parent package name
                   42424:      * @access private
                   42425:      */
                   42426:     function _setupGraph($t, $reg, &$deplinks, &$nodes, $package)
                   42427:     {
                   42428:         foreach ($t as $dep) {
                   42429:             $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
                   42430:             $dname = $reg->parsedPackageNameToString(
                   42431:                   array(
                   42432:                       'channel' => $depchannel,
                   42433:                       'package' => strtolower($dep['name']),
                   42434:                   ));
                   42435: 
                   42436:             if (isset($nodes[$dname])) {
                   42437:                 if (!isset($deplinks[$dname])) {
                   42438:                     $deplinks[$dname] = array();
                   42439:                 }
                   42440:                 $deplinks[$dname][$package] = 1;
                   42441:             }
                   42442:         }
                   42443:     }
                   42444: 
                   42445:     function _dependsOn($a, $b)
                   42446:     {
                   42447:         return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
                   42448:     }
                   42449: 
                   42450:     function _checkDepTree($channel, $package, $b, $checked = array())
                   42451:     {
                   42452:         $checked[$channel][$package] = true;
                   42453:         if (!isset($this->_depTree[$channel][$package])) {
                   42454:             return false;
                   42455:         }
                   42456: 
                   42457:         if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
                   42458:               [strtolower($b->getPackage())])) {
                   42459:             return true;
                   42460:         }
                   42461: 
                   42462:         foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
                   42463:             foreach ($packages as $pa => $true) {
                   42464:                 if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
                   42465:                     return true;
                   42466:                 }
                   42467:             }
                   42468:         }
                   42469: 
                   42470:         return false;
                   42471:     }
                   42472: 
                   42473:     function _sortInstall($a, $b)
                   42474:     {
                   42475:         if (!$a->getDeps() && !$b->getDeps()) {
                   42476:             return 0; // neither package has dependencies, order is insignificant
                   42477:         }
                   42478:         if ($a->getDeps() && !$b->getDeps()) {
                   42479:             return 1; // $a must be installed after $b because $a has dependencies
                   42480:         }
                   42481:         if (!$a->getDeps() && $b->getDeps()) {
                   42482:             return -1; // $b must be installed after $a because $b has dependencies
                   42483:         }
                   42484:         // both packages have dependencies
                   42485:         if ($this->_dependsOn($a, $b)) {
                   42486:             return 1;
                   42487:         }
                   42488:         if ($this->_dependsOn($b, $a)) {
                   42489:             return -1;
                   42490:         }
                   42491:         return 0;
                   42492:     }
                   42493: 
                   42494:     /**
                   42495:      * Download a file through HTTP.  Considers suggested file name in
                   42496:      * Content-disposition: header and can run a callback function for
                   42497:      * different events.  The callback will be called with two
                   42498:      * parameters: the callback type, and parameters.  The implemented
                   42499:      * callback types are:
                   42500:      *
                   42501:      *  'setup'       called at the very beginning, parameter is a UI object
                   42502:      *                that should be used for all output
                   42503:      *  'message'     the parameter is a string with an informational message
                   42504:      *  'saveas'      may be used to save with a different file name, the
                   42505:      *                parameter is the filename that is about to be used.
                   42506:      *                If a 'saveas' callback returns a non-empty string,
                   42507:      *                that file name will be used as the filename instead.
                   42508:      *                Note that $save_dir will not be affected by this, only
                   42509:      *                the basename of the file.
                   42510:      *  'start'       download is starting, parameter is number of bytes
                   42511:      *                that are expected, or -1 if unknown
                   42512:      *  'bytesread'   parameter is the number of bytes read so far
                   42513:      *  'done'        download is complete, parameter is the total number
                   42514:      *                of bytes read
                   42515:      *  'connfailed'  if the TCP/SSL connection fails, this callback is called
                   42516:      *                with array(host,port,errno,errmsg)
                   42517:      *  'writefailed' if writing to disk fails, this callback is called
                   42518:      *                with array(destfile,errmsg)
                   42519:      *
                   42520:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   42521:      * setting), the proxy will be used.
                   42522:      *
                   42523:      * @param string  $url       the URL to download
                   42524:      * @param object  $ui        PEAR_Frontend_* instance
                   42525:      * @param object  $config    PEAR_Config instance
                   42526:      * @param string  $save_dir  directory to save file in
                   42527:      * @param mixed   $callback  function/method to call for status
                   42528:      *                           updates
                   42529:      * @param false|string|array $lastmodified header values to check against for caching
                   42530:      *                           use false to return the header values from this download
                   42531:      * @param false|array $accept Accept headers to send
                   42532:      * @param false|string $channel Channel to use for retrieving authentication
                   42533:      * @return string|array  Returns the full path of the downloaded file or a PEAR
                   42534:      *                       error on failure.  If the error is caused by
                   42535:      *                       socket-related errors, the error object will
                   42536:      *                       have the fsockopen error code available through
                   42537:      *                       getCode().  If caching is requested, then return the header
                   42538:      *                       values.
                   42539:      *
                   42540:      * @access public
                   42541:      */
                   42542:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
                   42543:                           $accept = false, $channel = false)
                   42544:     {
                   42545:         static $redirect = 0;
                   42546:         // always reset , so we are clean case of error
                   42547:         $wasredirect = $redirect;
                   42548:         $redirect = 0;
                   42549:         if ($callback) {
                   42550:             call_user_func($callback, 'setup', array(&$ui));
                   42551:         }
                   42552: 
                   42553:         $info = parse_url($url);
                   42554:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   42555:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   42556:         }
                   42557: 
                   42558:         if (!isset($info['host'])) {
                   42559:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   42560:         }
                   42561: 
                   42562:         $host = isset($info['host']) ? $info['host'] : null;
                   42563:         $port = isset($info['port']) ? $info['port'] : null;
                   42564:         $path = isset($info['path']) ? $info['path'] : null;
                   42565: 
                   42566:         if (isset($this)) {
                   42567:             $config = &$this->config;
                   42568:         } else {
                   42569:             $config = &PEAR_Config::singleton();
                   42570:         }
                   42571: 
                   42572:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   42573:         if ($config->get('http_proxy') &&
                   42574:               $proxy = parse_url($config->get('http_proxy'))) {
                   42575:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   42576:             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
                   42577:                 $proxy_host = 'ssl://' . $proxy_host;
                   42578:             }
                   42579:             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
                   42580:             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   42581:             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   42582: 
                   42583:             if ($callback) {
                   42584:                 call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
                   42585:             }
                   42586:         }
                   42587: 
                   42588:         if (empty($port)) {
                   42589:             $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
                   42590:         }
                   42591: 
                   42592:         $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   42593: 
                   42594:         if ($proxy_host != '') {
                   42595:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr);
                   42596:             if (!$fp) {
                   42597:                 if ($callback) {
                   42598:                     call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port,
                   42599:                                                                   $errno, $errstr));
                   42600:                 }
                   42601:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno);
                   42602:             }
                   42603: 
                   42604:             if ($lastmodified === false || $lastmodified) {
                   42605:                 $request  = "GET $url HTTP/1.1\r\n";
                   42606:                 $request .= "Host: $host\r\n";
                   42607:             } else {
                   42608:                 $request  = "GET $url HTTP/1.0\r\n";
                   42609:                 $request .= "Host: $host\r\n";
                   42610:             }
                   42611:         } else {
                   42612:             $network_host = $host;
                   42613:             if (isset($info['scheme']) && $info['scheme'] == 'https') {
                   42614:                 $network_host = 'ssl://' . $host;
                   42615:             }
                   42616: 
                   42617:             $fp = @fsockopen($network_host, $port, $errno, $errstr);
                   42618:             if (!$fp) {
                   42619:                 if ($callback) {
                   42620:                     call_user_func($callback, 'connfailed', array($host, $port,
                   42621:                                                                   $errno, $errstr));
                   42622:                 }
                   42623:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   42624:             }
                   42625: 
                   42626:             if ($lastmodified === false || $lastmodified) {
                   42627:                 $request = "GET $path HTTP/1.1\r\n";
                   42628:                 $request .= "Host: $host\r\n";
                   42629:             } else {
                   42630:                 $request = "GET $path HTTP/1.0\r\n";
                   42631:                 $request .= "Host: $host\r\n";
                   42632:             }
                   42633:         }
                   42634: 
                   42635:         $ifmodifiedsince = '';
                   42636:         if (is_array($lastmodified)) {
                   42637:             if (isset($lastmodified['Last-Modified'])) {
                   42638:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   42639:             }
                   42640: 
                   42641:             if (isset($lastmodified['ETag'])) {
                   42642:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   42643:             }
                   42644:         } else {
                   42645:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   42646:         }
                   42647: 
                   42648:         $request .= $ifmodifiedsince .
                   42649:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
                   42650: 
                   42651:         if (isset($this)) { // only pass in authentication for non-static calls
                   42652:             $username = $config->get('username', null, $channel);
                   42653:             $password = $config->get('password', null, $channel);
                   42654:             if ($username && $password) {
                   42655:                 $tmp = base64_encode("$username:$password");
                   42656:                 $request .= "Authorization: Basic $tmp\r\n";
                   42657:             }
                   42658:         }
                   42659: 
                   42660:         if ($proxy_host != '' && $proxy_user != '') {
                   42661:             $request .= 'Proxy-Authorization: Basic ' .
                   42662:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   42663:         }
                   42664: 
                   42665:         if ($accept) {
                   42666:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   42667:         }
                   42668: 
                   42669:         $request .= "Connection: close\r\n";
                   42670:         $request .= "\r\n";
                   42671:         fwrite($fp, $request);
                   42672:         $headers = array();
                   42673:         $reply = 0;
                   42674:         while (trim($line = fgets($fp, 1024))) {
                   42675:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   42676:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   42677:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   42678:                 $reply = (int)$matches[1];
                   42679:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   42680:                     return false;
                   42681:                 }
                   42682: 
                   42683:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   42684:                     return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
                   42685:                 }
                   42686:             }
                   42687:         }
                   42688: 
                   42689:         if ($reply != 200) {
                   42690:             if (!isset($headers['location'])) {
                   42691:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
                   42692:             }
                   42693: 
                   42694:             if ($wasredirect > 4) {
                   42695:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
                   42696:             }
                   42697: 
                   42698:             $redirect = $wasredirect + 1;
                   42699:             return $this->downloadHttp($headers['location'],
                   42700:                     $ui, $save_dir, $callback, $lastmodified, $accept);
                   42701:         }
                   42702: 
                   42703:         if (isset($headers['content-disposition']) &&
                   42704:             preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
                   42705:             $save_as = basename($matches[1]);
                   42706:         } else {
                   42707:             $save_as = basename($url);
                   42708:         }
                   42709: 
                   42710:         if ($callback) {
                   42711:             $tmp = call_user_func($callback, 'saveas', $save_as);
                   42712:             if ($tmp) {
                   42713:                 $save_as = $tmp;
                   42714:             }
                   42715:         }
                   42716: 
                   42717:         $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
                   42718:         if (is_link($dest_file)) {
                   42719:             return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
                   42720:         }
                   42721: 
                   42722:         if (!$wp = @fopen($dest_file, 'wb')) {
                   42723:             fclose($fp);
                   42724:             if ($callback) {
                   42725:                 call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   42726:             }
                   42727:             return PEAR::raiseError("could not open $dest_file for writing");
                   42728:         }
                   42729: 
                   42730:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   42731: 
                   42732:         $bytes = 0;
                   42733:         if ($callback) {
                   42734:             call_user_func($callback, 'start', array(basename($dest_file), $length));
                   42735:         }
                   42736: 
                   42737:         while ($data = fread($fp, 1024)) {
                   42738:             $bytes += strlen($data);
                   42739:             if ($callback) {
                   42740:                 call_user_func($callback, 'bytesread', $bytes);
                   42741:             }
                   42742:             if (!@fwrite($wp, $data)) {
                   42743:                 fclose($fp);
                   42744:                 if ($callback) {
                   42745:                     call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   42746:                 }
                   42747:                 return PEAR::raiseError("$dest_file: write failed ($php_errormsg)");
                   42748:             }
                   42749:         }
                   42750: 
                   42751:         fclose($fp);
                   42752:         fclose($wp);
                   42753:         if ($callback) {
                   42754:             call_user_func($callback, 'done', $bytes);
                   42755:         }
                   42756: 
                   42757:         if ($lastmodified === false || $lastmodified) {
                   42758:             if (isset($headers['etag'])) {
                   42759:                 $lastmodified = array('ETag' => $headers['etag']);
                   42760:             }
                   42761: 
                   42762:             if (isset($headers['last-modified'])) {
                   42763:                 if (is_array($lastmodified)) {
                   42764:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   42765:                 } else {
                   42766:                     $lastmodified = $headers['last-modified'];
                   42767:                 }
                   42768:             }
                   42769:             return array($dest_file, $lastmodified, $headers);
                   42770:         }
                   42771:         return $dest_file;
                   42772:     }
                   42773: }PEAR-1.9.4/PEAR/ErrorStack.php0000644000076500000240000010225111605156760014556 0ustar  helgistaff<?php
                   42774: /**
                   42775:  * Error Stack Implementation
                   42776:  * 
                   42777:  * This is an incredibly simple implementation of a very complex error handling
                   42778:  * facility.  It contains the ability
                   42779:  * to track multiple errors from multiple packages simultaneously.  In addition,
                   42780:  * it can track errors of many levels, save data along with the error, context
                   42781:  * information such as the exact file, line number, class and function that
                   42782:  * generated the error, and if necessary, it can raise a traditional PEAR_Error.
                   42783:  * It has built-in support for PEAR::Log, to log errors as they occur
                   42784:  * 
                   42785:  * Since version 0.2alpha, it is also possible to selectively ignore errors,
                   42786:  * through the use of an error callback, see {@link pushCallback()}
                   42787:  * 
                   42788:  * Since version 0.3alpha, it is possible to specify the exception class
                   42789:  * returned from {@link push()}
                   42790:  *
                   42791:  * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
                   42792:  * still be done quite handily in an error callback or by manipulating the returned array
                   42793:  * @category   Debugging
                   42794:  * @package    PEAR_ErrorStack
                   42795:  * @author     Greg Beaver <cellog@php.net>
                   42796:  * @copyright  2004-2008 Greg Beaver
                   42797:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   42798:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
                   42799:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   42800:  */
                   42801: 
                   42802: /**
                   42803:  * Singleton storage
                   42804:  * 
                   42805:  * Format:
                   42806:  * <pre>
                   42807:  * array(
                   42808:  *  'package1' => PEAR_ErrorStack object,
                   42809:  *  'package2' => PEAR_ErrorStack object,
                   42810:  *  ...
                   42811:  * )
                   42812:  * </pre>
                   42813:  * @access private
                   42814:  * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
                   42815:  */
                   42816: $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
                   42817: 
                   42818: /**
                   42819:  * Global error callback (default)
                   42820:  * 
                   42821:  * This is only used if set to non-false.  * is the default callback for
                   42822:  * all packages, whereas specific packages may set a default callback
                   42823:  * for all instances, regardless of whether they are a singleton or not.
                   42824:  *
                   42825:  * To exclude non-singletons, only set the local callback for the singleton
                   42826:  * @see PEAR_ErrorStack::setDefaultCallback()
                   42827:  * @access private
                   42828:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
                   42829:  */
                   42830: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
                   42831:     '*' => false,
                   42832: );
                   42833: 
                   42834: /**
                   42835:  * Global Log object (default)
                   42836:  * 
                   42837:  * This is only used if set to non-false.  Use to set a default log object for
                   42838:  * all stacks, regardless of instantiation order or location
                   42839:  * @see PEAR_ErrorStack::setDefaultLogger()
                   42840:  * @access private
                   42841:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   42842:  */
                   42843: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
                   42844: 
                   42845: /**
                   42846:  * Global Overriding Callback
                   42847:  * 
                   42848:  * This callback will override any error callbacks that specific loggers have set.
                   42849:  * Use with EXTREME caution
                   42850:  * @see PEAR_ErrorStack::staticPushCallback()
                   42851:  * @access private
                   42852:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   42853:  */
                   42854: $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   42855: 
                   42856: /**#@+
                   42857:  * One of four possible return values from the error Callback
                   42858:  * @see PEAR_ErrorStack::_errorCallback()
                   42859:  */
                   42860: /**
                   42861:  * If this is returned, then the error will be both pushed onto the stack
                   42862:  * and logged.
                   42863:  */
                   42864: define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
                   42865: /**
                   42866:  * If this is returned, then the error will only be pushed onto the stack,
                   42867:  * and not logged.
                   42868:  */
                   42869: define('PEAR_ERRORSTACK_PUSH', 2);
                   42870: /**
                   42871:  * If this is returned, then the error will only be logged, but not pushed
                   42872:  * onto the error stack.
                   42873:  */
                   42874: define('PEAR_ERRORSTACK_LOG', 3);
                   42875: /**
                   42876:  * If this is returned, then the error is completely ignored.
                   42877:  */
                   42878: define('PEAR_ERRORSTACK_IGNORE', 4);
                   42879: /**
                   42880:  * If this is returned, then the error is logged and die() is called.
                   42881:  */
                   42882: define('PEAR_ERRORSTACK_DIE', 5);
                   42883: /**#@-*/
                   42884: 
                   42885: /**
                   42886:  * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
                   42887:  * the singleton method.
                   42888:  */
                   42889: define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
                   42890: 
                   42891: /**
                   42892:  * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
                   42893:  * that has no __toString() method
                   42894:  */
                   42895: define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
                   42896: /**
                   42897:  * Error Stack Implementation
                   42898:  *
                   42899:  * Usage:
                   42900:  * <code>
                   42901:  * // global error stack
                   42902:  * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
                   42903:  * // local error stack
                   42904:  * $local_stack = new PEAR_ErrorStack('MyPackage');
                   42905:  * </code>
                   42906:  * @author     Greg Beaver <cellog@php.net>
                   42907:  * @version    1.9.4
                   42908:  * @package    PEAR_ErrorStack
                   42909:  * @category   Debugging
                   42910:  * @copyright  2004-2008 Greg Beaver
                   42911:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   42912:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
                   42913:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   42914:  */
                   42915: class PEAR_ErrorStack {
                   42916:     /**
                   42917:      * Errors are stored in the order that they are pushed on the stack.
                   42918:      * @since 0.4alpha Errors are no longer organized by error level.
                   42919:      * This renders pop() nearly unusable, and levels could be more easily
                   42920:      * handled in a callback anyway
                   42921:      * @var array
                   42922:      * @access private
                   42923:      */
                   42924:     var $_errors = array();
                   42925: 
                   42926:     /**
                   42927:      * Storage of errors by level.
                   42928:      *
                   42929:      * Allows easy retrieval and deletion of only errors from a particular level
                   42930:      * @since PEAR 1.4.0dev
                   42931:      * @var array
                   42932:      * @access private
                   42933:      */
                   42934:     var $_errorsByLevel = array();
                   42935: 
                   42936:     /**
                   42937:      * Package name this error stack represents
                   42938:      * @var string
                   42939:      * @access protected
                   42940:      */
                   42941:     var $_package;
                   42942:     
                   42943:     /**
                   42944:      * Determines whether a PEAR_Error is thrown upon every error addition
                   42945:      * @var boolean
                   42946:      * @access private
                   42947:      */
                   42948:     var $_compat = false;
                   42949:     
                   42950:     /**
                   42951:      * If set to a valid callback, this will be used to generate the error
                   42952:      * message from the error code, otherwise the message passed in will be
                   42953:      * used
                   42954:      * @var false|string|array
                   42955:      * @access private
                   42956:      */
                   42957:     var $_msgCallback = false;
                   42958:     
                   42959:     /**
                   42960:      * If set to a valid callback, this will be used to generate the error
                   42961:      * context for an error.  For PHP-related errors, this will be a file
                   42962:      * and line number as retrieved from debug_backtrace(), but can be
                   42963:      * customized for other purposes.  The error might actually be in a separate
                   42964:      * configuration file, or in a database query.
                   42965:      * @var false|string|array
                   42966:      * @access protected
                   42967:      */
                   42968:     var $_contextCallback = false;
                   42969:     
                   42970:     /**
                   42971:      * If set to a valid callback, this will be called every time an error
                   42972:      * is pushed onto the stack.  The return value will be used to determine
                   42973:      * whether to allow an error to be pushed or logged.
                   42974:      * 
                   42975:      * The return value must be one an PEAR_ERRORSTACK_* constant
                   42976:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   42977:      * @var false|string|array
                   42978:      * @access protected
                   42979:      */
                   42980:     var $_errorCallback = array();
                   42981:     
                   42982:     /**
                   42983:      * PEAR::Log object for logging errors
                   42984:      * @var false|Log
                   42985:      * @access protected
                   42986:      */
                   42987:     var $_logger = false;
                   42988:     
                   42989:     /**
                   42990:      * Error messages - designed to be overridden
                   42991:      * @var array
                   42992:      * @abstract
                   42993:      */
                   42994:     var $_errorMsgs = array();
                   42995:     
                   42996:     /**
                   42997:      * Set up a new error stack
                   42998:      * 
                   42999:      * @param string   $package name of the package this error stack represents
                   43000:      * @param callback $msgCallback callback used for error message generation
                   43001:      * @param callback $contextCallback callback used for context generation,
                   43002:      *                 defaults to {@link getFileLine()}
                   43003:      * @param boolean  $throwPEAR_Error
                   43004:      */
                   43005:     function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
                   43006:                          $throwPEAR_Error = false)
                   43007:     {
                   43008:         $this->_package = $package;
                   43009:         $this->setMessageCallback($msgCallback);
                   43010:         $this->setContextCallback($contextCallback);
                   43011:         $this->_compat = $throwPEAR_Error;
                   43012:     }
                   43013:     
                   43014:     /**
                   43015:      * Return a single error stack for this package.
                   43016:      * 
                   43017:      * Note that all parameters are ignored if the stack for package $package
                   43018:      * has already been instantiated
                   43019:      * @param string   $package name of the package this error stack represents
                   43020:      * @param callback $msgCallback callback used for error message generation
                   43021:      * @param callback $contextCallback callback used for context generation,
                   43022:      *                 defaults to {@link getFileLine()}
                   43023:      * @param boolean  $throwPEAR_Error
                   43024:      * @param string   $stackClass class to instantiate
                   43025:      * @static
                   43026:      * @return PEAR_ErrorStack
                   43027:      */
                   43028:     function &singleton($package, $msgCallback = false, $contextCallback = false,
                   43029:                          $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
                   43030:     {
                   43031:         if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43032:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   43033:         }
                   43034:         if (!class_exists($stackClass)) {
                   43035:             if (function_exists('debug_backtrace')) {
                   43036:                 $trace = debug_backtrace();
                   43037:             }
                   43038:             PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
                   43039:                 'exception', array('stackclass' => $stackClass),
                   43040:                 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
                   43041:                 false, $trace);
                   43042:         }
                   43043:         $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
                   43044:             new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
                   43045: 
                   43046:         return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   43047:     }
                   43048: 
                   43049:     /**
                   43050:      * Internal error handler for PEAR_ErrorStack class
                   43051:      * 
                   43052:      * Dies if the error is an exception (and would have died anyway)
                   43053:      * @access private
                   43054:      */
                   43055:     function _handleError($err)
                   43056:     {
                   43057:         if ($err['level'] == 'exception') {
                   43058:             $message = $err['message'];
                   43059:             if (isset($_SERVER['REQUEST_URI'])) {
                   43060:                 echo '<br />';
                   43061:             } else {
                   43062:                 echo "\n";
                   43063:             }
                   43064:             var_dump($err['context']);
                   43065:             die($message);
                   43066:         }
                   43067:     }
                   43068:     
                   43069:     /**
                   43070:      * Set up a PEAR::Log object for all error stacks that don't have one
                   43071:      * @param Log $log 
                   43072:      * @static
                   43073:      */
                   43074:     function setDefaultLogger(&$log)
                   43075:     {
                   43076:         if (is_object($log) && method_exists($log, 'log') ) {
                   43077:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   43078:         } elseif (is_callable($log)) {
                   43079:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   43080:        }
                   43081:     }
                   43082:     
                   43083:     /**
                   43084:      * Set up a PEAR::Log object for this error stack
                   43085:      * @param Log $log 
                   43086:      */
                   43087:     function setLogger(&$log)
                   43088:     {
                   43089:         if (is_object($log) && method_exists($log, 'log') ) {
                   43090:             $this->_logger = &$log;
                   43091:         } elseif (is_callable($log)) {
                   43092:             $this->_logger = &$log;
                   43093:         }
                   43094:     }
                   43095:     
                   43096:     /**
                   43097:      * Set an error code => error message mapping callback
                   43098:      * 
                   43099:      * This method sets the callback that can be used to generate error
                   43100:      * messages for any instance
                   43101:      * @param array|string Callback function/method
                   43102:      */
                   43103:     function setMessageCallback($msgCallback)
                   43104:     {
                   43105:         if (!$msgCallback) {
                   43106:             $this->_msgCallback = array(&$this, 'getErrorMessage');
                   43107:         } else {
                   43108:             if (is_callable($msgCallback)) {
                   43109:                 $this->_msgCallback = $msgCallback;
                   43110:             }
                   43111:         }
                   43112:     }
                   43113:     
                   43114:     /**
                   43115:      * Get an error code => error message mapping callback
                   43116:      * 
                   43117:      * This method returns the current callback that can be used to generate error
                   43118:      * messages
                   43119:      * @return array|string|false Callback function/method or false if none
                   43120:      */
                   43121:     function getMessageCallback()
                   43122:     {
                   43123:         return $this->_msgCallback;
                   43124:     }
                   43125:     
                   43126:     /**
                   43127:      * Sets a default callback to be used by all error stacks
                   43128:      * 
                   43129:      * This method sets the callback that can be used to generate error
                   43130:      * messages for a singleton
                   43131:      * @param array|string Callback function/method
                   43132:      * @param string Package name, or false for all packages
                   43133:      * @static
                   43134:      */
                   43135:     function setDefaultCallback($callback = false, $package = false)
                   43136:     {
                   43137:         if (!is_callable($callback)) {
                   43138:             $callback = false;
                   43139:         }
                   43140:         $package = $package ? $package : '*';
                   43141:         $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
                   43142:     }
                   43143:     
                   43144:     /**
                   43145:      * Set a callback that generates context information (location of error) for an error stack
                   43146:      * 
                   43147:      * This method sets the callback that can be used to generate context
                   43148:      * information for an error.  Passing in NULL will disable context generation
                   43149:      * and remove the expensive call to debug_backtrace()
                   43150:      * @param array|string|null Callback function/method
                   43151:      */
                   43152:     function setContextCallback($contextCallback)
                   43153:     {
                   43154:         if ($contextCallback === null) {
                   43155:             return $this->_contextCallback = false;
                   43156:         }
                   43157:         if (!$contextCallback) {
                   43158:             $this->_contextCallback = array(&$this, 'getFileLine');
                   43159:         } else {
                   43160:             if (is_callable($contextCallback)) {
                   43161:                 $this->_contextCallback = $contextCallback;
                   43162:             }
                   43163:         }
                   43164:     }
                   43165:     
                   43166:     /**
                   43167:      * Set an error Callback
                   43168:      * If set to a valid callback, this will be called every time an error
                   43169:      * is pushed onto the stack.  The return value will be used to determine
                   43170:      * whether to allow an error to be pushed or logged.
                   43171:      * 
                   43172:      * The return value must be one of the ERRORSTACK_* constants.
                   43173:      * 
                   43174:      * This functionality can be used to emulate PEAR's pushErrorHandling, and
                   43175:      * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
                   43176:      * the error stack or logging
                   43177:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   43178:      * @see popCallback()
                   43179:      * @param string|array $cb
                   43180:      */
                   43181:     function pushCallback($cb)
                   43182:     {
                   43183:         array_push($this->_errorCallback, $cb);
                   43184:     }
                   43185:     
                   43186:     /**
                   43187:      * Remove a callback from the error callback stack
                   43188:      * @see pushCallback()
                   43189:      * @return array|string|false
                   43190:      */
                   43191:     function popCallback()
                   43192:     {
                   43193:         if (!count($this->_errorCallback)) {
                   43194:             return false;
                   43195:         }
                   43196:         return array_pop($this->_errorCallback);
                   43197:     }
                   43198:     
                   43199:     /**
                   43200:      * Set a temporary overriding error callback for every package error stack
                   43201:      *
                   43202:      * Use this to temporarily disable all existing callbacks (can be used
                   43203:      * to emulate the @ operator, for instance)
                   43204:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   43205:      * @see staticPopCallback(), pushCallback()
                   43206:      * @param string|array $cb
                   43207:      * @static
                   43208:      */
                   43209:     function staticPushCallback($cb)
                   43210:     {
                   43211:         array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
                   43212:     }
                   43213:     
                   43214:     /**
                   43215:      * Remove a temporary overriding error callback
                   43216:      * @see staticPushCallback()
                   43217:      * @return array|string|false
                   43218:      * @static
                   43219:      */
                   43220:     function staticPopCallback()
                   43221:     {
                   43222:         $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
                   43223:         if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
                   43224:             $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   43225:         }
                   43226:         return $ret;
                   43227:     }
                   43228:     
                   43229:     /**
                   43230:      * Add an error to the stack
                   43231:      * 
                   43232:      * If the message generator exists, it is called with 2 parameters.
                   43233:      *  - the current Error Stack object
                   43234:      *  - an array that is in the same format as an error.  Available indices
                   43235:      *    are 'code', 'package', 'time', 'params', 'level', and 'context'
                   43236:      * 
                   43237:      * Next, if the error should contain context information, this is
                   43238:      * handled by the context grabbing method.
                   43239:      * Finally, the error is pushed onto the proper error stack
                   43240:      * @param int    $code      Package-specific error code
                   43241:      * @param string $level     Error level.  This is NOT spell-checked
                   43242:      * @param array  $params    associative array of error parameters
                   43243:      * @param string $msg       Error message, or a portion of it if the message
                   43244:      *                          is to be generated
                   43245:      * @param array  $repackage If this error re-packages an error pushed by
                   43246:      *                          another package, place the array returned from
                   43247:      *                          {@link pop()} in this parameter
                   43248:      * @param array  $backtrace Protected parameter: use this to pass in the
                   43249:      *                          {@link debug_backtrace()} that should be used
                   43250:      *                          to find error context
                   43251:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   43252:      * thrown.  If a PEAR_Error is returned, the userinfo
                   43253:      * property is set to the following array:
                   43254:      * 
                   43255:      * <code>
                   43256:      * array(
                   43257:      *    'code' => $code,
                   43258:      *    'params' => $params,
                   43259:      *    'package' => $this->_package,
                   43260:      *    'level' => $level,
                   43261:      *    'time' => time(),
                   43262:      *    'context' => $context,
                   43263:      *    'message' => $msg,
                   43264:      * //['repackage' => $err] repackaged error array/Exception class
                   43265:      * );
                   43266:      * </code>
                   43267:      * 
                   43268:      * Normally, the previous array is returned.
                   43269:      */
                   43270:     function push($code, $level = 'error', $params = array(), $msg = false,
                   43271:                   $repackage = false, $backtrace = false)
                   43272:     {
                   43273:         $context = false;
                   43274:         // grab error context
                   43275:         if ($this->_contextCallback) {
                   43276:             if (!$backtrace) {
                   43277:                 $backtrace = debug_backtrace();
                   43278:             }
                   43279:             $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
                   43280:         }
                   43281:         
                   43282:         // save error
                   43283:         $time = explode(' ', microtime());
                   43284:         $time = $time[1] + $time[0];
                   43285:         $err = array(
                   43286:                 'code' => $code,
                   43287:                 'params' => $params,
                   43288:                 'package' => $this->_package,
                   43289:                 'level' => $level,
                   43290:                 'time' => $time,
                   43291:                 'context' => $context,
                   43292:                 'message' => $msg,
                   43293:                );
                   43294: 
                   43295:         if ($repackage) {
                   43296:             $err['repackage'] = $repackage;
                   43297:         }
                   43298: 
                   43299:         // set up the error message, if necessary
                   43300:         if ($this->_msgCallback) {
                   43301:             $msg = call_user_func_array($this->_msgCallback,
                   43302:                                         array(&$this, $err));
                   43303:             $err['message'] = $msg;
                   43304:         }        
                   43305:         $push = $log = true;
                   43306:         $die = false;
                   43307:         // try the overriding callback first
                   43308:         $callback = $this->staticPopCallback();
                   43309:         if ($callback) {
                   43310:             $this->staticPushCallback($callback);
                   43311:         }
                   43312:         if (!is_callable($callback)) {
                   43313:             // try the local callback next
                   43314:             $callback = $this->popCallback();
                   43315:             if (is_callable($callback)) {
                   43316:                 $this->pushCallback($callback);
                   43317:             } else {
                   43318:                 // try the default callback
                   43319:                 $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                   43320:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                   43321:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
                   43322:             }
                   43323:         }
                   43324:         if (is_callable($callback)) {
                   43325:             switch(call_user_func($callback, $err)){
                   43326:                case PEAR_ERRORSTACK_IGNORE: 
                   43327:                        return $err;
                   43328:                        break;
                   43329:                case PEAR_ERRORSTACK_PUSH: 
                   43330:                        $log = false;
                   43331:                        break;
                   43332:                case PEAR_ERRORSTACK_LOG: 
                   43333:                        $push = false;
                   43334:                        break;
                   43335:                case PEAR_ERRORSTACK_DIE: 
                   43336:                        $die = true;
                   43337:                        break;
                   43338:                 // anything else returned has the same effect as pushandlog
                   43339:             }
                   43340:         }
                   43341:         if ($push) {
                   43342:             array_unshift($this->_errors, $err);
                   43343:             if (!isset($this->_errorsByLevel[$err['level']])) {
                   43344:                 $this->_errorsByLevel[$err['level']] = array();
                   43345:             }
                   43346:             $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
                   43347:         }
                   43348:         if ($log) {
                   43349:             if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                   43350:                 $this->_log($err);
                   43351:             }
                   43352:         }
                   43353:         if ($die) {
                   43354:             die();
                   43355:         }
                   43356:         if ($this->_compat && $push) {
                   43357:             return $this->raiseError($msg, $code, null, null, $err);
                   43358:         }
                   43359:         return $err;
                   43360:     }
                   43361:     
                   43362:     /**
                   43363:      * Static version of {@link push()}
                   43364:      * 
                   43365:      * @param string $package   Package name this error belongs to
                   43366:      * @param int    $code      Package-specific error code
                   43367:      * @param string $level     Error level.  This is NOT spell-checked
                   43368:      * @param array  $params    associative array of error parameters
                   43369:      * @param string $msg       Error message, or a portion of it if the message
                   43370:      *                          is to be generated
                   43371:      * @param array  $repackage If this error re-packages an error pushed by
                   43372:      *                          another package, place the array returned from
                   43373:      *                          {@link pop()} in this parameter
                   43374:      * @param array  $backtrace Protected parameter: use this to pass in the
                   43375:      *                          {@link debug_backtrace()} that should be used
                   43376:      *                          to find error context
                   43377:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   43378:      *                          thrown.  see docs for {@link push()}
                   43379:      * @static
                   43380:      */
                   43381:     function staticPush($package, $code, $level = 'error', $params = array(),
                   43382:                         $msg = false, $repackage = false, $backtrace = false)
                   43383:     {
                   43384:         $s = &PEAR_ErrorStack::singleton($package);
                   43385:         if ($s->_contextCallback) {
                   43386:             if (!$backtrace) {
                   43387:                 if (function_exists('debug_backtrace')) {
                   43388:                     $backtrace = debug_backtrace();
                   43389:                 }
                   43390:             }
                   43391:         }
                   43392:         return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
                   43393:     }
                   43394:     
                   43395:     /**
                   43396:      * Log an error using PEAR::Log
                   43397:      * @param array $err Error array
                   43398:      * @param array $levels Error level => Log constant map
                   43399:      * @access protected
                   43400:      */
                   43401:     function _log($err)
                   43402:     {
                   43403:         if ($this->_logger) {
                   43404:             $logger = &$this->_logger;
                   43405:         } else {
                   43406:             $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
                   43407:         }
                   43408:         if (is_a($logger, 'Log')) {
                   43409:             $levels = array(
                   43410:                 'exception' => PEAR_LOG_CRIT,
                   43411:                 'alert' => PEAR_LOG_ALERT,
                   43412:                 'critical' => PEAR_LOG_CRIT,
                   43413:                 'error' => PEAR_LOG_ERR,
                   43414:                 'warning' => PEAR_LOG_WARNING,
                   43415:                 'notice' => PEAR_LOG_NOTICE,
                   43416:                 'info' => PEAR_LOG_INFO,
                   43417:                 'debug' => PEAR_LOG_DEBUG);
                   43418:             if (isset($levels[$err['level']])) {
                   43419:                 $level = $levels[$err['level']];
                   43420:             } else {
                   43421:                 $level = PEAR_LOG_INFO;
                   43422:             }
                   43423:             $logger->log($err['message'], $level, $err);
                   43424:         } else { // support non-standard logs
                   43425:             call_user_func($logger, $err);
                   43426:         }
                   43427:     }
                   43428: 
                   43429:     
                   43430:     /**
                   43431:      * Pop an error off of the error stack
                   43432:      * 
                   43433:      * @return false|array
                   43434:      * @since 0.4alpha it is no longer possible to specify a specific error
                   43435:      * level to return - the last error pushed will be returned, instead
                   43436:      */
                   43437:     function pop()
                   43438:     {
                   43439:         $err = @array_shift($this->_errors);
                   43440:         if (!is_null($err)) {
                   43441:             @array_pop($this->_errorsByLevel[$err['level']]);
                   43442:             if (!count($this->_errorsByLevel[$err['level']])) {
                   43443:                 unset($this->_errorsByLevel[$err['level']]);
                   43444:             }
                   43445:         }
                   43446:         return $err;
                   43447:     }
                   43448: 
                   43449:     /**
                   43450:      * Pop an error off of the error stack, static method
                   43451:      *
                   43452:      * @param string package name
                   43453:      * @return boolean
                   43454:      * @since PEAR1.5.0a1
                   43455:      */
                   43456:     function staticPop($package)
                   43457:     {
                   43458:         if ($package) {
                   43459:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43460:                 return false;
                   43461:             }
                   43462:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
                   43463:         }
                   43464:     }
                   43465: 
                   43466:     /**
                   43467:      * Determine whether there are any errors on the stack
                   43468:      * @param string|array Level name.  Use to determine if any errors
                   43469:      * of level (string), or levels (array) have been pushed
                   43470:      * @return boolean
                   43471:      */
                   43472:     function hasErrors($level = false)
                   43473:     {
                   43474:         if ($level) {
                   43475:             return isset($this->_errorsByLevel[$level]);
                   43476:         }
                   43477:         return count($this->_errors);
                   43478:     }
                   43479:     
                   43480:     /**
                   43481:      * Retrieve all errors since last purge
                   43482:      * 
                   43483:      * @param boolean set in order to empty the error stack
                   43484:      * @param string level name, to return only errors of a particular severity
                   43485:      * @return array
                   43486:      */
                   43487:     function getErrors($purge = false, $level = false)
                   43488:     {
                   43489:         if (!$purge) {
                   43490:             if ($level) {
                   43491:                 if (!isset($this->_errorsByLevel[$level])) {
                   43492:                     return array();
                   43493:                 } else {
                   43494:                     return $this->_errorsByLevel[$level];
                   43495:                 }
                   43496:             } else {
                   43497:                 return $this->_errors;
                   43498:             }
                   43499:         }
                   43500:         if ($level) {
                   43501:             $ret = $this->_errorsByLevel[$level];
                   43502:             foreach ($this->_errorsByLevel[$level] as $i => $unused) {
                   43503:                 // entries are references to the $_errors array
                   43504:                 $this->_errorsByLevel[$level][$i] = false;
                   43505:             }
                   43506:             // array_filter removes all entries === false
                   43507:             $this->_errors = array_filter($this->_errors);
                   43508:             unset($this->_errorsByLevel[$level]);
                   43509:             return $ret;
                   43510:         }
                   43511:         $ret = $this->_errors;
                   43512:         $this->_errors = array();
                   43513:         $this->_errorsByLevel = array();
                   43514:         return $ret;
                   43515:     }
                   43516:     
                   43517:     /**
                   43518:      * Determine whether there are any errors on a single error stack, or on any error stack
                   43519:      *
                   43520:      * The optional parameter can be used to test the existence of any errors without the need of
                   43521:      * singleton instantiation
                   43522:      * @param string|false Package name to check for errors
                   43523:      * @param string Level name to check for a particular severity
                   43524:      * @return boolean
                   43525:      * @static
                   43526:      */
                   43527:     function staticHasErrors($package = false, $level = false)
                   43528:     {
                   43529:         if ($package) {
                   43530:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43531:                 return false;
                   43532:             }
                   43533:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
                   43534:         }
                   43535:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   43536:             if ($obj->hasErrors($level)) {
                   43537:                 return true;
                   43538:             }
                   43539:         }
                   43540:         return false;
                   43541:     }
                   43542:     
                   43543:     /**
                   43544:      * Get a list of all errors since last purge, organized by package
                   43545:      * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
                   43546:      * @param boolean $purge Set to purge the error stack of existing errors
                   43547:      * @param string  $level Set to a level name in order to retrieve only errors of a particular level
                   43548:      * @param boolean $merge Set to return a flat array, not organized by package
                   43549:      * @param array   $sortfunc Function used to sort a merged array - default
                   43550:      *        sorts by time, and should be good for most cases
                   43551:      * @static
                   43552:      * @return array 
                   43553:      */
                   43554:     function staticGetErrors($purge = false, $level = false, $merge = false,
                   43555:                              $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
                   43556:     {
                   43557:         $ret = array();
                   43558:         if (!is_callable($sortfunc)) {
                   43559:             $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
                   43560:         }
                   43561:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   43562:             $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
                   43563:             if ($test) {
                   43564:                 if ($merge) {
                   43565:                     $ret = array_merge($ret, $test);
                   43566:                 } else {
                   43567:                     $ret[$package] = $test;
                   43568:                 }
                   43569:             }
                   43570:         }
                   43571:         if ($merge) {
                   43572:             usort($ret, $sortfunc);
                   43573:         }
                   43574:         return $ret;
                   43575:     }
                   43576:     
                   43577:     /**
                   43578:      * Error sorting function, sorts by time
                   43579:      * @access private
                   43580:      */
                   43581:     function _sortErrors($a, $b)
                   43582:     {
                   43583:         if ($a['time'] == $b['time']) {
                   43584:             return 0;
                   43585:         }
                   43586:         if ($a['time'] < $b['time']) {
                   43587:             return 1;
                   43588:         }
                   43589:         return -1;
                   43590:     }
                   43591: 
                   43592:     /**
                   43593:      * Standard file/line number/function/class context callback
                   43594:      *
                   43595:      * This function uses a backtrace generated from {@link debug_backtrace()}
                   43596:      * and so will not work at all in PHP < 4.3.0.  The frame should
                   43597:      * reference the frame that contains the source of the error.
                   43598:      * @return array|false either array('file' => file, 'line' => line,
                   43599:      *         'function' => function name, 'class' => class name) or
                   43600:      *         if this doesn't work, then false
                   43601:      * @param unused
                   43602:      * @param integer backtrace frame.
                   43603:      * @param array Results of debug_backtrace()
                   43604:      * @static
                   43605:      */
                   43606:     function getFileLine($code, $params, $backtrace = null)
                   43607:     {
                   43608:         if ($backtrace === null) {
                   43609:             return false;
                   43610:         }
                   43611:         $frame = 0;
                   43612:         $functionframe = 1;
                   43613:         if (!isset($backtrace[1])) {
                   43614:             $functionframe = 0;
                   43615:         } else {
                   43616:             while (isset($backtrace[$functionframe]['function']) &&
                   43617:                   $backtrace[$functionframe]['function'] == 'eval' &&
                   43618:                   isset($backtrace[$functionframe + 1])) {
                   43619:                 $functionframe++;
                   43620:             }
                   43621:         }
                   43622:         if (isset($backtrace[$frame])) {
                   43623:             if (!isset($backtrace[$frame]['file'])) {
                   43624:                 $frame++;
                   43625:             }
                   43626:             $funcbacktrace = $backtrace[$functionframe];
                   43627:             $filebacktrace = $backtrace[$frame];
                   43628:             $ret = array('file' => $filebacktrace['file'],
                   43629:                          'line' => $filebacktrace['line']);
                   43630:             // rearrange for eval'd code or create function errors
                   43631:             if (strpos($filebacktrace['file'], '(') && 
                   43632:                  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
                   43633:                   $matches)) {
                   43634:                 $ret['file'] = $matches[1];
                   43635:                 $ret['line'] = $matches[2] + 0;
                   43636:             }
                   43637:             if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
                   43638:                 if ($funcbacktrace['function'] != 'eval') {
                   43639:                     if ($funcbacktrace['function'] == '__lambda_func') {
                   43640:                         $ret['function'] = 'create_function() code';
                   43641:                     } else {
                   43642:                         $ret['function'] = $funcbacktrace['function'];
                   43643:                     }
                   43644:                 }
                   43645:             }
                   43646:             if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
                   43647:                 $ret['class'] = $funcbacktrace['class'];
                   43648:             }
                   43649:             return $ret;
                   43650:         }
                   43651:         return false;
                   43652:     }
                   43653:     
                   43654:     /**
                   43655:      * Standard error message generation callback
                   43656:      * 
                   43657:      * This method may also be called by a custom error message generator
                   43658:      * to fill in template values from the params array, simply
                   43659:      * set the third parameter to the error message template string to use
                   43660:      * 
                   43661:      * The special variable %__msg% is reserved: use it only to specify
                   43662:      * where a message passed in by the user should be placed in the template,
                   43663:      * like so:
                   43664:      * 
                   43665:      * Error message: %msg% - internal error
                   43666:      * 
                   43667:      * If the message passed like so:
                   43668:      * 
                   43669:      * <code>
                   43670:      * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
                   43671:      * </code>
                   43672:      * 
                   43673:      * The returned error message will be "Error message: server error 500 -
                   43674:      * internal error"
                   43675:      * @param PEAR_ErrorStack
                   43676:      * @param array
                   43677:      * @param string|false Pre-generated error message template
                   43678:      * @static
                   43679:      * @return string
                   43680:      */
                   43681:     function getErrorMessage(&$stack, $err, $template = false)
                   43682:     {
                   43683:         if ($template) {
                   43684:             $mainmsg = $template;
                   43685:         } else {
                   43686:             $mainmsg = $stack->getErrorMessageTemplate($err['code']);
                   43687:         }
                   43688:         $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
                   43689:         if (is_array($err['params']) && count($err['params'])) {
                   43690:             foreach ($err['params'] as $name => $val) {
                   43691:                 if (is_array($val)) {
                   43692:                     // @ is needed in case $val is a multi-dimensional array
                   43693:                     $val = @implode(', ', $val);
                   43694:                 }
                   43695:                 if (is_object($val)) {
                   43696:                     if (method_exists($val, '__toString')) {
                   43697:                         $val = $val->__toString();
                   43698:                     } else {
                   43699:                         PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
                   43700:                             'warning', array('obj' => get_class($val)),
                   43701:                             'object %obj% passed into getErrorMessage, but has no __toString() method');
                   43702:                         $val = 'Object';
                   43703:                     }
                   43704:                 }
                   43705:                 $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
                   43706:             }
                   43707:         }
                   43708:         return $mainmsg;
                   43709:     }
                   43710:     
                   43711:     /**
                   43712:      * Standard Error Message Template generator from code
                   43713:      * @return string
                   43714:      */
                   43715:     function getErrorMessageTemplate($code)
                   43716:     {
                   43717:         if (!isset($this->_errorMsgs[$code])) {
                   43718:             return '%__msg%';
                   43719:         }
                   43720:         return $this->_errorMsgs[$code];
                   43721:     }
                   43722:     
                   43723:     /**
                   43724:      * Set the Error Message Template array
                   43725:      * 
                   43726:      * The array format must be:
                   43727:      * <pre>
                   43728:      * array(error code => 'message template',...)
                   43729:      * </pre>
                   43730:      * 
                   43731:      * Error message parameters passed into {@link push()} will be used as input
                   43732:      * for the error message.  If the template is 'message %foo% was %bar%', and the
                   43733:      * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
                   43734:      * be 'message one was six'
                   43735:      * @return string
                   43736:      */
                   43737:     function setErrorMessageTemplate($template)
                   43738:     {
                   43739:         $this->_errorMsgs = $template;
                   43740:     }
                   43741:     
                   43742:     
                   43743:     /**
                   43744:      * emulate PEAR::raiseError()
                   43745:      * 
                   43746:      * @return PEAR_Error
                   43747:      */
                   43748:     function raiseError()
                   43749:     {
                   43750:         require_once 'PEAR.php';
                   43751:         $args = func_get_args();
                   43752:         return call_user_func_array(array('PEAR', 'raiseError'), $args);
                   43753:     }
                   43754: }
                   43755: $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
                   43756: $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
                   43757: ?>
                   43758: PEAR-1.9.4/PEAR/Exception.php0000644000076500000240000003326611605156760014446 0ustar  helgistaff<?php
                   43759: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   43760: /**
                   43761:  * PEAR_Exception
                   43762:  *
                   43763:  * PHP versions 4 and 5
                   43764:  *
                   43765:  * @category   pear
                   43766:  * @package    PEAR
                   43767:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   43768:  * @author     Hans Lellelid <hans@velum.net>
                   43769:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   43770:  * @author     Greg Beaver <cellog@php.net>
                   43771:  * @copyright  1997-2009 The Authors
                   43772:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   43773:  * @version    CVS: $Id: Exception.php 313023 2011-07-06 19:17:11Z dufuz $
                   43774:  * @link       http://pear.php.net/package/PEAR
                   43775:  * @since      File available since Release 1.3.3
                   43776:  */
                   43777: 
                   43778: 
                   43779: /**
                   43780:  * Base PEAR_Exception Class
                   43781:  *
                   43782:  * 1) Features:
                   43783:  *
                   43784:  * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
                   43785:  * - Definable triggers, shot when exceptions occur
                   43786:  * - Pretty and informative error messages
                   43787:  * - Added more context info available (like class, method or cause)
                   43788:  * - cause can be a PEAR_Exception or an array of mixed
                   43789:  *   PEAR_Exceptions/PEAR_ErrorStack warnings
                   43790:  * - callbacks for specific exception classes and their children
                   43791:  *
                   43792:  * 2) Ideas:
                   43793:  *
                   43794:  * - Maybe a way to define a 'template' for the output
                   43795:  *
                   43796:  * 3) Inherited properties from PHP Exception Class:
                   43797:  *
                   43798:  * protected $message
                   43799:  * protected $code
                   43800:  * protected $line
                   43801:  * protected $file
                   43802:  * private   $trace
                   43803:  *
                   43804:  * 4) Inherited methods from PHP Exception Class:
                   43805:  *
                   43806:  * __clone
                   43807:  * __construct
                   43808:  * getMessage
                   43809:  * getCode
                   43810:  * getFile
                   43811:  * getLine
                   43812:  * getTraceSafe
                   43813:  * getTraceSafeAsString
                   43814:  * __toString
                   43815:  *
                   43816:  * 5) Usage example
                   43817:  *
                   43818:  * <code>
                   43819:  *  require_once 'PEAR/Exception.php';
                   43820:  *
                   43821:  *  class Test {
                   43822:  *     function foo() {
                   43823:  *         throw new PEAR_Exception('Error Message', ERROR_CODE);
                   43824:  *     }
                   43825:  *  }
                   43826:  *
                   43827:  *  function myLogger($pear_exception) {
                   43828:  *     echo $pear_exception->getMessage();
                   43829:  *  }
                   43830:  *  // each time a exception is thrown the 'myLogger' will be called
                   43831:  *  // (its use is completely optional)
                   43832:  *  PEAR_Exception::addObserver('myLogger');
                   43833:  *  $test = new Test;
                   43834:  *  try {
                   43835:  *     $test->foo();
                   43836:  *  } catch (PEAR_Exception $e) {
                   43837:  *     print $e;
                   43838:  *  }
                   43839:  * </code>
                   43840:  *
                   43841:  * @category   pear
                   43842:  * @package    PEAR
                   43843:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   43844:  * @author     Hans Lellelid <hans@velum.net>
                   43845:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   43846:  * @author     Greg Beaver <cellog@php.net>
                   43847:  * @copyright  1997-2009 The Authors
                   43848:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   43849:  * @version    Release: 1.9.4
                   43850:  * @link       http://pear.php.net/package/PEAR
                   43851:  * @since      Class available since Release 1.3.3
                   43852:  *
                   43853:  */
                   43854: class PEAR_Exception extends Exception
                   43855: {
                   43856:     const OBSERVER_PRINT = -2;
                   43857:     const OBSERVER_TRIGGER = -4;
                   43858:     const OBSERVER_DIE = -8;
                   43859:     protected $cause;
                   43860:     private static $_observers = array();
                   43861:     private static $_uniqueid = 0;
                   43862:     private $_trace;
                   43863: 
                   43864:     /**
                   43865:      * Supported signatures:
                   43866:      *  - PEAR_Exception(string $message);
                   43867:      *  - PEAR_Exception(string $message, int $code);
                   43868:      *  - PEAR_Exception(string $message, Exception $cause);
                   43869:      *  - PEAR_Exception(string $message, Exception $cause, int $code);
                   43870:      *  - PEAR_Exception(string $message, PEAR_Error $cause);
                   43871:      *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
                   43872:      *  - PEAR_Exception(string $message, array $causes);
                   43873:      *  - PEAR_Exception(string $message, array $causes, int $code);
                   43874:      * @param string exception message
                   43875:      * @param int|Exception|PEAR_Error|array|null exception cause
                   43876:      * @param int|null exception code or null
                   43877:      */
                   43878:     public function __construct($message, $p2 = null, $p3 = null)
                   43879:     {
                   43880:         if (is_int($p2)) {
                   43881:             $code = $p2;
                   43882:             $this->cause = null;
                   43883:         } elseif (is_object($p2) || is_array($p2)) {
                   43884:             // using is_object allows both Exception and PEAR_Error
                   43885:             if (is_object($p2) && !($p2 instanceof Exception)) {
                   43886:                 if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
                   43887:                     throw new PEAR_Exception('exception cause must be Exception, ' .
                   43888:                         'array, or PEAR_Error');
                   43889:                 }
                   43890:             }
                   43891:             $code = $p3;
                   43892:             if (is_array($p2) && isset($p2['message'])) {
                   43893:                 // fix potential problem of passing in a single warning
                   43894:                 $p2 = array($p2);
                   43895:             }
                   43896:             $this->cause = $p2;
                   43897:         } else {
                   43898:             $code = null;
                   43899:             $this->cause = null;
                   43900:         }
                   43901:         parent::__construct($message, $code);
                   43902:         $this->signal();
                   43903:     }
                   43904: 
                   43905:     /**
                   43906:      * @param mixed $callback  - A valid php callback, see php func is_callable()
                   43907:      *                         - A PEAR_Exception::OBSERVER_* constant
                   43908:      *                         - An array(const PEAR_Exception::OBSERVER_*,
                   43909:      *                           mixed $options)
                   43910:      * @param string $label    The name of the observer. Use this if you want
                   43911:      *                         to remove it later with removeObserver()
                   43912:      */
                   43913:     public static function addObserver($callback, $label = 'default')
                   43914:     {
                   43915:         self::$_observers[$label] = $callback;
                   43916:     }
                   43917: 
                   43918:     public static function removeObserver($label = 'default')
                   43919:     {
                   43920:         unset(self::$_observers[$label]);
                   43921:     }
                   43922: 
                   43923:     /**
                   43924:      * @return int unique identifier for an observer
                   43925:      */
                   43926:     public static function getUniqueId()
                   43927:     {
                   43928:         return self::$_uniqueid++;
                   43929:     }
                   43930: 
                   43931:     private function signal()
                   43932:     {
                   43933:         foreach (self::$_observers as $func) {
                   43934:             if (is_callable($func)) {
                   43935:                 call_user_func($func, $this);
                   43936:                 continue;
                   43937:             }
                   43938:             settype($func, 'array');
                   43939:             switch ($func[0]) {
                   43940:                 case self::OBSERVER_PRINT :
                   43941:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   43942:                     printf($f, $this->getMessage());
                   43943:                     break;
                   43944:                 case self::OBSERVER_TRIGGER :
                   43945:                     $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
                   43946:                     trigger_error($this->getMessage(), $f);
                   43947:                     break;
                   43948:                 case self::OBSERVER_DIE :
                   43949:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   43950:                     die(printf($f, $this->getMessage()));
                   43951:                     break;
                   43952:                 default:
                   43953:                     trigger_error('invalid observer type', E_USER_WARNING);
                   43954:             }
                   43955:         }
                   43956:     }
                   43957: 
                   43958:     /**
                   43959:      * Return specific error information that can be used for more detailed
                   43960:      * error messages or translation.
                   43961:      *
                   43962:      * This method may be overridden in child exception classes in order
                   43963:      * to add functionality not present in PEAR_Exception and is a placeholder
                   43964:      * to define API
                   43965:      *
                   43966:      * The returned array must be an associative array of parameter => value like so:
                   43967:      * <pre>
                   43968:      * array('name' => $name, 'context' => array(...))
                   43969:      * </pre>
                   43970:      * @return array
                   43971:      */
                   43972:     public function getErrorData()
                   43973:     {
                   43974:         return array();
                   43975:     }
                   43976: 
                   43977:     /**
                   43978:      * Returns the exception that caused this exception to be thrown
                   43979:      * @access public
                   43980:      * @return Exception|array The context of the exception
                   43981:      */
                   43982:     public function getCause()
                   43983:     {
                   43984:         return $this->cause;
                   43985:     }
                   43986: 
                   43987:     /**
                   43988:      * Function must be public to call on caused exceptions
                   43989:      * @param array
                   43990:      */
                   43991:     public function getCauseMessage(&$causes)
                   43992:     {
                   43993:         $trace = $this->getTraceSafe();
                   43994:         $cause = array('class'   => get_class($this),
                   43995:                        'message' => $this->message,
                   43996:                        'file' => 'unknown',
                   43997:                        'line' => 'unknown');
                   43998:         if (isset($trace[0])) {
                   43999:             if (isset($trace[0]['file'])) {
                   44000:                 $cause['file'] = $trace[0]['file'];
                   44001:                 $cause['line'] = $trace[0]['line'];
                   44002:             }
                   44003:         }
                   44004:         $causes[] = $cause;
                   44005:         if ($this->cause instanceof PEAR_Exception) {
                   44006:             $this->cause->getCauseMessage($causes);
                   44007:         } elseif ($this->cause instanceof Exception) {
                   44008:             $causes[] = array('class'   => get_class($this->cause),
                   44009:                               'message' => $this->cause->getMessage(),
                   44010:                               'file' => $this->cause->getFile(),
                   44011:                               'line' => $this->cause->getLine());
                   44012:         } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
                   44013:             $causes[] = array('class' => get_class($this->cause),
                   44014:                               'message' => $this->cause->getMessage(),
                   44015:                               'file' => 'unknown',
                   44016:                               'line' => 'unknown');
                   44017:         } elseif (is_array($this->cause)) {
                   44018:             foreach ($this->cause as $cause) {
                   44019:                 if ($cause instanceof PEAR_Exception) {
                   44020:                     $cause->getCauseMessage($causes);
                   44021:                 } elseif ($cause instanceof Exception) {
                   44022:                     $causes[] = array('class'   => get_class($cause),
                   44023:                                    'message' => $cause->getMessage(),
                   44024:                                    'file' => $cause->getFile(),
                   44025:                                    'line' => $cause->getLine());
                   44026:                 } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
                   44027:                     $causes[] = array('class' => get_class($cause),
                   44028:                                       'message' => $cause->getMessage(),
                   44029:                                       'file' => 'unknown',
                   44030:                                       'line' => 'unknown');
                   44031:                 } elseif (is_array($cause) && isset($cause['message'])) {
                   44032:                     // PEAR_ErrorStack warning
                   44033:                     $causes[] = array(
                   44034:                         'class' => $cause['package'],
                   44035:                         'message' => $cause['message'],
                   44036:                         'file' => isset($cause['context']['file']) ?
                   44037:                                             $cause['context']['file'] :
                   44038:                                             'unknown',
                   44039:                         'line' => isset($cause['context']['line']) ?
                   44040:                                             $cause['context']['line'] :
                   44041:                                             'unknown',
                   44042:                     );
                   44043:                 }
                   44044:             }
                   44045:         }
                   44046:     }
                   44047: 
                   44048:     public function getTraceSafe()
                   44049:     {
                   44050:         if (!isset($this->_trace)) {
                   44051:             $this->_trace = $this->getTrace();
                   44052:             if (empty($this->_trace)) {
                   44053:                 $backtrace = debug_backtrace();
                   44054:                 $this->_trace = array($backtrace[count($backtrace)-1]);
                   44055:             }
                   44056:         }
                   44057:         return $this->_trace;
                   44058:     }
                   44059: 
                   44060:     public function getErrorClass()
                   44061:     {
                   44062:         $trace = $this->getTraceSafe();
                   44063:         return $trace[0]['class'];
                   44064:     }
                   44065: 
                   44066:     public function getErrorMethod()
                   44067:     {
                   44068:         $trace = $this->getTraceSafe();
                   44069:         return $trace[0]['function'];
                   44070:     }
                   44071: 
                   44072:     public function __toString()
                   44073:     {
                   44074:         if (isset($_SERVER['REQUEST_URI'])) {
                   44075:             return $this->toHtml();
                   44076:         }
                   44077:         return $this->toText();
                   44078:     }
                   44079: 
                   44080:     public function toHtml()
                   44081:     {
                   44082:         $trace = $this->getTraceSafe();
                   44083:         $causes = array();
                   44084:         $this->getCauseMessage($causes);
                   44085:         $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
                   44086:         foreach ($causes as $i => $cause) {
                   44087:             $html .= '<tr><td colspan="3" style="background: #ff9999">'
                   44088:                . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
                   44089:                . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
                   44090:                . 'on line <b>' . $cause['line'] . '</b>'
                   44091:                . "</td></tr>\n";
                   44092:         }
                   44093:         $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
                   44094:                . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
                   44095:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
                   44096:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
                   44097: 
                   44098:         foreach ($trace as $k => $v) {
                   44099:             $html .= '<tr><td style="text-align: center;">' . $k . '</td>'
                   44100:                    . '<td>';
                   44101:             if (!empty($v['class'])) {
                   44102:                 $html .= $v['class'] . $v['type'];
                   44103:             }
                   44104:             $html .= $v['function'];
                   44105:             $args = array();
                   44106:             if (!empty($v['args'])) {
                   44107:                 foreach ($v['args'] as $arg) {
                   44108:                     if (is_null($arg)) $args[] = 'null';
                   44109:                     elseif (is_array($arg)) $args[] = 'Array';
                   44110:                     elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
                   44111:                     elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
                   44112:                     elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
                   44113:                     else {
                   44114:                         $arg = (string)$arg;
                   44115:                         $str = htmlspecialchars(substr($arg, 0, 16));
                   44116:                         if (strlen($arg) > 16) $str .= '&hellip;';
                   44117:                         $args[] = "'" . $str . "'";
                   44118:                     }
                   44119:                 }
                   44120:             }
                   44121:             $html .= '(' . implode(', ',$args) . ')'
                   44122:                    . '</td>'
                   44123:                    . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
                   44124:                    . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
                   44125:                    . '</td></tr>' . "\n";
                   44126:         }
                   44127:         $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
                   44128:                . '<td>{main}</td>'
                   44129:                . '<td>&nbsp;</td></tr>' . "\n"
                   44130:                . '</table>';
                   44131:         return $html;
                   44132:     }
                   44133: 
                   44134:     public function toText()
                   44135:     {
                   44136:         $causes = array();
                   44137:         $this->getCauseMessage($causes);
                   44138:         $causeMsg = '';
                   44139:         foreach ($causes as $i => $cause) {
                   44140:             $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
                   44141:                    . $cause['message'] . ' in ' . $cause['file']
                   44142:                    . ' on line ' . $cause['line'] . "\n";
                   44143:         }
                   44144:         return $causeMsg . $this->getTraceAsString();
                   44145:     }
                   44146: }PEAR-1.9.4/PEAR/FixPHP5PEARWarnings.php0000644000076500000240000000023111605156760016036 0ustar  helgistaff<?php
                   44147: if ($skipmsg) {
                   44148:     $a = &new $ec($code, $mode, $options, $userinfo);
                   44149: } else {
                   44150:     $a = &new $ec($message, $code, $mode, $options, $userinfo);
                   44151: }
                   44152: ?>PEAR-1.9.4/PEAR/Frontend.php0000644000076500000240000001507711605156760014267 0ustar  helgistaff<?php
                   44153: /**
                   44154:  * PEAR_Frontend, the singleton-based frontend for user input/output
                   44155:  *
                   44156:  * PHP versions 4 and 5
                   44157:  *
                   44158:  * @category   pear
                   44159:  * @package    PEAR
                   44160:  * @author     Greg Beaver <cellog@php.net>
                   44161:  * @copyright  1997-2009 The Authors
                   44162:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44163:  * @version    CVS: $Id: Frontend.php 313023 2011-07-06 19:17:11Z dufuz $
                   44164:  * @link       http://pear.php.net/package/PEAR
                   44165:  * @since      File available since Release 1.4.0a1
                   44166:  */
                   44167: 
                   44168: /**
                   44169:  * Include error handling
                   44170:  */
                   44171: //require_once 'PEAR.php';
                   44172: 
                   44173: /**
                   44174:  * Which user interface class is being used.
                   44175:  * @var string class name
                   44176:  */
                   44177: $GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
                   44178: 
                   44179: /**
                   44180:  * Instance of $_PEAR_Command_uiclass.
                   44181:  * @var object
                   44182:  */
                   44183: $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
                   44184: 
                   44185: /**
                   44186:  * Singleton-based frontend for PEAR user input/output
                   44187:  *
                   44188:  * @category   pear
                   44189:  * @package    PEAR
                   44190:  * @author     Greg Beaver <cellog@php.net>
                   44191:  * @copyright  1997-2009 The Authors
                   44192:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44193:  * @version    Release: 1.9.4
                   44194:  * @link       http://pear.php.net/package/PEAR
                   44195:  * @since      Class available since Release 1.4.0a1
                   44196:  */
                   44197: class PEAR_Frontend extends PEAR
                   44198: {
                   44199:     /**
                   44200:      * Retrieve the frontend object
                   44201:      * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
                   44202:      * @static
                   44203:      */
                   44204:     function &singleton($type = null)
                   44205:     {
                   44206:         if ($type === null) {
                   44207:             if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
                   44208:                 $a = false;
                   44209:                 return $a;
                   44210:             }
                   44211:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44212:         }
                   44213: 
                   44214:         $a = PEAR_Frontend::setFrontendClass($type);
                   44215:         return $a;
                   44216:     }
                   44217: 
                   44218:     /**
                   44219:      * Set the frontend class that will be used by calls to {@link singleton()}
                   44220:      *
                   44221:      * Frontends are expected to conform to the PEAR naming standard of
                   44222:      * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
                   44223:      * @param string $uiclass full class name
                   44224:      * @return PEAR_Frontend
                   44225:      * @static
                   44226:      */
                   44227:     function &setFrontendClass($uiclass)
                   44228:     {
                   44229:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   44230:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
                   44231:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44232:         }
                   44233: 
                   44234:         if (!class_exists($uiclass)) {
                   44235:             $file = str_replace('_', '/', $uiclass) . '.php';
                   44236:             if (PEAR_Frontend::isIncludeable($file)) {
                   44237:                 include_once $file;
                   44238:             }
                   44239:         }
                   44240: 
                   44241:         if (class_exists($uiclass)) {
                   44242:             $obj = &new $uiclass;
                   44243:             // quick test to see if this class implements a few of the most
                   44244:             // important frontend methods
                   44245:             if (is_a($obj, 'PEAR_Frontend')) {
                   44246:                 $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
                   44247:                 $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
                   44248:                 return $obj;
                   44249:             }
                   44250: 
                   44251:             $err = PEAR::raiseError("not a frontend class: $uiclass");
                   44252:             return $err;
                   44253:         }
                   44254: 
                   44255:         $err = PEAR::raiseError("no such class: $uiclass");
                   44256:         return $err;
                   44257:     }
                   44258: 
                   44259:     /**
                   44260:      * Set the frontend class that will be used by calls to {@link singleton()}
                   44261:      *
                   44262:      * Frontends are expected to be a descendant of PEAR_Frontend
                   44263:      * @param PEAR_Frontend
                   44264:      * @return PEAR_Frontend
                   44265:      * @static
                   44266:      */
                   44267:     function &setFrontendObject($uiobject)
                   44268:     {
                   44269:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   44270:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
                   44271:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44272:         }
                   44273: 
                   44274:         if (!is_a($uiobject, 'PEAR_Frontend')) {
                   44275:             $err = PEAR::raiseError('not a valid frontend class: (' .
                   44276:                 get_class($uiobject) . ')');
                   44277:             return $err;
                   44278:         }
                   44279: 
                   44280:         $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
                   44281:         $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
                   44282:         return $uiobject;
                   44283:     }
                   44284: 
                   44285:     /**
                   44286:      * @param string $path relative or absolute include path
                   44287:      * @return boolean
                   44288:      * @static
                   44289:      */
                   44290:     function isIncludeable($path)
                   44291:     {
                   44292:         if (file_exists($path) && is_readable($path)) {
                   44293:             return true;
                   44294:         }
                   44295: 
                   44296:         $fp = @fopen($path, 'r', true);
                   44297:         if ($fp) {
                   44298:             fclose($fp);
                   44299:             return true;
                   44300:         }
                   44301: 
                   44302:         return false;
                   44303:     }
                   44304: 
                   44305:     /**
                   44306:      * @param PEAR_Config
                   44307:      */
                   44308:     function setConfig(&$config)
                   44309:     {
                   44310:     }
                   44311: 
                   44312:     /**
                   44313:      * This can be overridden to allow session-based temporary file management
                   44314:      *
                   44315:      * By default, all files are deleted at the end of a session.  The web installer
                   44316:      * needs to be able to sustain a list over many sessions in order to support
                   44317:      * user interaction with install scripts
                   44318:      */
                   44319:     function addTempFile($file)
                   44320:     {
                   44321:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   44322:     }
                   44323: 
                   44324:     /**
                   44325:      * Log an action
                   44326:      *
                   44327:      * @param string $msg the message to log
                   44328:      * @param boolean $append_crlf
                   44329:      * @return boolean true
                   44330:      * @abstract
                   44331:      */
                   44332:     function log($msg, $append_crlf = true)
                   44333:     {
                   44334:     }
                   44335: 
                   44336:     /**
                   44337:      * Run a post-installation script
                   44338:      *
                   44339:      * @param array $scripts array of post-install scripts
                   44340:      * @abstract
                   44341:      */
                   44342:     function runPostinstallScripts(&$scripts)
                   44343:     {
                   44344:     }
                   44345: 
                   44346:     /**
                   44347:      * Display human-friendly output formatted depending on the
                   44348:      * $command parameter.
                   44349:      *
                   44350:      * This should be able to handle basic output data with no command
                   44351:      * @param mixed  $data    data structure containing the information to display
                   44352:      * @param string $command command from which this method was called
                   44353:      * @abstract
                   44354:      */
                   44355:     function outputData($data, $command = '_default')
                   44356:     {
                   44357:     }
                   44358: 
                   44359:     /**
                   44360:      * Display a modal form dialog and return the given input
                   44361:      *
                   44362:      * A frontend that requires multiple requests to retrieve and process
                   44363:      * data must take these needs into account, and implement the request
                   44364:      * handling code.
                   44365:      * @param string $command  command from which this method was called
                   44366:      * @param array  $prompts  associative array. keys are the input field names
                   44367:      *                         and values are the description
                   44368:      * @param array  $types    array of input field types (text, password,
                   44369:      *                         etc.) keys have to be the same like in $prompts
                   44370:      * @param array  $defaults array of default values. again keys have
                   44371:      *                         to be the same like in $prompts.  Do not depend
                   44372:      *                         on a default value being set.
                   44373:      * @return array input sent by the user
                   44374:      * @abstract
                   44375:      */
                   44376:     function userDialog($command, $prompts, $types = array(), $defaults = array())
                   44377:     {
                   44378:     }
                   44379: }PEAR-1.9.4/PEAR/Installer.php0000644000076500000240000021147511605156760014445 0ustar  helgistaff<?php
                   44380: /**
                   44381:  * PEAR_Installer
                   44382:  *
                   44383:  * PHP versions 4 and 5
                   44384:  *
                   44385:  * @category   pear
                   44386:  * @package    PEAR
                   44387:  * @author     Stig Bakken <ssb@php.net>
                   44388:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   44389:  * @author     Martin Jansen <mj@php.net>
                   44390:  * @author     Greg Beaver <cellog@php.net>
                   44391:  * @copyright  1997-2009 The Authors
                   44392:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44393:  * @version    CVS: $Id: Installer.php 313024 2011-07-06 19:51:24Z dufuz $
                   44394:  * @link       http://pear.php.net/package/PEAR
                   44395:  * @since      File available since Release 0.1
                   44396:  */
                   44397: 
                   44398: /**
                   44399:  * Used for installation groups in package.xml 2.0 and platform exceptions
                   44400:  */
                   44401: require_once 'OS/Guess.php';
                   44402: require_once 'PEAR/Downloader.php';
                   44403: 
                   44404: define('PEAR_INSTALLER_NOBINARY', -240);
                   44405: /**
                   44406:  * Administration class used to install PEAR packages and maintain the
                   44407:  * installed package database.
                   44408:  *
                   44409:  * @category   pear
                   44410:  * @package    PEAR
                   44411:  * @author     Stig Bakken <ssb@php.net>
                   44412:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   44413:  * @author     Martin Jansen <mj@php.net>
                   44414:  * @author     Greg Beaver <cellog@php.net>
                   44415:  * @copyright  1997-2009 The Authors
                   44416:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44417:  * @version    Release: 1.9.4
                   44418:  * @link       http://pear.php.net/package/PEAR
                   44419:  * @since      Class available since Release 0.1
                   44420:  */
                   44421: class PEAR_Installer extends PEAR_Downloader
                   44422: {
                   44423:     // {{{ properties
                   44424: 
                   44425:     /** name of the package directory, for example Foo-1.0
                   44426:      * @var string
                   44427:      */
                   44428:     var $pkgdir;
                   44429: 
                   44430:     /** directory where PHP code files go
                   44431:      * @var string
                   44432:      */
                   44433:     var $phpdir;
                   44434: 
                   44435:     /** directory where PHP extension files go
                   44436:      * @var string
                   44437:      */
                   44438:     var $extdir;
                   44439: 
                   44440:     /** directory where documentation goes
                   44441:      * @var string
                   44442:      */
                   44443:     var $docdir;
                   44444: 
                   44445:     /** installation root directory (ala PHP's INSTALL_ROOT or
                   44446:      * automake's DESTDIR
                   44447:      * @var string
                   44448:      */
                   44449:     var $installroot = '';
                   44450: 
                   44451:     /** debug level
                   44452:      * @var int
                   44453:      */
                   44454:     var $debug = 1;
                   44455: 
                   44456:     /** temporary directory
                   44457:      * @var string
                   44458:      */
                   44459:     var $tmpdir;
                   44460: 
                   44461:     /**
                   44462:      * PEAR_Registry object used by the installer
                   44463:      * @var PEAR_Registry
                   44464:      */
                   44465:     var $registry;
                   44466: 
                   44467:     /**
                   44468:      * array of PEAR_Downloader_Packages
                   44469:      * @var array
                   44470:      */
                   44471:     var $_downloadedPackages;
                   44472: 
                   44473:     /** List of file transactions queued for an install/upgrade/uninstall.
                   44474:      *
                   44475:      *  Format:
                   44476:      *    array(
                   44477:      *      0 => array("rename => array("from-file", "to-file")),
                   44478:      *      1 => array("delete" => array("file-to-delete")),
                   44479:      *      ...
                   44480:      *    )
                   44481:      *
                   44482:      * @var array
                   44483:      */
                   44484:     var $file_operations = array();
                   44485: 
                   44486:     // }}}
                   44487: 
                   44488:     // {{{ constructor
                   44489: 
                   44490:     /**
                   44491:      * PEAR_Installer constructor.
                   44492:      *
                   44493:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
                   44494:      *
                   44495:      * @access public
                   44496:      */
                   44497:     function PEAR_Installer(&$ui)
                   44498:     {
                   44499:         parent::PEAR_Common();
                   44500:         $this->setFrontendObject($ui);
                   44501:         $this->debug = $this->config->get('verbose');
                   44502:     }
                   44503: 
                   44504:     function setOptions($options)
                   44505:     {
                   44506:         $this->_options = $options;
                   44507:     }
                   44508: 
                   44509:     function setConfig(&$config)
                   44510:     {
                   44511:         $this->config    = &$config;
                   44512:         $this->_registry = &$config->getRegistry();
                   44513:     }
                   44514: 
                   44515:     // }}}
                   44516: 
                   44517:     function _removeBackups($files)
                   44518:     {
                   44519:         foreach ($files as $path) {
                   44520:             $this->addFileOperation('removebackup', array($path));
                   44521:         }
                   44522:     }
                   44523: 
                   44524:     // {{{ _deletePackageFiles()
                   44525: 
                   44526:     /**
                   44527:      * Delete a package's installed files, does not remove empty directories.
                   44528:      *
                   44529:      * @param string package name
                   44530:      * @param string channel name
                   44531:      * @param bool if true, then files are backed up first
                   44532:      * @return bool TRUE on success, or a PEAR error on failure
                   44533:      * @access protected
                   44534:      */
                   44535:     function _deletePackageFiles($package, $channel = false, $backup = false)
                   44536:     {
                   44537:         if (!$channel) {
                   44538:             $channel = 'pear.php.net';
                   44539:         }
                   44540: 
                   44541:         if (!strlen($package)) {
                   44542:             return $this->raiseError("No package to uninstall given");
                   44543:         }
                   44544: 
                   44545:         if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
                   44546:             // to avoid race conditions, include all possible needed files
                   44547:             require_once 'PEAR/Task/Common.php';
                   44548:             require_once 'PEAR/Task/Replace.php';
                   44549:             require_once 'PEAR/Task/Unixeol.php';
                   44550:             require_once 'PEAR/Task/Windowseol.php';
                   44551:             require_once 'PEAR/PackageFile/v1.php';
                   44552:             require_once 'PEAR/PackageFile/v2.php';
                   44553:             require_once 'PEAR/PackageFile/Generator/v1.php';
                   44554:             require_once 'PEAR/PackageFile/Generator/v2.php';
                   44555:         }
                   44556: 
                   44557:         $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
                   44558:         if ($filelist == null) {
                   44559:             return $this->raiseError("$channel/$package not installed");
                   44560:         }
                   44561: 
                   44562:         $ret = array();
                   44563:         foreach ($filelist as $file => $props) {
                   44564:             if (empty($props['installed_as'])) {
                   44565:                 continue;
                   44566:             }
                   44567: 
                   44568:             $path = $props['installed_as'];
                   44569:             if ($backup) {
                   44570:                 $this->addFileOperation('backup', array($path));
                   44571:                 $ret[] = $path;
                   44572:             }
                   44573: 
                   44574:             $this->addFileOperation('delete', array($path));
                   44575:         }
                   44576: 
                   44577:         if ($backup) {
                   44578:             return $ret;
                   44579:         }
                   44580: 
                   44581:         return true;
                   44582:     }
                   44583: 
                   44584:     // }}}
                   44585:     // {{{ _installFile()
                   44586: 
                   44587:     /**
                   44588:      * @param string filename
                   44589:      * @param array attributes from <file> tag in package.xml
                   44590:      * @param string path to install the file in
                   44591:      * @param array options from command-line
                   44592:      * @access private
                   44593:      */
                   44594:     function _installFile($file, $atts, $tmp_path, $options)
                   44595:     {
                   44596:         // {{{ return if this file is meant for another platform
                   44597:         static $os;
                   44598:         if (!isset($this->_registry)) {
                   44599:             $this->_registry = &$this->config->getRegistry();
                   44600:         }
                   44601: 
                   44602:         if (isset($atts['platform'])) {
                   44603:             if (empty($os)) {
                   44604:                 $os = new OS_Guess();
                   44605:             }
                   44606: 
                   44607:             if (strlen($atts['platform']) && $atts['platform']{0} == '!') {
                   44608:                 $negate   = true;
                   44609:                 $platform = substr($atts['platform'], 1);
                   44610:             } else {
                   44611:                 $negate    = false;
                   44612:                 $platform = $atts['platform'];
                   44613:             }
                   44614: 
                   44615:             if ((bool) $os->matchSignature($platform) === $negate) {
                   44616:                 $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
                   44617:                 return PEAR_INSTALLER_SKIPPED;
                   44618:             }
                   44619:         }
                   44620:         // }}}
                   44621: 
                   44622:         $channel = $this->pkginfo->getChannel();
                   44623:         // {{{ assemble the destination paths
                   44624:         switch ($atts['role']) {
                   44625:             case 'src':
                   44626:             case 'extsrc':
                   44627:                 $this->source_files++;
                   44628:                 return;
                   44629:             case 'doc':
                   44630:             case 'data':
                   44631:             case 'test':
                   44632:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
                   44633:                             DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
                   44634:                 unset($atts['baseinstalldir']);
                   44635:                 break;
                   44636:             case 'ext':
                   44637:             case 'php':
                   44638:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
                   44639:                 break;
                   44640:             case 'script':
                   44641:                 $dest_dir = $this->config->get('bin_dir', null, $channel);
                   44642:                 break;
                   44643:             default:
                   44644:                 return $this->raiseError("Invalid role `$atts[role]' for file $file");
                   44645:         }
                   44646: 
                   44647:         $save_destdir = $dest_dir;
                   44648:         if (!empty($atts['baseinstalldir'])) {
                   44649:             $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   44650:         }
                   44651: 
                   44652:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   44653:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   44654:         }
                   44655: 
                   44656:         if (empty($atts['install-as'])) {
                   44657:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   44658:         } else {
                   44659:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   44660:         }
                   44661:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   44662: 
                   44663:         // Clean up the DIRECTORY_SEPARATOR mess
                   44664:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   44665:         list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   44666:                                                     array(DIRECTORY_SEPARATOR,
                   44667:                                                           DIRECTORY_SEPARATOR,
                   44668:                                                           DIRECTORY_SEPARATOR),
                   44669:                                                     array($dest_file, $orig_file));
                   44670:         $final_dest_file = $installed_as = $dest_file;
                   44671:         if (isset($this->_options['packagingroot'])) {
                   44672:             $installedas_dest_dir  = dirname($final_dest_file);
                   44673:             $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44674:             $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
                   44675:         } else {
                   44676:             $installedas_dest_dir  = dirname($final_dest_file);
                   44677:             $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44678:         }
                   44679: 
                   44680:         $dest_dir  = dirname($final_dest_file);
                   44681:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44682:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   44683:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   44684:         }
                   44685:         // }}}
                   44686: 
                   44687:         if (empty($this->_options['register-only']) &&
                   44688:               (!file_exists($dest_dir) || !is_dir($dest_dir))) {
                   44689:             if (!$this->mkDirHier($dest_dir)) {
                   44690:                 return $this->raiseError("failed to mkdir $dest_dir",
                   44691:                                          PEAR_INSTALLER_FAILED);
                   44692:             }
                   44693:             $this->log(3, "+ mkdir $dest_dir");
                   44694:         }
                   44695: 
                   44696:         // pretty much nothing happens if we are only registering the install
                   44697:         if (empty($this->_options['register-only'])) {
                   44698:             if (empty($atts['replacements'])) {
                   44699:                 if (!file_exists($orig_file)) {
                   44700:                     return $this->raiseError("file $orig_file does not exist",
                   44701:                                              PEAR_INSTALLER_FAILED);
                   44702:                 }
                   44703: 
                   44704:                 if (!@copy($orig_file, $dest_file)) {
                   44705:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   44706:                                              PEAR_INSTALLER_FAILED);
                   44707:                 }
                   44708: 
                   44709:                 $this->log(3, "+ cp $orig_file $dest_file");
                   44710:                 if (isset($atts['md5sum'])) {
                   44711:                     $md5sum = md5_file($dest_file);
                   44712:                 }
                   44713:             } else {
                   44714:                 // {{{ file with replacements
                   44715:                 if (!file_exists($orig_file)) {
                   44716:                     return $this->raiseError("file does not exist",
                   44717:                                              PEAR_INSTALLER_FAILED);
                   44718:                 }
                   44719: 
                   44720:                 $contents = file_get_contents($orig_file);
                   44721:                 if ($contents === false) {
                   44722:                     $contents = '';
                   44723:                 }
                   44724: 
                   44725:                 if (isset($atts['md5sum'])) {
                   44726:                     $md5sum = md5($contents);
                   44727:                 }
                   44728: 
                   44729:                 $subst_from = $subst_to = array();
                   44730:                 foreach ($atts['replacements'] as $a) {
                   44731:                     $to = '';
                   44732:                     if ($a['type'] == 'php-const') {
                   44733:                         if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
                   44734:                             eval("\$to = $a[to];");
                   44735:                         } else {
                   44736:                             if (!isset($options['soft'])) {
                   44737:                                 $this->log(0, "invalid php-const replacement: $a[to]");
                   44738:                             }
                   44739:                             continue;
                   44740:                         }
                   44741:                     } elseif ($a['type'] == 'pear-config') {
                   44742:                         if ($a['to'] == 'master_server') {
                   44743:                             $chan = $this->_registry->getChannel($channel);
                   44744:                             if (!PEAR::isError($chan)) {
                   44745:                                 $to = $chan->getServer();
                   44746:                             } else {
                   44747:                                 $to = $this->config->get($a['to'], null, $channel);
                   44748:                             }
                   44749:                         } else {
                   44750:                             $to = $this->config->get($a['to'], null, $channel);
                   44751:                         }
                   44752:                         if (is_null($to)) {
                   44753:                             if (!isset($options['soft'])) {
                   44754:                                 $this->log(0, "invalid pear-config replacement: $a[to]");
                   44755:                             }
                   44756:                             continue;
                   44757:                         }
                   44758:                     } elseif ($a['type'] == 'package-info') {
                   44759:                         if ($t = $this->pkginfo->packageInfo($a['to'])) {
                   44760:                             $to = $t;
                   44761:                         } else {
                   44762:                             if (!isset($options['soft'])) {
                   44763:                                 $this->log(0, "invalid package-info replacement: $a[to]");
                   44764:                             }
                   44765:                             continue;
                   44766:                         }
                   44767:                     }
                   44768:                     if (!is_null($to)) {
                   44769:                         $subst_from[] = $a['from'];
                   44770:                         $subst_to[] = $to;
                   44771:                     }
                   44772:                 }
                   44773: 
                   44774:                 $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
                   44775:                 if (sizeof($subst_from)) {
                   44776:                     $contents = str_replace($subst_from, $subst_to, $contents);
                   44777:                 }
                   44778: 
                   44779:                 $wp = @fopen($dest_file, "wb");
                   44780:                 if (!is_resource($wp)) {
                   44781:                     return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   44782:                                              PEAR_INSTALLER_FAILED);
                   44783:                 }
                   44784: 
                   44785:                 if (@fwrite($wp, $contents) === false) {
                   44786:                     return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   44787:                                              PEAR_INSTALLER_FAILED);
                   44788:                 }
                   44789: 
                   44790:                 fclose($wp);
                   44791:                 // }}}
                   44792:             }
                   44793: 
                   44794:             // {{{ check the md5
                   44795:             if (isset($md5sum)) {
                   44796:                 if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
                   44797:                     $this->log(2, "md5sum ok: $final_dest_file");
                   44798:                 } else {
                   44799:                     if (empty($options['force'])) {
                   44800:                         // delete the file
                   44801:                         if (file_exists($dest_file)) {
                   44802:                             unlink($dest_file);
                   44803:                         }
                   44804: 
                   44805:                         if (!isset($options['ignore-errors'])) {
                   44806:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   44807:                                                  PEAR_INSTALLER_FAILED);
                   44808:                         }
                   44809: 
                   44810:                         if (!isset($options['soft'])) {
                   44811:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   44812:                         }
                   44813:                     } else {
                   44814:                         if (!isset($options['soft'])) {
                   44815:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   44816:                         }
                   44817:                     }
                   44818:                 }
                   44819:             }
                   44820:             // }}}
                   44821:             // {{{ set file permissions
                   44822:             if (!OS_WINDOWS) {
                   44823:                 if ($atts['role'] == 'script') {
                   44824:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                   44825:                     $this->log(3, "+ chmod +x $dest_file");
                   44826:                 } else {
                   44827:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   44828:                 }
                   44829: 
                   44830:                 if ($atts['role'] != 'src') {
                   44831:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   44832:                     if (!@chmod($dest_file, $mode)) {
                   44833:                         if (!isset($options['soft'])) {
                   44834:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   44835:                         }
                   44836:                     }
                   44837:                 }
                   44838:             }
                   44839:             // }}}
                   44840: 
                   44841:             if ($atts['role'] == 'src') {
                   44842:                 rename($dest_file, $final_dest_file);
                   44843:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   44844:             } else {
                   44845:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file,
                   44846:                     $atts['role'] == 'ext'));
                   44847:             }
                   44848:         }
                   44849: 
                   44850:         // Store the full path where the file was installed for easy unistall
                   44851:         if ($atts['role'] != 'script') {
                   44852:             $loc = $this->config->get($atts['role'] . '_dir');
                   44853:         } else {
                   44854:             $loc = $this->config->get('bin_dir');
                   44855:         }
                   44856: 
                   44857:         if ($atts['role'] != 'src') {
                   44858:             $this->addFileOperation("installed_as", array($file, $installed_as,
                   44859:                                     $loc,
                   44860:                                     dirname(substr($installedas_dest_file, strlen($loc)))));
                   44861:         }
                   44862: 
                   44863:         //$this->log(2, "installed: $dest_file");
                   44864:         return PEAR_INSTALLER_OK;
                   44865:     }
                   44866: 
                   44867:     // }}}
                   44868:     // {{{ _installFile2()
                   44869: 
                   44870:     /**
                   44871:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   44872:      * @param string filename
                   44873:      * @param array attributes from <file> tag in package.xml
                   44874:      * @param string path to install the file in
                   44875:      * @param array options from command-line
                   44876:      * @access private
                   44877:      */
                   44878:     function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
                   44879:     {
                   44880:         $atts = $real_atts;
                   44881:         if (!isset($this->_registry)) {
                   44882:             $this->_registry = &$this->config->getRegistry();
                   44883:         }
                   44884: 
                   44885:         $channel = $pkg->getChannel();
                   44886:         // {{{ assemble the destination paths
                   44887:         if (!in_array($atts['attribs']['role'],
                   44888:               PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
                   44889:             return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
                   44890:                     "' for file $file");
                   44891:         }
                   44892: 
                   44893:         $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
                   44894:         $err  = $role->setup($this, $pkg, $atts['attribs'], $file);
                   44895:         if (PEAR::isError($err)) {
                   44896:             return $err;
                   44897:         }
                   44898: 
                   44899:         if (!$role->isInstallable()) {
                   44900:             return;
                   44901:         }
                   44902: 
                   44903:         $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
                   44904:         if (PEAR::isError($info)) {
                   44905:             return $info;
                   44906:         }
                   44907: 
                   44908:         list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
                   44909:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   44910:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   44911:         }
                   44912: 
                   44913:         $final_dest_file = $installed_as = $dest_file;
                   44914:         if (isset($this->_options['packagingroot'])) {
                   44915:             $final_dest_file = $this->_prependPath($final_dest_file,
                   44916:                 $this->_options['packagingroot']);
                   44917:         }
                   44918: 
                   44919:         $dest_dir  = dirname($final_dest_file);
                   44920:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44921:         // }}}
                   44922: 
                   44923:         if (empty($this->_options['register-only'])) {
                   44924:             if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
                   44925:                 if (!$this->mkDirHier($dest_dir)) {
                   44926:                     return $this->raiseError("failed to mkdir $dest_dir",
                   44927:                                              PEAR_INSTALLER_FAILED);
                   44928:                 }
                   44929:                 $this->log(3, "+ mkdir $dest_dir");
                   44930:             }
                   44931:         }
                   44932: 
                   44933:         $attribs = $atts['attribs'];
                   44934:         unset($atts['attribs']);
                   44935:         // pretty much nothing happens if we are only registering the install
                   44936:         if (empty($this->_options['register-only'])) {
                   44937:             if (!count($atts)) { // no tasks
                   44938:                 if (!file_exists($orig_file)) {
                   44939:                     return $this->raiseError("file $orig_file does not exist",
                   44940:                                              PEAR_INSTALLER_FAILED);
                   44941:                 }
                   44942: 
                   44943:                 if (!@copy($orig_file, $dest_file)) {
                   44944:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   44945:                                              PEAR_INSTALLER_FAILED);
                   44946:                 }
                   44947: 
                   44948:                 $this->log(3, "+ cp $orig_file $dest_file");
                   44949:                 if (isset($attribs['md5sum'])) {
                   44950:                     $md5sum = md5_file($dest_file);
                   44951:                 }
                   44952:             } else { // file with tasks
                   44953:                 if (!file_exists($orig_file)) {
                   44954:                     return $this->raiseError("file $orig_file does not exist",
                   44955:                                              PEAR_INSTALLER_FAILED);
                   44956:                 }
                   44957: 
                   44958:                 $contents = file_get_contents($orig_file);
                   44959:                 if ($contents === false) {
                   44960:                     $contents = '';
                   44961:                 }
                   44962: 
                   44963:                 if (isset($attribs['md5sum'])) {
                   44964:                     $md5sum = md5($contents);
                   44965:                 }
                   44966: 
                   44967:                 foreach ($atts as $tag => $raw) {
                   44968:                     $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
                   44969:                     $task = "PEAR_Task_$tag";
                   44970:                     $task = &new $task($this->config, $this, PEAR_TASK_INSTALL);
                   44971:                     if (!$task->isScript()) { // scripts are only handled after installation
                   44972:                         $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
                   44973:                         $res = $task->startSession($pkg, $contents, $final_dest_file);
                   44974:                         if ($res === false) {
                   44975:                             continue; // skip this file
                   44976:                         }
                   44977: 
                   44978:                         if (PEAR::isError($res)) {
                   44979:                             return $res;
                   44980:                         }
                   44981: 
                   44982:                         $contents = $res; // save changes
                   44983:                     }
                   44984: 
                   44985:                     $wp = @fopen($dest_file, "wb");
                   44986:                     if (!is_resource($wp)) {
                   44987:                         return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   44988:                                                  PEAR_INSTALLER_FAILED);
                   44989:                     }
                   44990: 
                   44991:                     if (fwrite($wp, $contents) === false) {
                   44992:                         return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   44993:                                                  PEAR_INSTALLER_FAILED);
                   44994:                     }
                   44995: 
                   44996:                     fclose($wp);
                   44997:                 }
                   44998:             }
                   44999: 
                   45000:             // {{{ check the md5
                   45001:             if (isset($md5sum)) {
                   45002:                 // Make sure the original md5 sum matches with expected
                   45003:                 if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
                   45004:                     $this->log(2, "md5sum ok: $final_dest_file");
                   45005: 
                   45006:                     if (isset($contents)) {
                   45007:                         // set md5 sum based on $content in case any tasks were run.
                   45008:                         $real_atts['attribs']['md5sum'] = md5($contents);
                   45009:                     }
                   45010:                 } else {
                   45011:                     if (empty($options['force'])) {
                   45012:                         // delete the file
                   45013:                         if (file_exists($dest_file)) {
                   45014:                             unlink($dest_file);
                   45015:                         }
                   45016: 
                   45017:                         if (!isset($options['ignore-errors'])) {
                   45018:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   45019:                                                      PEAR_INSTALLER_FAILED);
                   45020:                         }
                   45021: 
                   45022:                         if (!isset($options['soft'])) {
                   45023:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45024:                         }
                   45025:                     } else {
                   45026:                         if (!isset($options['soft'])) {
                   45027:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45028:                         }
                   45029:                     }
                   45030:                 }
                   45031:             } else {
                   45032:                 $real_atts['attribs']['md5sum'] = md5_file($dest_file);
                   45033:             }
                   45034: 
                   45035:             // }}}
                   45036:             // {{{ set file permissions
                   45037:             if (!OS_WINDOWS) {
                   45038:                 if ($role->isExecutable()) {
                   45039:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                   45040:                     $this->log(3, "+ chmod +x $dest_file");
                   45041:                 } else {
                   45042:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   45043:                 }
                   45044: 
                   45045:                 if ($attribs['role'] != 'src') {
                   45046:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   45047:                     if (!@chmod($dest_file, $mode)) {
                   45048:                         if (!isset($options['soft'])) {
                   45049:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   45050:                         }
                   45051:                     }
                   45052:                 }
                   45053:             }
                   45054:             // }}}
                   45055: 
                   45056:             if ($attribs['role'] == 'src') {
                   45057:                 rename($dest_file, $final_dest_file);
                   45058:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   45059:             } else {
                   45060:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
                   45061:             }
                   45062:         }
                   45063: 
                   45064:         // Store the full path where the file was installed for easy uninstall
                   45065:         if ($attribs['role'] != 'src') {
                   45066:             $loc = $this->config->get($role->getLocationConfig(), null, $channel);
                   45067:             $this->addFileOperation('installed_as', array($file, $installed_as,
                   45068:                                 $loc,
                   45069:                                 dirname(substr($installed_as, strlen($loc)))));
                   45070:         }
                   45071: 
                   45072:         //$this->log(2, "installed: $dest_file");
                   45073:         return PEAR_INSTALLER_OK;
                   45074:     }
                   45075: 
                   45076:     // }}}
                   45077:     // {{{ addFileOperation()
                   45078: 
                   45079:     /**
                   45080:      * Add a file operation to the current file transaction.
                   45081:      *
                   45082:      * @see startFileTransaction()
                   45083:      * @param string $type This can be one of:
                   45084:      *    - rename:  rename a file ($data has 3 values)
                   45085:      *    - backup:  backup an existing file ($data has 1 value)
                   45086:      *    - removebackup:  clean up backups created during install ($data has 1 value)
                   45087:      *    - chmod:   change permissions on a file ($data has 2 values)
                   45088:      *    - delete:  delete a file ($data has 1 value)
                   45089:      *    - rmdir:   delete a directory if empty ($data has 1 value)
                   45090:      *    - installed_as: mark a file as installed ($data has 4 values).
                   45091:      * @param array $data For all file operations, this array must contain the
                   45092:      *    full path to the file or directory that is being operated on.  For
                   45093:      *    the rename command, the first parameter must be the file to rename,
                   45094:      *    the second its new name, the third whether this is a PHP extension.
                   45095:      *
                   45096:      *    The installed_as operation contains 4 elements in this order:
                   45097:      *    1. Filename as listed in the filelist element from package.xml
                   45098:      *    2. Full path to the installed file
                   45099:      *    3. Full path from the php_dir configuration variable used in this
                   45100:      *       installation
                   45101:      *    4. Relative path from the php_dir that this file is installed in
                   45102:      */
                   45103:     function addFileOperation($type, $data)
                   45104:     {
                   45105:         if (!is_array($data)) {
                   45106:             return $this->raiseError('Internal Error: $data in addFileOperation'
                   45107:                 . ' must be an array, was ' . gettype($data));
                   45108:         }
                   45109: 
                   45110:         if ($type == 'chmod') {
                   45111:             $octmode = decoct($data[0]);
                   45112:             $this->log(3, "adding to transaction: $type $octmode $data[1]");
                   45113:         } else {
                   45114:             $this->log(3, "adding to transaction: $type " . implode(" ", $data));
                   45115:         }
                   45116:         $this->file_operations[] = array($type, $data);
                   45117:     }
                   45118: 
                   45119:     // }}}
                   45120:     // {{{ startFileTransaction()
                   45121: 
                   45122:     function startFileTransaction($rollback_in_case = false)
                   45123:     {
                   45124:         if (count($this->file_operations) && $rollback_in_case) {
                   45125:             $this->rollbackFileTransaction();
                   45126:         }
                   45127:         $this->file_operations = array();
                   45128:     }
                   45129: 
                   45130:     // }}}
                   45131:     // {{{ commitFileTransaction()
                   45132: 
                   45133:     function commitFileTransaction()
                   45134:     {
                   45135:         // {{{ first, check permissions and such manually
                   45136:         $errors = array();
                   45137:         foreach ($this->file_operations as $key => $tr) {
                   45138:             list($type, $data) = $tr;
                   45139:             switch ($type) {
                   45140:                 case 'rename':
                   45141:                     if (!file_exists($data[0])) {
                   45142:                         $errors[] = "cannot rename file $data[0], doesn't exist";
                   45143:                     }
                   45144: 
                   45145:                     // check that dest dir. is writable
                   45146:                     if (!is_writable(dirname($data[1]))) {
                   45147:                         $errors[] = "permission denied ($type): $data[1]";
                   45148:                     }
                   45149:                     break;
                   45150:                 case 'chmod':
                   45151:                     // check that file is writable
                   45152:                     if (!is_writable($data[1])) {
                   45153:                         $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
                   45154:                     }
                   45155:                     break;
                   45156:                 case 'delete':
                   45157:                     if (!file_exists($data[0])) {
                   45158:                         $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
                   45159:                     }
                   45160:                     // check that directory is writable
                   45161:                     if (file_exists($data[0])) {
                   45162:                         if (!is_writable(dirname($data[0]))) {
                   45163:                             $errors[] = "permission denied ($type): $data[0]";
                   45164:                         } else {
                   45165:                             // make sure the file to be deleted can be opened for writing
                   45166:                             $fp = false;
                   45167:                             if (!is_dir($data[0]) &&
                   45168:                                   (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
                   45169:                                 $errors[] = "permission denied ($type): $data[0]";
                   45170:                             } elseif ($fp) {
                   45171:                                 fclose($fp);
                   45172:                             }
                   45173:                         }
                   45174: 
                   45175:                         /* Verify we are not deleting a file owned by another package
                   45176:                          * This can happen when a file moves from package A to B in
                   45177:                          * an upgrade ala http://pear.php.net/17986
                   45178:                          */
                   45179:                         $info = array(
                   45180:                             'package' => strtolower($this->pkginfo->getName()),
                   45181:                             'channel' => strtolower($this->pkginfo->getChannel()),
                   45182:                         );
                   45183:                         $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
                   45184:                         if (is_array($result)) {
                   45185:                             $res = array_diff($result, $info);
                   45186:                             if (!empty($res)) {
                   45187:                                 $new = $this->_registry->getPackage($result[1], $result[0]);
                   45188:                                 $this->file_operations[$key] = false;
                   45189:                                 $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.");
                   45190:                             }
                   45191:                         }
                   45192:                     }
                   45193:                     break;
                   45194:             }
                   45195: 
                   45196:         }
                   45197:         // }}}
                   45198: 
                   45199:         $n = count($this->file_operations);
                   45200:         $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
                   45201: 
                   45202:         $m = count($errors);
                   45203:         if ($m > 0) {
                   45204:             foreach ($errors as $error) {
                   45205:                 if (!isset($this->_options['soft'])) {
                   45206:                     $this->log(1, $error);
                   45207:                 }
                   45208:             }
                   45209: 
                   45210:             if (!isset($this->_options['ignore-errors'])) {
                   45211:                 return false;
                   45212:             }
                   45213:         }
                   45214: 
                   45215:         $this->_dirtree = array();
                   45216:         // {{{ really commit the transaction
                   45217:         foreach ($this->file_operations as $i => $tr) {
                   45218:             if (!$tr) {
                   45219:                 // support removal of non-existing backups
                   45220:                 continue;
                   45221:             }
                   45222: 
                   45223:             list($type, $data) = $tr;
                   45224:             switch ($type) {
                   45225:                 case 'backup':
                   45226:                     if (!file_exists($data[0])) {
                   45227:                         $this->file_operations[$i] = false;
                   45228:                         break;
                   45229:                     }
                   45230: 
                   45231:                     if (!@copy($data[0], $data[0] . '.bak')) {
                   45232:                         $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
                   45233:                             '.bak ' . $php_errormsg);
                   45234:                         return false;
                   45235:                     }
                   45236:                     $this->log(3, "+ backup $data[0] to $data[0].bak");
                   45237:                     break;
                   45238:                 case 'removebackup':
                   45239:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   45240:                         unlink($data[0] . '.bak');
                   45241:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   45242:                     }
                   45243:                     break;
                   45244:                 case 'rename':
                   45245:                     $test = file_exists($data[1]) ? @unlink($data[1]) : null;
                   45246:                     if (!$test && file_exists($data[1])) {
                   45247:                         if ($data[2]) {
                   45248:                             $extra = ', this extension must be installed manually.  Rename to "' .
                   45249:                                 basename($data[1]) . '"';
                   45250:                         } else {
                   45251:                             $extra = '';
                   45252:                         }
                   45253: 
                   45254:                         if (!isset($this->_options['soft'])) {
                   45255:                             $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
                   45256:                                 $data[0] . $extra);
                   45257:                         }
                   45258: 
                   45259:                         if (!isset($this->_options['ignore-errors'])) {
                   45260:                             return false;
                   45261:                         }
                   45262:                     }
                   45263: 
                   45264:                     // permissions issues with rename - copy() is far superior
                   45265:                     $perms = @fileperms($data[0]);
                   45266:                     if (!@copy($data[0], $data[1])) {
                   45267:                         $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
                   45268:                             ' ' . $php_errormsg);
                   45269:                         return false;
                   45270:                     }
                   45271: 
                   45272:                     // copy over permissions, otherwise they are lost
                   45273:                     @chmod($data[1], $perms);
                   45274:                     @unlink($data[0]);
                   45275:                     $this->log(3, "+ mv $data[0] $data[1]");
                   45276:                     break;
                   45277:                 case 'chmod':
                   45278:                     if (!@chmod($data[1], $data[0])) {
                   45279:                         $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
                   45280:                             decoct($data[0]) . ' ' . $php_errormsg);
                   45281:                         return false;
                   45282:                     }
                   45283: 
                   45284:                     $octmode = decoct($data[0]);
                   45285:                     $this->log(3, "+ chmod $octmode $data[1]");
                   45286:                     break;
                   45287:                 case 'delete':
                   45288:                     if (file_exists($data[0])) {
                   45289:                         if (!@unlink($data[0])) {
                   45290:                             $this->log(1, 'Could not delete ' . $data[0] . ' ' .
                   45291:                                 $php_errormsg);
                   45292:                             return false;
                   45293:                         }
                   45294:                         $this->log(3, "+ rm $data[0]");
                   45295:                     }
                   45296:                     break;
                   45297:                 case 'rmdir':
                   45298:                     if (file_exists($data[0])) {
                   45299:                         do {
                   45300:                             $testme = opendir($data[0]);
                   45301:                             while (false !== ($entry = readdir($testme))) {
                   45302:                                 if ($entry == '.' || $entry == '..') {
                   45303:                                     continue;
                   45304:                                 }
                   45305:                                 closedir($testme);
                   45306:                                 break 2; // this directory is not empty and can't be
                   45307:                                          // deleted
                   45308:                             }
                   45309: 
                   45310:                             closedir($testme);
                   45311:                             if (!@rmdir($data[0])) {
                   45312:                                 $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
                   45313:                                     $php_errormsg);
                   45314:                                 return false;
                   45315:                             }
                   45316:                             $this->log(3, "+ rmdir $data[0]");
                   45317:                         } while (false);
                   45318:                     }
                   45319:                     break;
                   45320:                 case 'installed_as':
                   45321:                     $this->pkginfo->setInstalledAs($data[0], $data[1]);
                   45322:                     if (!isset($this->_dirtree[dirname($data[1])])) {
                   45323:                         $this->_dirtree[dirname($data[1])] = true;
                   45324:                         $this->pkginfo->setDirtree(dirname($data[1]));
                   45325: 
                   45326:                         while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
                   45327:                                 $data[3] != '/' && $data[3] != '\\') {
                   45328:                             $this->pkginfo->setDirtree($pp =
                   45329:                                 $this->_prependPath($data[3], $data[2]));
                   45330:                             $this->_dirtree[$pp] = true;
                   45331:                             $data[3] = dirname($data[3]);
                   45332:                         }
                   45333:                     }
                   45334:                     break;
                   45335:             }
                   45336:         }
                   45337:         // }}}
                   45338:         $this->log(2, "successfully committed $n file operations");
                   45339:         $this->file_operations = array();
                   45340:         return true;
                   45341:     }
                   45342: 
                   45343:     // }}}
                   45344:     // {{{ rollbackFileTransaction()
                   45345: 
                   45346:     function rollbackFileTransaction()
                   45347:     {
                   45348:         $n = count($this->file_operations);
                   45349:         $this->log(2, "rolling back $n file operations");
                   45350:         foreach ($this->file_operations as $tr) {
                   45351:             list($type, $data) = $tr;
                   45352:             switch ($type) {
                   45353:                 case 'backup':
                   45354:                     if (file_exists($data[0] . '.bak')) {
                   45355:                         if (file_exists($data[0] && is_writable($data[0]))) {
                   45356:                             unlink($data[0]);
                   45357:                         }
                   45358:                         @copy($data[0] . '.bak', $data[0]);
                   45359:                         $this->log(3, "+ restore $data[0] from $data[0].bak");
                   45360:                     }
                   45361:                     break;
                   45362:                 case 'removebackup':
                   45363:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   45364:                         unlink($data[0] . '.bak');
                   45365:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   45366:                     }
                   45367:                     break;
                   45368:                 case 'rename':
                   45369:                     @unlink($data[0]);
                   45370:                     $this->log(3, "+ rm $data[0]");
                   45371:                     break;
                   45372:                 case 'mkdir':
                   45373:                     @rmdir($data[0]);
                   45374:                     $this->log(3, "+ rmdir $data[0]");
                   45375:                     break;
                   45376:                 case 'chmod':
                   45377:                     break;
                   45378:                 case 'delete':
                   45379:                     break;
                   45380:                 case 'installed_as':
                   45381:                     $this->pkginfo->setInstalledAs($data[0], false);
                   45382:                     break;
                   45383:             }
                   45384:         }
                   45385:         $this->pkginfo->resetDirtree();
                   45386:         $this->file_operations = array();
                   45387:     }
                   45388: 
                   45389:     // }}}
                   45390:     // {{{ mkDirHier($dir)
                   45391: 
                   45392:     function mkDirHier($dir)
                   45393:     {
                   45394:         $this->addFileOperation('mkdir', array($dir));
                   45395:         return parent::mkDirHier($dir);
                   45396:     }
                   45397: 
                   45398:     // }}}
                   45399:     // {{{ download()
                   45400: 
                   45401:     /**
                   45402:      * Download any files and their dependencies, if necessary
                   45403:      *
                   45404:      * @param array a mixed list of package names, local files, or package.xml
                   45405:      * @param PEAR_Config
                   45406:      * @param array options from the command line
                   45407:      * @param array this is the array that will be populated with packages to
                   45408:      *              install.  Format of each entry:
                   45409:      *
                   45410:      * <code>
                   45411:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   45412:      *    'info' => array() // parsed package.xml
                   45413:      * );
                   45414:      * </code>
                   45415:      * @param array this will be populated with any error messages
                   45416:      * @param false private recursion variable
                   45417:      * @param false private recursion variable
                   45418:      * @param false private recursion variable
                   45419:      * @deprecated in favor of PEAR_Downloader
                   45420:      */
                   45421:     function download($packages, $options, &$config, &$installpackages,
                   45422:                       &$errors, $installed = false, $willinstall = false, $state = false)
                   45423:     {
                   45424:         // trickiness: initialize here
                   45425:         parent::PEAR_Downloader($this->ui, $options, $config);
                   45426:         $ret             = parent::download($packages);
                   45427:         $errors          = $this->getErrorMsgs();
                   45428:         $installpackages = $this->getDownloadedPackages();
                   45429:         trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " .
                   45430:                       "in favor of PEAR_Downloader class", E_USER_WARNING);
                   45431:         return $ret;
                   45432:     }
                   45433: 
                   45434:     // }}}
                   45435:     // {{{ _parsePackageXml()
                   45436: 
                   45437:     function _parsePackageXml(&$descfile)
                   45438:     {
                   45439:         // Parse xml file -----------------------------------------------
                   45440:         $pkg = new PEAR_PackageFile($this->config, $this->debug);
                   45441:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   45442:         $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
                   45443:         PEAR::staticPopErrorHandling();
                   45444:         if (PEAR::isError($p)) {
                   45445:             if (is_array($p->getUserInfo())) {
                   45446:                 foreach ($p->getUserInfo() as $err) {
                   45447:                     $loglevel = $err['level'] == 'error' ? 0 : 1;
                   45448:                     if (!isset($this->_options['soft'])) {
                   45449:                         $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
                   45450:                     }
                   45451:                 }
                   45452:             }
                   45453:             return $this->raiseError('Installation failed: invalid package file');
                   45454:         }
                   45455: 
                   45456:         $descfile = $p->getPackageFile();
                   45457:         return $p;
                   45458:     }
                   45459: 
                   45460:     // }}}
                   45461:     /**
                   45462:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   45463:      * dependency validation
                   45464:      * @param array
                   45465:      */
                   45466:     function setDownloadedPackages(&$pkgs)
                   45467:     {
                   45468:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   45469:         $err = $this->analyzeDependencies($pkgs);
                   45470:         PEAR::popErrorHandling();
                   45471:         if (PEAR::isError($err)) {
                   45472:             return $err;
                   45473:         }
                   45474:         $this->_downloadedPackages = &$pkgs;
                   45475:     }
                   45476: 
                   45477:     /**
                   45478:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   45479:      * dependency validation
                   45480:      * @param array
                   45481:      */
                   45482:     function setUninstallPackages(&$pkgs)
                   45483:     {
                   45484:         $this->_downloadedPackages = &$pkgs;
                   45485:     }
                   45486: 
                   45487:     function getInstallPackages()
                   45488:     {
                   45489:         return $this->_downloadedPackages;
                   45490:     }
                   45491: 
                   45492:     // {{{ install()
                   45493: 
                   45494:     /**
                   45495:      * Installs the files within the package file specified.
                   45496:      *
                   45497:      * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
                   45498:      *        or a pre-initialized packagefile object
                   45499:      * @param array $options
                   45500:      * recognized options:
                   45501:      * - installroot   : optional prefix directory for installation
                   45502:      * - force         : force installation
                   45503:      * - register-only : update registry but don't install files
                   45504:      * - upgrade       : upgrade existing install
                   45505:      * - soft          : fail silently
                   45506:      * - nodeps        : ignore dependency conflicts/missing dependencies
                   45507:      * - alldeps       : install all dependencies
                   45508:      * - onlyreqdeps   : install only required dependencies
                   45509:      *
                   45510:      * @return array|PEAR_Error package info if successful
                   45511:      */
                   45512:     function install($pkgfile, $options = array())
                   45513:     {
                   45514:         $this->_options = $options;
                   45515:         $this->_registry = &$this->config->getRegistry();
                   45516:         if (is_object($pkgfile)) {
                   45517:             $dlpkg    = &$pkgfile;
                   45518:             $pkg      = $pkgfile->getPackageFile();
                   45519:             $pkgfile  = $pkg->getArchiveFile();
                   45520:             $descfile = $pkg->getPackageFile();
                   45521:         } else {
                   45522:             $descfile = $pkgfile;
                   45523:             $pkg      = $this->_parsePackageXml($descfile);
                   45524:             if (PEAR::isError($pkg)) {
                   45525:                 return $pkg;
                   45526:             }
                   45527:         }
                   45528: 
                   45529:         $tmpdir = dirname($descfile);
                   45530:         if (realpath($descfile) != realpath($pkgfile)) {
                   45531:             // Use the temp_dir since $descfile can contain the download dir path
                   45532:             $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
                   45533:             $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');
                   45534: 
                   45535:             $tar = new Archive_Tar($pkgfile);
                   45536:             if (!$tar->extract($tmpdir)) {
                   45537:                 return $this->raiseError("unable to unpack $pkgfile");
                   45538:             }
                   45539:         }
                   45540: 
                   45541:         $pkgname = $pkg->getName();
                   45542:         $channel = $pkg->getChannel();
                   45543:         if (isset($this->_options['packagingroot'])) {
                   45544:             $regdir = $this->_prependPath(
                   45545:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   45546:                 $this->_options['packagingroot']);
                   45547: 
                   45548:             $packrootphp_dir = $this->_prependPath(
                   45549:                 $this->config->get('php_dir', null, $channel),
                   45550:                 $this->_options['packagingroot']);
                   45551:         }
                   45552: 
                   45553:         if (isset($options['installroot'])) {
                   45554:             $this->config->setInstallRoot($options['installroot']);
                   45555:             $this->_registry = &$this->config->getRegistry();
                   45556:             $installregistry = &$this->_registry;
                   45557:             $this->installroot = ''; // all done automagically now
                   45558:             $php_dir = $this->config->get('php_dir', null, $channel);
                   45559:         } else {
                   45560:             $this->config->setInstallRoot(false);
                   45561:             $this->_registry = &$this->config->getRegistry();
                   45562:             if (isset($this->_options['packagingroot'])) {
                   45563:                 $installregistry = &new PEAR_Registry($regdir);
                   45564:                 if (!$installregistry->channelExists($channel, true)) {
                   45565:                     // we need to fake a channel-discover of this channel
                   45566:                     $chanobj = $this->_registry->getChannel($channel, true);
                   45567:                     $installregistry->addChannel($chanobj);
                   45568:                 }
                   45569:                 $php_dir = $packrootphp_dir;
                   45570:             } else {
                   45571:                 $installregistry = &$this->_registry;
                   45572:                 $php_dir = $this->config->get('php_dir', null, $channel);
                   45573:             }
                   45574:             $this->installroot = '';
                   45575:         }
                   45576: 
                   45577:         // {{{ checks to do when not in "force" mode
                   45578:         if (empty($options['force']) &&
                   45579:               (file_exists($this->config->get('php_dir')) &&
                   45580:                is_dir($this->config->get('php_dir')))) {
                   45581:             $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
                   45582:             $instfilelist = $pkg->getInstallationFileList(true);
                   45583:             if (PEAR::isError($instfilelist)) {
                   45584:                 return $instfilelist;
                   45585:             }
                   45586: 
                   45587:             // ensure we have the most accurate registry
                   45588:             $installregistry->flushFileMap();
                   45589:             $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
                   45590:             if (PEAR::isError($test)) {
                   45591:                 return $test;
                   45592:             }
                   45593: 
                   45594:             if (sizeof($test)) {
                   45595:                 $pkgs = $this->getInstallPackages();
                   45596:                 $found = false;
                   45597:                 foreach ($pkgs as $param) {
                   45598:                     if ($pkg->isSubpackageOf($param)) {
                   45599:                         $found = true;
                   45600:                         break;
                   45601:                     }
                   45602:                 }
                   45603: 
                   45604:                 if ($found) {
                   45605:                     // subpackages can conflict with earlier versions of parent packages
                   45606:                     $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
                   45607:                     $tmp = $test;
                   45608:                     foreach ($tmp as $file => $info) {
                   45609:                         if (is_array($info)) {
                   45610:                             if (strtolower($info[1]) == strtolower($param->getPackage()) &&
                   45611:                                   strtolower($info[0]) == strtolower($param->getChannel())
                   45612:                             ) {
                   45613:                                 if (isset($parentreg['filelist'][$file])) {
                   45614:                                     unset($parentreg['filelist'][$file]);
                   45615:                                 } else{
                   45616:                                     $pos     = strpos($file, '/');
                   45617:                                     $basedir = substr($file, 0, $pos);
                   45618:                                     $file2   = substr($file, $pos + 1);
                   45619:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   45620:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   45621:                                     ) {
                   45622:                                         unset($parentreg['filelist'][$file2]);
                   45623:                                     }
                   45624:                                 }
                   45625: 
                   45626:                                 unset($test[$file]);
                   45627:                             }
                   45628:                         } else {
                   45629:                             if (strtolower($param->getChannel()) != 'pear.php.net') {
                   45630:                                 continue;
                   45631:                             }
                   45632: 
                   45633:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   45634:                                 if (isset($parentreg['filelist'][$file])) {
                   45635:                                     unset($parentreg['filelist'][$file]);
                   45636:                                 } else{
                   45637:                                     $pos     = strpos($file, '/');
                   45638:                                     $basedir = substr($file, 0, $pos);
                   45639:                                     $file2   = substr($file, $pos + 1);
                   45640:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   45641:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   45642:                                     ) {
                   45643:                                         unset($parentreg['filelist'][$file2]);
                   45644:                                     }
                   45645:                                 }
                   45646: 
                   45647:                                 unset($test[$file]);
                   45648:                             }
                   45649:                         }
                   45650:                     }
                   45651: 
                   45652:                     $pfk = &new PEAR_PackageFile($this->config);
                   45653:                     $parentpkg = &$pfk->fromArray($parentreg);
                   45654:                     $installregistry->updatePackage2($parentpkg);
                   45655:                 }
                   45656: 
                   45657:                 if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
                   45658:                     $tmp = $test;
                   45659:                     foreach ($tmp as $file => $info) {
                   45660:                         if (is_string($info)) {
                   45661:                             // pear.php.net packages are always stored as strings
                   45662:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   45663:                                 // upgrading existing package
                   45664:                                 unset($test[$file]);
                   45665:                             }
                   45666:                         }
                   45667:                     }
                   45668:                 }
                   45669: 
                   45670:                 if (count($test)) {
                   45671:                     $msg = "$channel/$pkgname: conflicting files found:\n";
                   45672:                     $longest = max(array_map("strlen", array_keys($test)));
                   45673:                     $fmt = "%${longest}s (%s)\n";
                   45674:                     foreach ($test as $file => $info) {
                   45675:                         if (!is_array($info)) {
                   45676:                             $info = array('pear.php.net', $info);
                   45677:                         }
                   45678:                         $info = $info[0] . '/' . $info[1];
                   45679:                         $msg .= sprintf($fmt, $file, $info);
                   45680:                     }
                   45681: 
                   45682:                     if (!isset($options['ignore-errors'])) {
                   45683:                         return $this->raiseError($msg);
                   45684:                     }
                   45685: 
                   45686:                     if (!isset($options['soft'])) {
                   45687:                         $this->log(0, "WARNING: $msg");
                   45688:                     }
                   45689:                 }
                   45690:             }
                   45691:         }
                   45692:         // }}}
                   45693: 
                   45694:         $this->startFileTransaction();
                   45695: 
                   45696:         $usechannel = $channel;
                   45697:         if ($channel == 'pecl.php.net') {
                   45698:             $test = $installregistry->packageExists($pkgname, $channel);
                   45699:             if (!$test) {
                   45700:                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   45701:                 $usechannel = 'pear.php.net';
                   45702:             }
                   45703:         } else {
                   45704:             $test = $installregistry->packageExists($pkgname, $channel);
                   45705:         }
                   45706: 
                   45707:         if (empty($options['upgrade']) && empty($options['soft'])) {
                   45708:             // checks to do only when installing new packages
                   45709:             if (empty($options['force']) && $test) {
                   45710:                 return $this->raiseError("$channel/$pkgname is already installed");
                   45711:             }
                   45712:         } else {
                   45713:             // Upgrade
                   45714:             if ($test) {
                   45715:                 $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                   45716:                 $v2 = $pkg->getVersion();
                   45717:                 $cmp = version_compare("$v1", "$v2", 'gt');
                   45718:                 if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
                   45719:                     return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
                   45720:                 }
                   45721:             }
                   45722:         }
                   45723: 
                   45724:         // Do cleanups for upgrade and install, remove old release's files first
                   45725:         if ($test && empty($options['register-only'])) {
                   45726:             // when upgrading, remove old release's files first:
                   45727:             if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
                   45728:                   true))) {
                   45729:                 if (!isset($options['ignore-errors'])) {
                   45730:                     return $this->raiseError($err);
                   45731:                 }
                   45732: 
                   45733:                 if (!isset($options['soft'])) {
                   45734:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   45735:                 }
                   45736:             } else {
                   45737:                 $backedup = $err;
                   45738:             }
                   45739:         }
                   45740: 
                   45741:         // {{{ Copy files to dest dir ---------------------------------------
                   45742: 
                   45743:         // info from the package it self we want to access from _installFile
                   45744:         $this->pkginfo = &$pkg;
                   45745:         // used to determine whether we should build any C code
                   45746:         $this->source_files = 0;
                   45747: 
                   45748:         $savechannel = $this->config->get('default_channel');
                   45749:         if (empty($options['register-only']) && !is_dir($php_dir)) {
                   45750:             if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
                   45751:                 return $this->raiseError("no installation destination directory '$php_dir'\n");
                   45752:             }
                   45753:         }
                   45754: 
                   45755:         if (substr($pkgfile, -4) != '.xml') {
                   45756:             $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
                   45757:         }
                   45758: 
                   45759:         $this->configSet('default_channel', $channel);
                   45760:         // {{{ install files
                   45761: 
                   45762:         $ver = $pkg->getPackagexmlVersion();
                   45763:         if (version_compare($ver, '2.0', '>=')) {
                   45764:             $filelist = $pkg->getInstallationFilelist();
                   45765:         } else {
                   45766:             $filelist = $pkg->getFileList();
                   45767:         }
                   45768: 
                   45769:         if (PEAR::isError($filelist)) {
                   45770:             return $filelist;
                   45771:         }
                   45772: 
                   45773:         $p = &$installregistry->getPackage($pkgname, $channel);
                   45774:         $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
                   45775: 
                   45776:         $pkg->resetFilelist();
                   45777:         $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
                   45778:             'version', $pkg->getChannel()));
                   45779:         foreach ($filelist as $file => $atts) {
                   45780:             $this->expectError(PEAR_INSTALLER_FAILED);
                   45781:             if ($pkg->getPackagexmlVersion() == '1.0') {
                   45782:                 $res = $this->_installFile($file, $atts, $tmpdir, $options);
                   45783:             } else {
                   45784:                 $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
                   45785:             }
                   45786:             $this->popExpect();
                   45787: 
                   45788:             if (PEAR::isError($res)) {
                   45789:                 if (empty($options['ignore-errors'])) {
                   45790:                     $this->rollbackFileTransaction();
                   45791:                     if ($res->getMessage() == "file does not exist") {
                   45792:                         $this->raiseError("file $file in package.xml does not exist");
                   45793:                     }
                   45794: 
                   45795:                     return $this->raiseError($res);
                   45796:                 }
                   45797: 
                   45798:                 if (!isset($options['soft'])) {
                   45799:                     $this->log(0, "Warning: " . $res->getMessage());
                   45800:                 }
                   45801:             }
                   45802: 
                   45803:             $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
                   45804:             if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
                   45805:                 // Register files that were installed
                   45806:                 $pkg->installedFile($file, $atts);
                   45807:             }
                   45808:         }
                   45809:         // }}}
                   45810: 
                   45811:         // {{{ compile and install source files
                   45812:         if ($this->source_files > 0 && empty($options['nobuild'])) {
                   45813:             if (PEAR::isError($err =
                   45814:                   $this->_compileSourceFiles($savechannel, $pkg))) {
                   45815:                 return $err;
                   45816:             }
                   45817:         }
                   45818:         // }}}
                   45819: 
                   45820:         if (isset($backedup)) {
                   45821:             $this->_removeBackups($backedup);
                   45822:         }
                   45823: 
                   45824:         if (!$this->commitFileTransaction()) {
                   45825:             $this->rollbackFileTransaction();
                   45826:             $this->configSet('default_channel', $savechannel);
                   45827:             return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
                   45828:         }
                   45829:         // }}}
                   45830: 
                   45831:         $ret          = false;
                   45832:         $installphase = 'install';
                   45833:         $oldversion   = false;
                   45834:         // {{{ Register that the package is installed -----------------------
                   45835:         if (empty($options['upgrade'])) {
                   45836:             // if 'force' is used, replace the info in registry
                   45837:             $usechannel = $channel;
                   45838:             if ($channel == 'pecl.php.net') {
                   45839:                 $test = $installregistry->packageExists($pkgname, $channel);
                   45840:                 if (!$test) {
                   45841:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   45842:                     $usechannel = 'pear.php.net';
                   45843:                 }
                   45844:             } else {
                   45845:                 $test = $installregistry->packageExists($pkgname, $channel);
                   45846:             }
                   45847: 
                   45848:             if (!empty($options['force']) && $test) {
                   45849:                 $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                   45850:                 $installregistry->deletePackage($pkgname, $usechannel);
                   45851:             }
                   45852:             $ret = $installregistry->addPackage2($pkg);
                   45853:         } else {
                   45854:             if ($dirtree) {
                   45855:                 $this->startFileTransaction();
                   45856:                 // attempt to delete empty directories
                   45857:                 uksort($dirtree, array($this, '_sortDirs'));
                   45858:                 foreach($dirtree as $dir => $notused) {
                   45859:                     $this->addFileOperation('rmdir', array($dir));
                   45860:                 }
                   45861:                 $this->commitFileTransaction();
                   45862:             }
                   45863: 
                   45864:             $usechannel = $channel;
                   45865:             if ($channel == 'pecl.php.net') {
                   45866:                 $test = $installregistry->packageExists($pkgname, $channel);
                   45867:                 if (!$test) {
                   45868:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   45869:                     $usechannel = 'pear.php.net';
                   45870:                 }
                   45871:             } else {
                   45872:                 $test = $installregistry->packageExists($pkgname, $channel);
                   45873:             }
                   45874: 
                   45875:             // new: upgrade installs a package if it isn't installed
                   45876:             if (!$test) {
                   45877:                 $ret = $installregistry->addPackage2($pkg);
                   45878:             } else {
                   45879:                 if ($usechannel != $channel) {
                   45880:                     $installregistry->deletePackage($pkgname, $usechannel);
                   45881:                     $ret = $installregistry->addPackage2($pkg);
                   45882:                 } else {
                   45883:                     $ret = $installregistry->updatePackage2($pkg);
                   45884:                 }
                   45885:                 $installphase = 'upgrade';
                   45886:             }
                   45887:         }
                   45888: 
                   45889:         if (!$ret) {
                   45890:             $this->configSet('default_channel', $savechannel);
                   45891:             return $this->raiseError("Adding package $channel/$pkgname to registry failed");
                   45892:         }
                   45893:         // }}}
                   45894: 
                   45895:         $this->configSet('default_channel', $savechannel);
                   45896:         if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
                   45897:             if (PEAR_Task_Common::hasPostinstallTasks()) {
                   45898:                 PEAR_Task_Common::runPostinstallTasks($installphase);
                   45899:             }
                   45900:         }
                   45901: 
                   45902:         return $pkg->toArray(true);
                   45903:     }
                   45904: 
                   45905:     // }}}
                   45906: 
                   45907:     // {{{ _compileSourceFiles()
                   45908:     /**
                   45909:      * @param string
                   45910:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   45911:      */
                   45912:     function _compileSourceFiles($savechannel, &$filelist)
                   45913:     {
                   45914:         require_once 'PEAR/Builder.php';
                   45915:         $this->log(1, "$this->source_files source files, building");
                   45916:         $bob = &new PEAR_Builder($this->ui);
                   45917:         $bob->debug = $this->debug;
                   45918:         $built = $bob->build($filelist, array(&$this, '_buildCallback'));
                   45919:         if (PEAR::isError($built)) {
                   45920:             $this->rollbackFileTransaction();
                   45921:             $this->configSet('default_channel', $savechannel);
                   45922:             return $built;
                   45923:         }
                   45924: 
                   45925:         $this->log(1, "\nBuild process completed successfully");
                   45926:         foreach ($built as $ext) {
                   45927:             $bn = basename($ext['file']);
                   45928:             list($_ext_name, $_ext_suff) = explode('.', $bn);
                   45929:             if ($_ext_suff == '.so' || $_ext_suff == '.dll') {
                   45930:                 if (extension_loaded($_ext_name)) {
                   45931:                     $this->raiseError("Extension '$_ext_name' already loaded. " .
                   45932:                                       'Please unload it in your php.ini file ' .
                   45933:                                       'prior to install or upgrade');
                   45934:                 }
                   45935:                 $role = 'ext';
                   45936:             } else {
                   45937:                 $role = 'src';
                   45938:             }
                   45939: 
                   45940:             $dest = $ext['dest'];
                   45941:             $packagingroot = '';
                   45942:             if (isset($this->_options['packagingroot'])) {
                   45943:                 $packagingroot = $this->_options['packagingroot'];
                   45944:             }
                   45945: 
                   45946:             $copyto = $this->_prependPath($dest, $packagingroot);
                   45947:             $extra  = $copyto != $dest ? " as '$copyto'" : '';
                   45948:             $this->log(1, "Installing '$dest'$extra");
                   45949: 
                   45950:             $copydir = dirname($copyto);
                   45951:             // pretty much nothing happens if we are only registering the install
                   45952:             if (empty($this->_options['register-only'])) {
                   45953:                 if (!file_exists($copydir) || !is_dir($copydir)) {
                   45954:                     if (!$this->mkDirHier($copydir)) {
                   45955:                         return $this->raiseError("failed to mkdir $copydir",
                   45956:                             PEAR_INSTALLER_FAILED);
                   45957:                     }
                   45958: 
                   45959:                     $this->log(3, "+ mkdir $copydir");
                   45960:                 }
                   45961: 
                   45962:                 if (!@copy($ext['file'], $copyto)) {
                   45963:                     return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED);
                   45964:                 }
                   45965: 
                   45966:                 $this->log(3, "+ cp $ext[file] $copyto");
                   45967:                 $this->addFileOperation('rename', array($ext['file'], $copyto));
                   45968:                 if (!OS_WINDOWS) {
                   45969:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   45970:                     $this->addFileOperation('chmod', array($mode, $copyto));
                   45971:                     if (!@chmod($copyto, $mode)) {
                   45972:                         $this->log(0, "failed to change mode of $copyto ($php_errormsg)");
                   45973:                     }
                   45974:                 }
                   45975:             }
                   45976: 
                   45977: 
                   45978:             $data = array(
                   45979:                 'role'         => $role,
                   45980:                 'name'         => $bn,
                   45981:                 'installed_as' => $dest,
                   45982:                 'php_api'      => $ext['php_api'],
                   45983:                 'zend_mod_api' => $ext['zend_mod_api'],
                   45984:                 'zend_ext_api' => $ext['zend_ext_api'],
                   45985:             );
                   45986: 
                   45987:             if ($filelist->getPackageXmlVersion() == '1.0') {
                   45988:                 $filelist->installedFile($bn, $data);
                   45989:             } else {
                   45990:                 $filelist->installedFile($bn, array('attribs' => $data));
                   45991:             }
                   45992:         }
                   45993:     }
                   45994: 
                   45995:     // }}}
                   45996:     function &getUninstallPackages()
                   45997:     {
                   45998:         return $this->_downloadedPackages;
                   45999:     }
                   46000:     // {{{ uninstall()
                   46001: 
                   46002:     /**
                   46003:      * Uninstall a package
                   46004:      *
                   46005:      * This method removes all files installed by the application, and then
                   46006:      * removes any empty directories.
                   46007:      * @param string package name
                   46008:      * @param array Command-line options.  Possibilities include:
                   46009:      *
                   46010:      *              - installroot: base installation dir, if not the default
                   46011:      *              - register-only : update registry but don't remove files
                   46012:      *              - nodeps: do not process dependencies of other packages to ensure
                   46013:      *                        uninstallation does not break things
                   46014:      */
                   46015:     function uninstall($package, $options = array())
                   46016:     {
                   46017:         $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
                   46018:         $this->config->setInstallRoot($installRoot);
                   46019: 
                   46020:         $this->installroot = '';
                   46021:         $this->_registry = &$this->config->getRegistry();
                   46022:         if (is_object($package)) {
                   46023:             $channel = $package->getChannel();
                   46024:             $pkg     = $package;
                   46025:             $package = $pkg->getPackage();
                   46026:         } else {
                   46027:             $pkg = false;
                   46028:             $info = $this->_registry->parsePackageName($package,
                   46029:                 $this->config->get('default_channel'));
                   46030:             $channel = $info['channel'];
                   46031:             $package = $info['package'];
                   46032:         }
                   46033: 
                   46034:         $savechannel = $this->config->get('default_channel');
                   46035:         $this->configSet('default_channel', $channel);
                   46036:         if (!is_object($pkg)) {
                   46037:             $pkg = $this->_registry->getPackage($package, $channel);
                   46038:         }
                   46039: 
                   46040:         if (!$pkg) {
                   46041:             $this->configSet('default_channel', $savechannel);
                   46042:             return $this->raiseError($this->_registry->parsedPackageNameToString(
                   46043:                 array(
                   46044:                     'channel' => $channel,
                   46045:                     'package' => $package
                   46046:                 ), true) . ' not installed');
                   46047:         }
                   46048: 
                   46049:         if ($pkg->getInstalledBinary()) {
                   46050:             // this is just an alias for a binary package
                   46051:             return $this->_registry->deletePackage($package, $channel);
                   46052:         }
                   46053: 
                   46054:         $filelist = $pkg->getFilelist();
                   46055:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   46056:         if (!class_exists('PEAR_Dependency2')) {
                   46057:             require_once 'PEAR/Dependency2.php';
                   46058:         }
                   46059: 
                   46060:         $depchecker = &new PEAR_Dependency2($this->config, $options,
                   46061:             array('channel' => $channel, 'package' => $package),
                   46062:             PEAR_VALIDATE_UNINSTALLING);
                   46063:         $e = $depchecker->validatePackageUninstall($this);
                   46064:         PEAR::staticPopErrorHandling();
                   46065:         if (PEAR::isError($e)) {
                   46066:             if (!isset($options['ignore-errors'])) {
                   46067:                 return $this->raiseError($e);
                   46068:             }
                   46069: 
                   46070:             if (!isset($options['soft'])) {
                   46071:                 $this->log(0, 'WARNING: ' . $e->getMessage());
                   46072:             }
                   46073:         } elseif (is_array($e)) {
                   46074:             if (!isset($options['soft'])) {
                   46075:                 $this->log(0, $e[0]);
                   46076:             }
                   46077:         }
                   46078: 
                   46079:         $this->pkginfo = &$pkg;
                   46080:         // pretty much nothing happens if we are only registering the uninstall
                   46081:         if (empty($options['register-only'])) {
                   46082:             // {{{ Delete the files
                   46083:             $this->startFileTransaction();
                   46084:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   46085:             if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
                   46086:                 PEAR::popErrorHandling();
                   46087:                 $this->rollbackFileTransaction();
                   46088:                 $this->configSet('default_channel', $savechannel);
                   46089:                 if (!isset($options['ignore-errors'])) {
                   46090:                     return $this->raiseError($err);
                   46091:                 }
                   46092: 
                   46093:                 if (!isset($options['soft'])) {
                   46094:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   46095:                 }
                   46096:             } else {
                   46097:                 PEAR::popErrorHandling();
                   46098:             }
                   46099: 
                   46100:             if (!$this->commitFileTransaction()) {
                   46101:                 $this->rollbackFileTransaction();
                   46102:                 if (!isset($options['ignore-errors'])) {
                   46103:                     return $this->raiseError("uninstall failed");
                   46104:                 }
                   46105: 
                   46106:                 if (!isset($options['soft'])) {
                   46107:                     $this->log(0, 'WARNING: uninstall failed');
                   46108:                 }
                   46109:             } else {
                   46110:                 $this->startFileTransaction();
                   46111:                 $dirtree = $pkg->getDirTree();
                   46112:                 if ($dirtree === false) {
                   46113:                     $this->configSet('default_channel', $savechannel);
                   46114:                     return $this->_registry->deletePackage($package, $channel);
                   46115:                 }
                   46116: 
                   46117:                 // attempt to delete empty directories
                   46118:                 uksort($dirtree, array($this, '_sortDirs'));
                   46119:                 foreach($dirtree as $dir => $notused) {
                   46120:                     $this->addFileOperation('rmdir', array($dir));
                   46121:                 }
                   46122: 
                   46123:                 if (!$this->commitFileTransaction()) {
                   46124:                     $this->rollbackFileTransaction();
                   46125:                     if (!isset($options['ignore-errors'])) {
                   46126:                         return $this->raiseError("uninstall failed");
                   46127:                     }
                   46128: 
                   46129:                     if (!isset($options['soft'])) {
                   46130:                         $this->log(0, 'WARNING: uninstall failed');
                   46131:                     }
                   46132:                 }
                   46133:             }
                   46134:             // }}}
                   46135:         }
                   46136: 
                   46137:         $this->configSet('default_channel', $savechannel);
                   46138:         // Register that the package is no longer installed
                   46139:         return $this->_registry->deletePackage($package, $channel);
                   46140:     }
                   46141: 
                   46142:     /**
                   46143:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   46144:      *
                   46145:      * It also removes duplicate dependencies
                   46146:      * @param array an array of PEAR_PackageFile_v[1/2] objects
                   46147:      * @return array|PEAR_Error array of array(packagefilename, package.xml contents)
                   46148:      */
                   46149:     function sortPackagesForUninstall(&$packages)
                   46150:     {
                   46151:         $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
                   46152:         if (PEAR::isError($this->_dependencyDB)) {
                   46153:             return $this->_dependencyDB;
                   46154:         }
                   46155:         usort($packages, array(&$this, '_sortUninstall'));
                   46156:     }
                   46157: 
                   46158:     function _sortUninstall($a, $b)
                   46159:     {
                   46160:         if (!$a->getDeps() && !$b->getDeps()) {
                   46161:             return 0; // neither package has dependencies, order is insignificant
                   46162:         }
                   46163:         if ($a->getDeps() && !$b->getDeps()) {
                   46164:             return -1; // $a must be installed after $b because $a has dependencies
                   46165:         }
                   46166:         if (!$a->getDeps() && $b->getDeps()) {
                   46167:             return 1; // $b must be installed after $a because $b has dependencies
                   46168:         }
                   46169:         // both packages have dependencies
                   46170:         if ($this->_dependencyDB->dependsOn($a, $b)) {
                   46171:             return -1;
                   46172:         }
                   46173:         if ($this->_dependencyDB->dependsOn($b, $a)) {
                   46174:             return 1;
                   46175:         }
                   46176:         return 0;
                   46177:     }
                   46178: 
                   46179:     // }}}
                   46180:     // {{{ _sortDirs()
                   46181:     function _sortDirs($a, $b)
                   46182:     {
                   46183:         if (strnatcmp($a, $b) == -1) return 1;
                   46184:         if (strnatcmp($a, $b) == 1) return -1;
                   46185:         return 0;
                   46186:     }
                   46187: 
                   46188:     // }}}
                   46189: 
                   46190:     // {{{ _buildCallback()
                   46191: 
                   46192:     function _buildCallback($what, $data)
                   46193:     {
                   46194:         if (($what == 'cmdoutput' && $this->debug > 1) ||
                   46195:             ($what == 'output' && $this->debug > 0)) {
                   46196:             $this->ui->outputData(rtrim($data), 'build');
                   46197:         }
                   46198:     }
                   46199: 
                   46200:     // }}}
                   46201: }PEAR-1.9.4/PEAR/PackageFile.php0000644000076500000240000003705511605156760014643 0ustar  helgistaff<?php
                   46202: /**
                   46203:  * PEAR_PackageFile, package.xml parsing utility class
                   46204:  *
                   46205:  * PHP versions 4 and 5
                   46206:  *
                   46207:  * @category   pear
                   46208:  * @package    PEAR
                   46209:  * @author     Greg Beaver <cellog@php.net>
                   46210:  * @copyright  1997-2009 The Authors
                   46211:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46212:  * @version    CVS: $Id: PackageFile.php 313024 2011-07-06 19:51:24Z dufuz $
                   46213:  * @link       http://pear.php.net/package/PEAR
                   46214:  * @since      File available since Release 1.4.0a1
                   46215:  */
                   46216: 
                   46217: /**
                   46218:  * needed for PEAR_VALIDATE_* constants
                   46219:  */
                   46220: require_once 'PEAR/Validate.php';
                   46221: /**
                   46222:  * Error code if the package.xml <package> tag does not contain a valid version
                   46223:  */
                   46224: define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
                   46225: /**
                   46226:  * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
                   46227:  * currently
                   46228:  */
                   46229: define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
                   46230: /**
                   46231:  * Abstraction for the package.xml package description file
                   46232:  *
                   46233:  * @category   pear
                   46234:  * @package    PEAR
                   46235:  * @author     Greg Beaver <cellog@php.net>
                   46236:  * @copyright  1997-2009 The Authors
                   46237:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46238:  * @version    Release: 1.9.4
                   46239:  * @link       http://pear.php.net/package/PEAR
                   46240:  * @since      Class available since Release 1.4.0a1
                   46241:  */
                   46242: class PEAR_PackageFile
                   46243: {
                   46244:     /**
                   46245:      * @var PEAR_Config
                   46246:      */
                   46247:     var $_config;
                   46248:     var $_debug;
                   46249: 
                   46250:     var $_logger = false;
                   46251:     /**
                   46252:      * @var boolean
                   46253:      */
                   46254:     var $_rawReturn = false;
                   46255: 
                   46256:     /**
                   46257:      * helper for extracting Archive_Tar errors
                   46258:      * @var array
                   46259:      * @access private
                   46260:      */
                   46261:     var $_extractErrors = array();
                   46262: 
                   46263:     /**
                   46264:      *
                   46265:      * @param   PEAR_Config $config
                   46266:      * @param   ?   $debug
                   46267:      * @param   string @tmpdir Optional temporary directory for uncompressing
                   46268:      *          files
                   46269:      */
                   46270:     function PEAR_PackageFile(&$config, $debug = false)
                   46271:     {
                   46272:         $this->_config = $config;
                   46273:         $this->_debug = $debug;
                   46274:     }
                   46275: 
                   46276:     /**
                   46277:      * Turn off validation - return a parsed package.xml without checking it
                   46278:      *
                   46279:      * This is used by the package-validate command
                   46280:      */
                   46281:     function rawReturn()
                   46282:     {
                   46283:         $this->_rawReturn = true;
                   46284:     }
                   46285: 
                   46286:     function setLogger(&$l)
                   46287:     {
                   46288:         $this->_logger = &$l;
                   46289:     }
                   46290: 
                   46291:     /**
                   46292:      * Create a PEAR_PackageFile_Parser_v* of a given version.
                   46293:      * @param   int $version
                   46294:      * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
                   46295:      */
                   46296:     function &parserFactory($version)
                   46297:     {
                   46298:         if (!in_array($version{0}, array('1', '2'))) {
                   46299:             $a = false;
                   46300:             return $a;
                   46301:         }
                   46302: 
                   46303:         include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
                   46304:         $version = $version{0};
                   46305:         $class = "PEAR_PackageFile_Parser_v$version";
                   46306:         $a = new $class;
                   46307:         return $a;
                   46308:     }
                   46309: 
                   46310:     /**
                   46311:      * For simpler unit-testing
                   46312:      * @return string
                   46313:      */
                   46314:     function getClassPrefix()
                   46315:     {
                   46316:         return 'PEAR_PackageFile_v';
                   46317:     }
                   46318: 
                   46319:     /**
                   46320:      * Create a PEAR_PackageFile_v* of a given version.
                   46321:      * @param   int $version
                   46322:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
                   46323:      */
                   46324:     function &factory($version)
                   46325:     {
                   46326:         if (!in_array($version{0}, array('1', '2'))) {
                   46327:             $a = false;
                   46328:             return $a;
                   46329:         }
                   46330: 
                   46331:         include_once 'PEAR/PackageFile/v' . $version{0} . '.php';
                   46332:         $version = $version{0};
                   46333:         $class = $this->getClassPrefix() . $version;
                   46334:         $a = new $class;
                   46335:         return $a;
                   46336:     }
                   46337: 
                   46338:     /**
                   46339:      * Create a PEAR_PackageFile_v* from its toArray() method
                   46340:      *
                   46341:      * WARNING: no validation is performed, the array is assumed to be valid,
                   46342:      * always parse from xml if you want validation.
                   46343:      * @param   array $arr
                   46344:      * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
                   46345:      * @uses    factory() to construct the returned object.
                   46346:      */
                   46347:     function &fromArray($arr)
                   46348:     {
                   46349:         if (isset($arr['xsdversion'])) {
                   46350:             $obj = &$this->factory($arr['xsdversion']);
                   46351:             if ($this->_logger) {
                   46352:                 $obj->setLogger($this->_logger);
                   46353:             }
                   46354: 
                   46355:             $obj->setConfig($this->_config);
                   46356:             $obj->fromArray($arr);
                   46357:             return $obj;
                   46358:         }
                   46359: 
                   46360:         if (isset($arr['package']['attribs']['version'])) {
                   46361:             $obj = &$this->factory($arr['package']['attribs']['version']);
                   46362:         } else {
                   46363:             $obj = &$this->factory('1.0');
                   46364:         }
                   46365: 
                   46366:         if ($this->_logger) {
                   46367:             $obj->setLogger($this->_logger);
                   46368:         }
                   46369: 
                   46370:         $obj->setConfig($this->_config);
                   46371:         $obj->fromArray($arr);
                   46372:         return $obj;
                   46373:     }
                   46374: 
                   46375:     /**
                   46376:      * Create a PEAR_PackageFile_v* from an XML string.
                   46377:      * @access  public
                   46378:      * @param   string $data contents of package.xml file
                   46379:      * @param   int $state package state (one of PEAR_VALIDATE_* constants)
                   46380:      * @param   string $file full path to the package.xml file (and the files
                   46381:      *          it references)
                   46382:      * @param   string $archive optional name of the archive that the XML was
                   46383:      *          extracted from, if any
                   46384:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46385:      * @uses    parserFactory() to construct a parser to load the package.
                   46386:      */
                   46387:     function &fromXmlString($data, $state, $file, $archive = false)
                   46388:     {
                   46389:         if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
                   46390:             if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
                   46391:                 return PEAR::raiseError('package.xml version "' . $packageversion[1] .
                   46392:                     '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
                   46393:             }
                   46394: 
                   46395:             $object = &$this->parserFactory($packageversion[1]);
                   46396:             if ($this->_logger) {
                   46397:                 $object->setLogger($this->_logger);
                   46398:             }
                   46399: 
                   46400:             $object->setConfig($this->_config);
                   46401:             $pf = $object->parse($data, $file, $archive);
                   46402:             if (PEAR::isError($pf)) {
                   46403:                 return $pf;
                   46404:             }
                   46405: 
                   46406:             if ($this->_rawReturn) {
                   46407:                 return $pf;
                   46408:             }
                   46409: 
                   46410:             if (!$pf->validate($state)) {;
                   46411:                 if ($this->_config->get('verbose') > 0
                   46412:                     && $this->_logger && $pf->getValidationWarnings(false)
                   46413:                 ) {
                   46414:                     foreach ($pf->getValidationWarnings(false) as $warning) {
                   46415:                         $this->_logger->log(0, 'ERROR: ' . $warning['message']);
                   46416:                     }
                   46417:                 }
                   46418: 
                   46419:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   46420:                     2, null, null, $pf->getValidationWarnings());
                   46421:                 return $a;
                   46422:             }
                   46423: 
                   46424:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   46425:                 foreach ($pf->getValidationWarnings() as $warning) {
                   46426:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   46427:                 }
                   46428:             }
                   46429: 
                   46430:             if (method_exists($pf, 'flattenFilelist')) {
                   46431:                 $pf->flattenFilelist(); // for v2
                   46432:             }
                   46433: 
                   46434:             return $pf;
                   46435:         } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
                   46436:             $a = PEAR::raiseError('package.xml file "' . $file .
                   46437:                 '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
                   46438:             return $a;
                   46439:         } else {
                   46440:             if (!class_exists('PEAR_ErrorStack')) {
                   46441:                 require_once 'PEAR/ErrorStack.php';
                   46442:             }
                   46443: 
                   46444:             PEAR_ErrorStack::staticPush('PEAR_PackageFile',
                   46445:                 PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
                   46446:                 'warning', array('xml' => $data), 'package.xml "' . $file .
                   46447:                     '" has no package.xml <package> version');
                   46448:             $object = &$this->parserFactory('1.0');
                   46449:             $object->setConfig($this->_config);
                   46450:             $pf = $object->parse($data, $file, $archive);
                   46451:             if (PEAR::isError($pf)) {
                   46452:                 return $pf;
                   46453:             }
                   46454: 
                   46455:             if ($this->_rawReturn) {
                   46456:                 return $pf;
                   46457:             }
                   46458: 
                   46459:             if (!$pf->validate($state)) {
                   46460:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   46461:                     2, null, null, $pf->getValidationWarnings());
                   46462:                 return $a;
                   46463:             }
                   46464: 
                   46465:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   46466:                 foreach ($pf->getValidationWarnings() as $warning) {
                   46467:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   46468:                 }
                   46469:             }
                   46470: 
                   46471:             if (method_exists($pf, 'flattenFilelist')) {
                   46472:                 $pf->flattenFilelist(); // for v2
                   46473:             }
                   46474: 
                   46475:             return $pf;
                   46476:         }
                   46477:     }
                   46478: 
                   46479:     /**
                   46480:      * Register a temporary file or directory.  When the destructor is
                   46481:      * executed, all registered temporary files and directories are
                   46482:      * removed.
                   46483:      *
                   46484:      * @param string  $file  name of file or directory
                   46485:      * @return  void
                   46486:      */
                   46487:     function addTempFile($file)
                   46488:     {
                   46489:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   46490:     }
                   46491: 
                   46492:     /**
                   46493:      * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
                   46494:      * @access  public
                   46495:      * @param string contents of package.xml file
                   46496:      * @param int package state (one of PEAR_VALIDATE_* constants)
                   46497:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46498:      * @using   Archive_Tar to extract the files
                   46499:      * @using   fromPackageFile() to load the package after the package.xml
                   46500:      *          file is extracted.
                   46501:      */
                   46502:     function &fromTgzFile($file, $state)
                   46503:     {
                   46504:         if (!class_exists('Archive_Tar')) {
                   46505:             require_once 'Archive/Tar.php';
                   46506:         }
                   46507: 
                   46508:         $tar = new Archive_Tar($file);
                   46509:         if ($this->_debug <= 1) {
                   46510:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   46511:         }
                   46512: 
                   46513:         $content = $tar->listContent();
                   46514:         if ($this->_debug <= 1) {
                   46515:             $tar->popErrorHandling();
                   46516:         }
                   46517: 
                   46518:         if (!is_array($content)) {
                   46519:             if (is_string($file) && strlen($file < 255) &&
                   46520:                   (!file_exists($file) || !@is_file($file))) {
                   46521:                 $ret = PEAR::raiseError("could not open file \"$file\"");
                   46522:                 return $ret;
                   46523:             }
                   46524: 
                   46525:             $file = realpath($file);
                   46526:             $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                   46527:                                      '. Invalid tgz file.');
                   46528:             return $ret;
                   46529:         }
                   46530: 
                   46531:         if (!count($content) && !@is_file($file)) {
                   46532:             $ret = PEAR::raiseError("could not open file \"$file\"");
                   46533:             return $ret;
                   46534:         }
                   46535: 
                   46536:         $xml      = null;
                   46537:         $origfile = $file;
                   46538:         foreach ($content as $file) {
                   46539:             $name = $file['filename'];
                   46540:             if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
                   46541:                 $xml = $name;
                   46542:                 break;
                   46543:             }
                   46544: 
                   46545:             if ($name == 'package.xml') {
                   46546:                 $xml = $name;
                   46547:                 break;
                   46548:             } elseif (preg_match('/package.xml$/', $name, $match)) {
                   46549:                 $xml = $name;
                   46550:                 break;
                   46551:             }
                   46552:         }
                   46553: 
                   46554:         $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
                   46555:         if ($tmpdir === false) {
                   46556:             $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
                   46557:             return $ret;
                   46558:         }
                   46559: 
                   46560:         PEAR_PackageFile::addTempFile($tmpdir);
                   46561: 
                   46562:         $this->_extractErrors();
                   46563:         PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
                   46564: 
                   46565:         if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
                   46566:             $extra = implode("\n", $this->_extractErrors());
                   46567:             if ($extra) {
                   46568:                 $extra = ' ' . $extra;
                   46569:             }
                   46570: 
                   46571:             PEAR::staticPopErrorHandling();
                   46572:             $ret = PEAR::raiseError('could not extract the package.xml file from "' .
                   46573:                 $origfile . '"' . $extra);
                   46574:             return $ret;
                   46575:         }
                   46576: 
                   46577:         PEAR::staticPopErrorHandling();
                   46578:         $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
                   46579:         return $ret;
                   46580:     }
                   46581: 
                   46582:     /**
                   46583:      * helper callback for extracting Archive_Tar errors
                   46584:      *
                   46585:      * @param PEAR_Error|null $err
                   46586:      * @return array
                   46587:      * @access private
                   46588:      */
                   46589:     function _extractErrors($err = null)
                   46590:     {
                   46591:         static $errors = array();
                   46592:         if ($err === null) {
                   46593:             $e = $errors;
                   46594:             $errors = array();
                   46595:             return $e;
                   46596:         }
                   46597:         $errors[] = $err->getMessage();
                   46598:     }
                   46599: 
                   46600:     /**
                   46601:      * Create a PEAR_PackageFile_v* from a package.xml file.
                   46602:      *
                   46603:      * @access public
                   46604:      * @param   string  $descfile  name of package xml file
                   46605:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   46606:      * @param   string|false $archive name of the archive this package.xml came
                   46607:      *          from, if any
                   46608:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46609:      * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
                   46610:      *          XML is loaded from the package.xml file.
                   46611:      */
                   46612:     function &fromPackageFile($descfile, $state, $archive = false)
                   46613:     {
                   46614:         $fp = false;
                   46615:         if (is_string($descfile) && strlen($descfile) < 255 &&
                   46616:              (
                   46617:               !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
                   46618:               || (!$fp = @fopen($descfile, 'r'))
                   46619:              )
                   46620:         ) {
                   46621:             $a = PEAR::raiseError("Unable to open $descfile");
                   46622:             return $a;
                   46623:         }
                   46624: 
                   46625:         // read the whole thing so we only get one cdata callback
                   46626:         // for each block of cdata
                   46627:         fclose($fp);
                   46628:         $data = file_get_contents($descfile);
                   46629:         $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
                   46630:         return $ret;
                   46631:     }
                   46632: 
                   46633:     /**
                   46634:      * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
                   46635:      *
                   46636:      * This method is able to extract information about a package from a .tgz
                   46637:      * archive or from a XML package definition file.
                   46638:      *
                   46639:      * @access public
                   46640:      * @param   string  $info file name
                   46641:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   46642:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46643:      * @uses    fromPackageFile() if the file appears to be XML
                   46644:      * @uses    fromTgzFile() to load all non-XML files
                   46645:      */
                   46646:     function &fromAnyFile($info, $state)
                   46647:     {
                   46648:         if (is_dir($info)) {
                   46649:             $dir_name = realpath($info);
                   46650:             if (file_exists($dir_name . '/package.xml')) {
                   46651:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
                   46652:             } elseif (file_exists($dir_name .  '/package2.xml')) {
                   46653:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
                   46654:             } else {
                   46655:                 $info = PEAR::raiseError("No package definition found in '$info' directory");
                   46656:             }
                   46657: 
                   46658:             return $info;
                   46659:         }
                   46660: 
                   46661:         $fp = false;
                   46662:         if (is_string($info) && strlen($info) < 255 &&
                   46663:              (file_exists($info) || ($fp = @fopen($info, 'r')))
                   46664:         ) {
                   46665: 
                   46666:             if ($fp) {
                   46667:                 fclose($fp);
                   46668:             }
                   46669: 
                   46670:             $tmp = substr($info, -4);
                   46671:             if ($tmp == '.xml') {
                   46672:                 $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   46673:             } elseif ($tmp == '.tar' || $tmp == '.tgz') {
                   46674:                 $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   46675:             } else {
                   46676:                 $fp   = fopen($info, 'r');
                   46677:                 $test = fread($fp, 5);
                   46678:                 fclose($fp);
                   46679:                 if ($test == '<?xml') {
                   46680:                     $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   46681:                 } else {
                   46682:                     $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   46683:                 }
                   46684:             }
                   46685: 
                   46686:             return $info;
                   46687:         }
                   46688: 
                   46689:         $info = PEAR::raiseError("Cannot open '$info' for parsing");
                   46690:         return $info;
                   46691:     }
                   46692: }PEAR-1.9.4/PEAR/Packager.php0000644000076500000240000001715111605156760014220 0ustar  helgistaff<?php
                   46693: /**
                   46694:  * PEAR_Packager for generating releases
                   46695:  *
                   46696:  * PHP versions 4 and 5
                   46697:  *
                   46698:  * @category   pear
                   46699:  * @package    PEAR
                   46700:  * @author     Stig Bakken <ssb@php.net>
                   46701:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   46702:  * @author     Greg Beaver <cellog@php.net>
                   46703:  * @copyright  1997-2009 The Authors
                   46704:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46705:  * @version    CVS: $Id: Packager.php 313023 2011-07-06 19:17:11Z dufuz $
                   46706:  * @link       http://pear.php.net/package/PEAR
                   46707:  * @since      File available since Release 0.1
                   46708:  */
                   46709: 
                   46710: /**
                   46711:  * base class
                   46712:  */
                   46713: require_once 'PEAR/Common.php';
                   46714: require_once 'PEAR/PackageFile.php';
                   46715: require_once 'System.php';
                   46716: 
                   46717: /**
                   46718:  * Administration class used to make a PEAR release tarball.
                   46719:  *
                   46720:  * @category   pear
                   46721:  * @package    PEAR
                   46722:  * @author     Greg Beaver <cellog@php.net>
                   46723:  * @copyright  1997-2009 The Authors
                   46724:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46725:  * @version    Release: 1.9.4
                   46726:  * @link       http://pear.php.net/package/PEAR
                   46727:  * @since      Class available since Release 0.1
                   46728:  */
                   46729: class PEAR_Packager extends PEAR_Common
                   46730: {
                   46731:     /**
                   46732:      * @var PEAR_Registry
                   46733:      */
                   46734:     var $_registry;
                   46735: 
                   46736:     function package($pkgfile = null, $compress = true, $pkg2 = null)
                   46737:     {
                   46738:         // {{{ validate supplied package.xml file
                   46739:         if (empty($pkgfile)) {
                   46740:             $pkgfile = 'package.xml';
                   46741:         }
                   46742: 
                   46743:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   46744:         $pkg  = &new PEAR_PackageFile($this->config, $this->debug);
                   46745:         $pf   = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
                   46746:         $main = &$pf;
                   46747:         PEAR::staticPopErrorHandling();
                   46748:         if (PEAR::isError($pf)) {
                   46749:             if (is_array($pf->getUserInfo())) {
                   46750:                 foreach ($pf->getUserInfo() as $error) {
                   46751:                     $this->log(0, 'Error: ' . $error['message']);
                   46752:                 }
                   46753:             }
                   46754: 
                   46755:             $this->log(0, $pf->getMessage());
                   46756:             return $this->raiseError("Cannot package, errors in package file");
                   46757:         }
                   46758: 
                   46759:         foreach ($pf->getValidationWarnings() as $warning) {
                   46760:             $this->log(1, 'Warning: ' . $warning['message']);
                   46761:         }
                   46762: 
                   46763:         // }}}
                   46764:         if ($pkg2) {
                   46765:             $this->log(0, 'Attempting to process the second package file');
                   46766:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   46767:             $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
                   46768:             PEAR::staticPopErrorHandling();
                   46769:             if (PEAR::isError($pf2)) {
                   46770:                 if (is_array($pf2->getUserInfo())) {
                   46771:                     foreach ($pf2->getUserInfo() as $error) {
                   46772:                         $this->log(0, 'Error: ' . $error['message']);
                   46773:                     }
                   46774:                 }
                   46775:                 $this->log(0, $pf2->getMessage());
                   46776:                 return $this->raiseError("Cannot package, errors in second package file");
                   46777:             }
                   46778: 
                   46779:             foreach ($pf2->getValidationWarnings() as $warning) {
                   46780:                 $this->log(1, 'Warning: ' . $warning['message']);
                   46781:             }
                   46782: 
                   46783:             if ($pf2->getPackagexmlVersion() == '2.0' ||
                   46784:                   $pf2->getPackagexmlVersion() == '2.1'
                   46785:             ) {
                   46786:                 $main  = &$pf2;
                   46787:                 $other = &$pf;
                   46788:             } else {
                   46789:                 $main  = &$pf;
                   46790:                 $other = &$pf2;
                   46791:             }
                   46792: 
                   46793:             if ($main->getPackagexmlVersion() != '2.0' &&
                   46794:                   $main->getPackagexmlVersion() != '2.1') {
                   46795:                 return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
                   46796:                     'only package together a package.xml 1.0 and package.xml 2.0');
                   46797:             }
                   46798: 
                   46799:             if ($other->getPackagexmlVersion() != '1.0') {
                   46800:                 return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
                   46801:                     'only package together a package.xml 1.0 and package.xml 2.0');
                   46802:             }
                   46803:         }
                   46804: 
                   46805:         $main->setLogger($this);
                   46806:         if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
                   46807:             foreach ($main->getValidationWarnings() as $warning) {
                   46808:                 $this->log(0, 'Error: ' . $warning['message']);
                   46809:             }
                   46810:             return $this->raiseError("Cannot package, errors in package");
                   46811:         }
                   46812: 
                   46813:         foreach ($main->getValidationWarnings() as $warning) {
                   46814:             $this->log(1, 'Warning: ' . $warning['message']);
                   46815:         }
                   46816: 
                   46817:         if ($pkg2) {
                   46818:             $other->setLogger($this);
                   46819:             $a = false;
                   46820:             if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
                   46821:                 foreach ($other->getValidationWarnings() as $warning) {
                   46822:                     $this->log(0, 'Error: ' . $warning['message']);
                   46823:                 }
                   46824: 
                   46825:                 foreach ($main->getValidationWarnings() as $warning) {
                   46826:                     $this->log(0, 'Error: ' . $warning['message']);
                   46827:                 }
                   46828: 
                   46829:                 if ($a) {
                   46830:                     return $this->raiseError('The two package.xml files are not equivalent!');
                   46831:                 }
                   46832: 
                   46833:                 return $this->raiseError("Cannot package, errors in package");
                   46834:             }
                   46835: 
                   46836:             foreach ($other->getValidationWarnings() as $warning) {
                   46837:                 $this->log(1, 'Warning: ' . $warning['message']);
                   46838:             }
                   46839: 
                   46840:             $gen = &$main->getDefaultGenerator();
                   46841:             $tgzfile = $gen->toTgz2($this, $other, $compress);
                   46842:             if (PEAR::isError($tgzfile)) {
                   46843:                 return $tgzfile;
                   46844:             }
                   46845: 
                   46846:             $dest_package = basename($tgzfile);
                   46847:             $pkgdir       = dirname($pkgfile);
                   46848: 
                   46849:             // TAR the Package -------------------------------------------
                   46850:             $this->log(1, "Package $dest_package done");
                   46851:             if (file_exists("$pkgdir/CVS/Root")) {
                   46852:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                   46853:                 $cvstag = "RELEASE_$cvsversion";
                   46854:                 $this->log(1, 'Tag the released code with "pear cvstag ' .
                   46855:                     $main->getPackageFile() . '"');
                   46856:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
                   46857:             } elseif (file_exists("$pkgdir/.svn")) {
                   46858:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                   46859:                 $svntag = $pf->getName() . "-$svnversion";
                   46860:                 $this->log(1, 'Tag the released code with "pear svntag ' .
                   46861:                     $main->getPackageFile() . '"');
                   46862:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
                   46863:             }
                   46864:         } else { // this branch is executed for single packagefile packaging
                   46865:             $gen = &$pf->getDefaultGenerator();
                   46866:             $tgzfile = $gen->toTgz($this, $compress);
                   46867:             if (PEAR::isError($tgzfile)) {
                   46868:                 $this->log(0, $tgzfile->getMessage());
                   46869:                 return $this->raiseError("Cannot package, errors in package");
                   46870:             }
                   46871: 
                   46872:             $dest_package = basename($tgzfile);
                   46873:             $pkgdir       = dirname($pkgfile);
                   46874: 
                   46875:             // TAR the Package -------------------------------------------
                   46876:             $this->log(1, "Package $dest_package done");
                   46877:             if (file_exists("$pkgdir/CVS/Root")) {
                   46878:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                   46879:                 $cvstag = "RELEASE_$cvsversion";
                   46880:                 $this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
                   46881:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
                   46882:             } elseif (file_exists("$pkgdir/.svn")) {
                   46883:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                   46884:                 $svntag = $pf->getName() . "-$svnversion";
                   46885:                 $this->log(1, "Tag the released code with `pear svntag $pkgfile'");
                   46886:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
                   46887:             }
                   46888:         }
                   46889: 
                   46890:         return $dest_package;
                   46891:     }
                   46892: }PEAR-1.9.4/PEAR/Registry.php0000644000076500000240000022412411605156760014313 0ustar  helgistaff<?php
                   46893: /**
                   46894:  * PEAR_Registry
                   46895:  *
                   46896:  * PHP versions 4 and 5
                   46897:  *
                   46898:  * @category   pear
                   46899:  * @package    PEAR
                   46900:  * @author     Stig Bakken <ssb@php.net>
                   46901:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   46902:  * @author     Greg Beaver <cellog@php.net>
                   46903:  * @copyright  1997-2009 The Authors
                   46904:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46905:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
                   46906:  * @link       http://pear.php.net/package/PEAR
                   46907:  * @since      File available since Release 0.1
                   46908:  */
                   46909: 
                   46910: /**
                   46911:  * for PEAR_Error
                   46912:  */
                   46913: require_once 'PEAR.php';
                   46914: require_once 'PEAR/DependencyDB.php';
                   46915: 
                   46916: define('PEAR_REGISTRY_ERROR_LOCK',         -2);
                   46917: define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
                   46918: define('PEAR_REGISTRY_ERROR_FILE',         -4);
                   46919: define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
                   46920: define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
                   46921: 
                   46922: /**
                   46923:  * Administration class used to maintain the installed package database.
                   46924:  * @category   pear
                   46925:  * @package    PEAR
                   46926:  * @author     Stig Bakken <ssb@php.net>
                   46927:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   46928:  * @author     Greg Beaver <cellog@php.net>
                   46929:  * @copyright  1997-2009 The Authors
                   46930:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46931:  * @version    Release: 1.9.4
                   46932:  * @link       http://pear.php.net/package/PEAR
                   46933:  * @since      Class available since Release 1.4.0a1
                   46934:  */
                   46935: class PEAR_Registry extends PEAR
                   46936: {
                   46937:     /**
                   46938:      * File containing all channel information.
                   46939:      * @var string
                   46940:      */
                   46941:     var $channels = '';
                   46942: 
                   46943:     /** Directory where registry files are stored.
                   46944:      * @var string
                   46945:      */
                   46946:     var $statedir = '';
                   46947: 
                   46948:     /** File where the file map is stored
                   46949:      * @var string
                   46950:      */
                   46951:     var $filemap = '';
                   46952: 
                   46953:     /** Directory where registry files for channels are stored.
                   46954:      * @var string
                   46955:      */
                   46956:     var $channelsdir = '';
                   46957: 
                   46958:     /** Name of file used for locking the registry
                   46959:      * @var string
                   46960:      */
                   46961:     var $lockfile = '';
                   46962: 
                   46963:     /** File descriptor used during locking
                   46964:      * @var resource
                   46965:      */
                   46966:     var $lock_fp = null;
                   46967: 
                   46968:     /** Mode used during locking
                   46969:      * @var int
                   46970:      */
                   46971:     var $lock_mode = 0; // XXX UNUSED
                   46972: 
                   46973:     /** Cache of package information.  Structure:
                   46974:      * array(
                   46975:      *   'package' => array('id' => ... ),
                   46976:      *   ... )
                   46977:      * @var array
                   46978:      */
                   46979:     var $pkginfo_cache = array();
                   46980: 
                   46981:     /** Cache of file map.  Structure:
                   46982:      * array( '/path/to/file' => 'package', ... )
                   46983:      * @var array
                   46984:      */
                   46985:     var $filemap_cache = array();
                   46986: 
                   46987:     /**
                   46988:      * @var false|PEAR_ChannelFile
                   46989:      */
                   46990:     var $_pearChannel;
                   46991: 
                   46992:     /**
                   46993:      * @var false|PEAR_ChannelFile
                   46994:      */
                   46995:     var $_peclChannel;
                   46996: 
                   46997:     /**
                   46998:      * @var false|PEAR_ChannelFile
                   46999:      */
                   47000:     var $_docChannel;
                   47001: 
                   47002:     /**
                   47003:      * @var PEAR_DependencyDB
                   47004:      */
                   47005:     var $_dependencyDB;
                   47006: 
                   47007:     /**
                   47008:      * @var PEAR_Config
                   47009:      */
                   47010:     var $_config;
                   47011: 
                   47012:     /**
                   47013:      * PEAR_Registry constructor.
                   47014:      *
                   47015:      * @param string (optional) PEAR install directory (for .php files)
                   47016:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
                   47017:      *        default values are not desired.  Only used the very first time a PEAR
                   47018:      *        repository is initialized
                   47019:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
                   47020:      *        default values are not desired.  Only used the very first time a PEAR
                   47021:      *        repository is initialized
                   47022:      *
                   47023:      * @access public
                   47024:      */
                   47025:     function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
                   47026:                            $pecl_channel = false)
                   47027:     {
                   47028:         parent::PEAR();
                   47029:         $this->setInstallDir($pear_install_dir);
                   47030:         $this->_pearChannel = $pear_channel;
                   47031:         $this->_peclChannel = $pecl_channel;
                   47032:         $this->_config      = false;
                   47033:     }
                   47034: 
                   47035:     function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR)
                   47036:     {
                   47037:         $ds = DIRECTORY_SEPARATOR;
                   47038:         $this->install_dir = $pear_install_dir;
                   47039:         $this->channelsdir = $pear_install_dir.$ds.'.channels';
                   47040:         $this->statedir    = $pear_install_dir.$ds.'.registry';
                   47041:         $this->filemap     = $pear_install_dir.$ds.'.filemap';
                   47042:         $this->lockfile    = $pear_install_dir.$ds.'.lock';
                   47043:     }
                   47044: 
                   47045:     function hasWriteAccess()
                   47046:     {
                   47047:         if (!file_exists($this->install_dir)) {
                   47048:             $dir = $this->install_dir;
                   47049:             while ($dir && $dir != '.') {
                   47050:                 $olddir = $dir;
                   47051:                 $dir    = dirname($dir);
                   47052:                 if ($dir != '.' && file_exists($dir)) {
                   47053:                     if (is_writeable($dir)) {
                   47054:                         return true;
                   47055:                     }
                   47056: 
                   47057:                     return false;
                   47058:                 }
                   47059: 
                   47060:                 if ($dir == $olddir) { // this can happen in safe mode
                   47061:                     return @is_writable($dir);
                   47062:                 }
                   47063:             }
                   47064: 
                   47065:             return false;
                   47066:         }
                   47067: 
                   47068:         return is_writeable($this->install_dir);
                   47069:     }
                   47070: 
                   47071:     function setConfig(&$config, $resetInstallDir = true)
                   47072:     {
                   47073:         $this->_config = &$config;
                   47074:         if ($resetInstallDir) {
                   47075:             $this->setInstallDir($config->get('php_dir'));
                   47076:         }
                   47077:     }
                   47078: 
                   47079:     function _initializeChannelDirs()
                   47080:     {
                   47081:         static $running = false;
                   47082:         if (!$running) {
                   47083:             $running = true;
                   47084:             $ds = DIRECTORY_SEPARATOR;
                   47085:             if (!is_dir($this->channelsdir) ||
                   47086:                   !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   47087:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   47088:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   47089:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47090:                 if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47091:                     $pear_channel = $this->_pearChannel;
                   47092:                     if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
                   47093:                         if (!class_exists('PEAR_ChannelFile')) {
                   47094:                             require_once 'PEAR/ChannelFile.php';
                   47095:                         }
                   47096: 
                   47097:                         $pear_channel = new PEAR_ChannelFile;
                   47098:                         $pear_channel->setAlias('pear');
                   47099:                         $pear_channel->setServer('pear.php.net');
                   47100:                         $pear_channel->setSummary('PHP Extension and Application Repository');
                   47101:                         $pear_channel->setDefaultPEARProtocols();
                   47102:                         $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   47103:                         $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   47104:                         $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   47105:                         //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
                   47106:                     } else {
                   47107:                         $pear_channel->setServer('pear.php.net');
                   47108:                         $pear_channel->setAlias('pear');
                   47109:                     }
                   47110: 
                   47111:                     $pear_channel->validate();
                   47112:                     $this->_addChannel($pear_channel);
                   47113:                 }
                   47114: 
                   47115:                 if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
                   47116:                     $pecl_channel = $this->_peclChannel;
                   47117:                     if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
                   47118:                         if (!class_exists('PEAR_ChannelFile')) {
                   47119:                             require_once 'PEAR/ChannelFile.php';
                   47120:                         }
                   47121: 
                   47122:                         $pecl_channel = new PEAR_ChannelFile;
                   47123:                         $pecl_channel->setAlias('pecl');
                   47124:                         $pecl_channel->setServer('pecl.php.net');
                   47125:                         $pecl_channel->setSummary('PHP Extension Community Library');
                   47126:                         $pecl_channel->setDefaultPEARProtocols();
                   47127:                         $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   47128:                         $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   47129:                         $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   47130:                     } else {
                   47131:                         $pecl_channel->setServer('pecl.php.net');
                   47132:                         $pecl_channel->setAlias('pecl');
                   47133:                     }
                   47134: 
                   47135:                     $pecl_channel->validate();
                   47136:                     $this->_addChannel($pecl_channel);
                   47137:                 }
                   47138: 
                   47139:                 if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
                   47140:                     $doc_channel = $this->_docChannel;
                   47141:                     if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
                   47142:                         if (!class_exists('PEAR_ChannelFile')) {
                   47143:                             require_once 'PEAR/ChannelFile.php';
                   47144:                         }
                   47145: 
                   47146:                         $doc_channel = new PEAR_ChannelFile;
                   47147:                         $doc_channel->setAlias('phpdocs');
                   47148:                         $doc_channel->setServer('doc.php.net');
                   47149:                         $doc_channel->setSummary('PHP Documentation Team');
                   47150:                         $doc_channel->setDefaultPEARProtocols();
                   47151:                         $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   47152:                         $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   47153:                         $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   47154:                     } else {
                   47155:                         $doc_channel->setServer('doc.php.net');
                   47156:                         $doc_channel->setAlias('doc');
                   47157:                     }
                   47158: 
                   47159:                     $doc_channel->validate();
                   47160:                     $this->_addChannel($doc_channel);
                   47161:                 }
                   47162: 
                   47163:                 if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47164:                     if (!class_exists('PEAR_ChannelFile')) {
                   47165:                         require_once 'PEAR/ChannelFile.php';
                   47166:                     }
                   47167: 
                   47168:                     $private = new PEAR_ChannelFile;
                   47169:                     $private->setName('__uri');
                   47170:                     $private->setDefaultPEARProtocols();
                   47171:                     $private->setBaseURL('REST1.0', '****');
                   47172:                     $private->setSummary('Pseudo-channel for static packages');
                   47173:                     $this->_addChannel($private);
                   47174:                 }
                   47175:                 $this->_rebuildFileMap();
                   47176:             }
                   47177: 
                   47178:             $running = false;
                   47179:         }
                   47180:     }
                   47181: 
                   47182:     function _initializeDirs()
                   47183:     {
                   47184:         $ds = DIRECTORY_SEPARATOR;
                   47185:         // XXX Compatibility code should be removed in the future
                   47186:         // rename all registry files if any to lowercase
                   47187:         if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
                   47188:               $handle = opendir($this->statedir)) {
                   47189:             $dest = $this->statedir . $ds;
                   47190:             while (false !== ($file = readdir($handle))) {
                   47191:                 if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
                   47192:                     rename($dest . $file, $dest . strtolower($file));
                   47193:                 }
                   47194:             }
                   47195:             closedir($handle);
                   47196:         }
                   47197: 
                   47198:         $this->_initializeChannelDirs();
                   47199:         if (!file_exists($this->filemap)) {
                   47200:             $this->_rebuildFileMap();
                   47201:         }
                   47202:         $this->_initializeDepDB();
                   47203:     }
                   47204: 
                   47205:     function _initializeDepDB()
                   47206:     {
                   47207:         if (!isset($this->_dependencyDB)) {
                   47208:             static $initializing = false;
                   47209:             if (!$initializing) {
                   47210:                 $initializing = true;
                   47211:                 if (!$this->_config) { // never used?
                   47212:                     $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
                   47213:                     $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
                   47214:                         $file);
                   47215:                     $this->_config->setRegistry($this);
                   47216:                     $this->_config->set('php_dir', $this->install_dir);
                   47217:                 }
                   47218: 
                   47219:                 $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   47220:                 if (PEAR::isError($this->_dependencyDB)) {
                   47221:                     // attempt to recover by removing the dep db
                   47222:                     if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
                   47223:                         DIRECTORY_SEPARATOR . '.depdb')) {
                   47224:                         @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
                   47225:                             DIRECTORY_SEPARATOR . '.depdb');
                   47226:                     }
                   47227: 
                   47228:                     $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   47229:                     if (PEAR::isError($this->_dependencyDB)) {
                   47230:                         echo $this->_dependencyDB->getMessage();
                   47231:                         echo 'Unrecoverable error';
                   47232:                         exit(1);
                   47233:                     }
                   47234:                 }
                   47235: 
                   47236:                 $initializing = false;
                   47237:             }
                   47238:         }
                   47239:     }
                   47240: 
                   47241:     /**
                   47242:      * PEAR_Registry destructor.  Makes sure no locks are forgotten.
                   47243:      *
                   47244:      * @access private
                   47245:      */
                   47246:     function _PEAR_Registry()
                   47247:     {
                   47248:         parent::_PEAR();
                   47249:         if (is_resource($this->lock_fp)) {
                   47250:             $this->_unlock();
                   47251:         }
                   47252:     }
                   47253: 
                   47254:     /**
                   47255:      * Make sure the directory where we keep registry files exists.
                   47256:      *
                   47257:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47258:      * created
                   47259:      *
                   47260:      * @access private
                   47261:      */
                   47262:     function _assertStateDir($channel = false)
                   47263:     {
                   47264:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   47265:             return $this->_assertChannelStateDir($channel);
                   47266:         }
                   47267: 
                   47268:         static $init = false;
                   47269:         if (!file_exists($this->statedir)) {
                   47270:             if (!$this->hasWriteAccess()) {
                   47271:                 return false;
                   47272:             }
                   47273: 
                   47274:             require_once 'System.php';
                   47275:             if (!System::mkdir(array('-p', $this->statedir))) {
                   47276:                 return $this->raiseError("could not create directory '{$this->statedir}'");
                   47277:             }
                   47278:             $init = true;
                   47279:         } elseif (!is_dir($this->statedir)) {
                   47280:             return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
                   47281:                 'it already exists and is not a directory');
                   47282:         }
                   47283: 
                   47284:         $ds = DIRECTORY_SEPARATOR;
                   47285:         if (!file_exists($this->channelsdir)) {
                   47286:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   47287:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   47288:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   47289:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47290:                 $init = true;
                   47291:             }
                   47292:         } elseif (!is_dir($this->channelsdir)) {
                   47293:             return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
                   47294:                 'it already exists and is not a directory');
                   47295:         }
                   47296: 
                   47297:         if ($init) {
                   47298:             static $running = false;
                   47299:             if (!$running) {
                   47300:                 $running = true;
                   47301:                 $this->_initializeDirs();
                   47302:                 $running = false;
                   47303:                 $init = false;
                   47304:             }
                   47305:         } else {
                   47306:             $this->_initializeDepDB();
                   47307:         }
                   47308: 
                   47309:         return true;
                   47310:     }
                   47311: 
                   47312:     /**
                   47313:      * Make sure the directory where we keep registry files exists for a non-standard channel.
                   47314:      *
                   47315:      * @param string channel name
                   47316:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47317:      * created
                   47318:      *
                   47319:      * @access private
                   47320:      */
                   47321:     function _assertChannelStateDir($channel)
                   47322:     {
                   47323:         $ds = DIRECTORY_SEPARATOR;
                   47324:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   47325:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47326:                 $this->_initializeChannelDirs();
                   47327:             }
                   47328:             return $this->_assertStateDir($channel);
                   47329:         }
                   47330: 
                   47331:         $channelDir = $this->_channelDirectoryName($channel);
                   47332:         if (!is_dir($this->channelsdir) ||
                   47333:               !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47334:             $this->_initializeChannelDirs();
                   47335:         }
                   47336: 
                   47337:         if (!file_exists($channelDir)) {
                   47338:             if (!$this->hasWriteAccess()) {
                   47339:                 return false;
                   47340:             }
                   47341: 
                   47342:             require_once 'System.php';
                   47343:             if (!System::mkdir(array('-p', $channelDir))) {
                   47344:                 return $this->raiseError("could not create directory '" . $channelDir .
                   47345:                     "'");
                   47346:             }
                   47347:         } elseif (!is_dir($channelDir)) {
                   47348:             return $this->raiseError("could not create directory '" . $channelDir .
                   47349:                 "', already exists and is not a directory");
                   47350:         }
                   47351: 
                   47352:         return true;
                   47353:     }
                   47354: 
                   47355:     /**
                   47356:      * Make sure the directory where we keep registry files for channels exists
                   47357:      *
                   47358:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47359:      * created
                   47360:      *
                   47361:      * @access private
                   47362:      */
                   47363:     function _assertChannelDir()
                   47364:     {
                   47365:         if (!file_exists($this->channelsdir)) {
                   47366:             if (!$this->hasWriteAccess()) {
                   47367:                 return false;
                   47368:             }
                   47369: 
                   47370:             require_once 'System.php';
                   47371:             if (!System::mkdir(array('-p', $this->channelsdir))) {
                   47372:                 return $this->raiseError("could not create directory '{$this->channelsdir}'");
                   47373:             }
                   47374:         } elseif (!is_dir($this->channelsdir)) {
                   47375:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   47376:                 "', it already exists and is not a directory");
                   47377:         }
                   47378: 
                   47379:         if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   47380:             if (!$this->hasWriteAccess()) {
                   47381:                 return false;
                   47382:             }
                   47383: 
                   47384:             require_once 'System.php';
                   47385:             if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
                   47386:                 return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
                   47387:             }
                   47388:         } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   47389:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   47390:                 "/.alias', it already exists and is not a directory");
                   47391:         }
                   47392: 
                   47393:         return true;
                   47394:     }
                   47395: 
                   47396:     /**
                   47397:      * Get the name of the file where data for a given package is stored.
                   47398:      *
                   47399:      * @param string channel name, or false if this is a PEAR package
                   47400:      * @param string package name
                   47401:      *
                   47402:      * @return string registry file name
                   47403:      *
                   47404:      * @access public
                   47405:      */
                   47406:     function _packageFileName($package, $channel = false)
                   47407:     {
                   47408:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   47409:             return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
                   47410:                 strtolower($package) . '.reg';
                   47411:         }
                   47412: 
                   47413:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
                   47414:     }
                   47415: 
                   47416:     /**
                   47417:      * Get the name of the file where data for a given channel is stored.
                   47418:      * @param string channel name
                   47419:      * @return string registry file name
                   47420:      */
                   47421:     function _channelFileName($channel, $noaliases = false)
                   47422:     {
                   47423:         if (!$noaliases) {
                   47424:             if (file_exists($this->_getChannelAliasFileName($channel))) {
                   47425:                 $channel = implode('', file($this->_getChannelAliasFileName($channel)));
                   47426:             }
                   47427:         }
                   47428:         return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
                   47429:             strtolower($channel)) . '.reg';
                   47430:     }
                   47431: 
                   47432:     /**
                   47433:      * @param string
                   47434:      * @return string
                   47435:      */
                   47436:     function _getChannelAliasFileName($alias)
                   47437:     {
                   47438:         return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
                   47439:               DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
                   47440:     }
                   47441: 
                   47442:     /**
                   47443:      * Get the name of a channel from its alias
                   47444:      */
                   47445:     function _getChannelFromAlias($channel)
                   47446:     {
                   47447:         if (!$this->_channelExists($channel)) {
                   47448:             if ($channel == 'pear.php.net') {
                   47449:                 return 'pear.php.net';
                   47450:             }
                   47451: 
                   47452:             if ($channel == 'pecl.php.net') {
                   47453:                 return 'pecl.php.net';
                   47454:             }
                   47455: 
                   47456:             if ($channel == 'doc.php.net') {
                   47457:                 return 'doc.php.net';
                   47458:             }
                   47459: 
                   47460:             if ($channel == '__uri') {
                   47461:                 return '__uri';
                   47462:             }
                   47463: 
                   47464:             return false;
                   47465:         }
                   47466: 
                   47467:         $channel = strtolower($channel);
                   47468:         if (file_exists($this->_getChannelAliasFileName($channel))) {
                   47469:             // translate an alias to an actual channel
                   47470:             return implode('', file($this->_getChannelAliasFileName($channel)));
                   47471:         }
                   47472: 
                   47473:         return $channel;
                   47474:     }
                   47475: 
                   47476:     /**
                   47477:      * Get the alias of a channel from its alias or its name
                   47478:      */
                   47479:     function _getAlias($channel)
                   47480:     {
                   47481:         if (!$this->_channelExists($channel)) {
                   47482:             if ($channel == 'pear.php.net') {
                   47483:                 return 'pear';
                   47484:             }
                   47485: 
                   47486:             if ($channel == 'pecl.php.net') {
                   47487:                 return 'pecl';
                   47488:             }
                   47489: 
                   47490:             if ($channel == 'doc.php.net') {
                   47491:                 return 'phpdocs';
                   47492:             }
                   47493: 
                   47494:             return false;
                   47495:         }
                   47496: 
                   47497:         $channel = $this->_getChannel($channel);
                   47498:         if (PEAR::isError($channel)) {
                   47499:             return $channel;
                   47500:         }
                   47501: 
                   47502:         return $channel->getAlias();
                   47503:     }
                   47504: 
                   47505:     /**
                   47506:      * Get the name of the file where data for a given package is stored.
                   47507:      *
                   47508:      * @param string channel name, or false if this is a PEAR package
                   47509:      * @param string package name
                   47510:      *
                   47511:      * @return string registry file name
                   47512:      *
                   47513:      * @access public
                   47514:      */
                   47515:     function _channelDirectoryName($channel)
                   47516:     {
                   47517:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   47518:             return $this->statedir;
                   47519:         }
                   47520: 
                   47521:         $ch = $this->_getChannelFromAlias($channel);
                   47522:         if (!$ch) {
                   47523:             $ch = $channel;
                   47524:         }
                   47525: 
                   47526:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
                   47527:             str_replace('/', '_', $ch));
                   47528:     }
                   47529: 
                   47530:     function _openPackageFile($package, $mode, $channel = false)
                   47531:     {
                   47532:         if (!$this->_assertStateDir($channel)) {
                   47533:             return null;
                   47534:         }
                   47535: 
                   47536:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   47537:             return null;
                   47538:         }
                   47539: 
                   47540:         $file = $this->_packageFileName($package, $channel);
                   47541:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   47542:             return null;
                   47543:         }
                   47544: 
                   47545:         $fp = @fopen($file, $mode);
                   47546:         if (!$fp) {
                   47547:             return null;
                   47548:         }
                   47549: 
                   47550:         return $fp;
                   47551:     }
                   47552: 
                   47553:     function _closePackageFile($fp)
                   47554:     {
                   47555:         fclose($fp);
                   47556:     }
                   47557: 
                   47558:     function _openChannelFile($channel, $mode)
                   47559:     {
                   47560:         if (!$this->_assertChannelDir()) {
                   47561:             return null;
                   47562:         }
                   47563: 
                   47564:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   47565:             return null;
                   47566:         }
                   47567: 
                   47568:         $file = $this->_channelFileName($channel);
                   47569:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   47570:             return null;
                   47571:         }
                   47572: 
                   47573:         $fp = @fopen($file, $mode);
                   47574:         if (!$fp) {
                   47575:             return null;
                   47576:         }
                   47577: 
                   47578:         return $fp;
                   47579:     }
                   47580: 
                   47581:     function _closeChannelFile($fp)
                   47582:     {
                   47583:         fclose($fp);
                   47584:     }
                   47585: 
                   47586:     function _rebuildFileMap()
                   47587:     {
                   47588:         if (!class_exists('PEAR_Installer_Role')) {
                   47589:             require_once 'PEAR/Installer/Role.php';
                   47590:         }
                   47591: 
                   47592:         $channels = $this->_listAllPackages();
                   47593:         $files = array();
                   47594:         foreach ($channels as $channel => $packages) {
                   47595:             foreach ($packages as $package) {
                   47596:                 $version = $this->_packageInfo($package, 'version', $channel);
                   47597:                 $filelist = $this->_packageInfo($package, 'filelist', $channel);
                   47598:                 if (!is_array($filelist)) {
                   47599:                     continue;
                   47600:                 }
                   47601: 
                   47602:                 foreach ($filelist as $name => $attrs) {
                   47603:                     if (isset($attrs['attribs'])) {
                   47604:                         $attrs = $attrs['attribs'];
                   47605:                     }
                   47606: 
                   47607:                     // it is possible for conflicting packages in different channels to
                   47608:                     // conflict with data files/doc files
                   47609:                     if ($name == 'dirtree') {
                   47610:                         continue;
                   47611:                     }
                   47612: 
                   47613:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   47614:                           PEAR_Installer_Role::getInstallableRoles())) {
                   47615:                         // these are not installed
                   47616:                         continue;
                   47617:                     }
                   47618: 
                   47619:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   47620:                           PEAR_Installer_Role::getBaseinstallRoles())) {
                   47621:                         $attrs['baseinstalldir'] = $package;
                   47622:                     }
                   47623: 
                   47624:                     if (isset($attrs['baseinstalldir'])) {
                   47625:                         $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
                   47626:                     } else {
                   47627:                         $file = $name;
                   47628:                     }
                   47629: 
                   47630:                     $file = preg_replace(',^/+,', '', $file);
                   47631:                     if ($channel != 'pear.php.net') {
                   47632:                         if (!isset($files[$attrs['role']])) {
                   47633:                             $files[$attrs['role']] = array();
                   47634:                         }
                   47635:                         $files[$attrs['role']][$file] = array(strtolower($channel),
                   47636:                             strtolower($package));
                   47637:                     } else {
                   47638:                         if (!isset($files[$attrs['role']])) {
                   47639:                             $files[$attrs['role']] = array();
                   47640:                         }
                   47641:                         $files[$attrs['role']][$file] = strtolower($package);
                   47642:                     }
                   47643:                 }
                   47644:             }
                   47645:         }
                   47646: 
                   47647: 
                   47648:         $this->_assertStateDir();
                   47649:         if (!$this->hasWriteAccess()) {
                   47650:             return false;
                   47651:         }
                   47652: 
                   47653:         $fp = @fopen($this->filemap, 'wb');
                   47654:         if (!$fp) {
                   47655:             return false;
                   47656:         }
                   47657: 
                   47658:         $this->filemap_cache = $files;
                   47659:         fwrite($fp, serialize($files));
                   47660:         fclose($fp);
                   47661:         return true;
                   47662:     }
                   47663: 
                   47664:     function _readFileMap()
                   47665:     {
                   47666:         if (!file_exists($this->filemap)) {
                   47667:             return array();
                   47668:         }
                   47669: 
                   47670:         $fp = @fopen($this->filemap, 'r');
                   47671:         if (!$fp) {
                   47672:             return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
                   47673:         }
                   47674: 
                   47675:         clearstatcache();
                   47676:         $rt = get_magic_quotes_runtime();
                   47677:         set_magic_quotes_runtime(0);
                   47678:         $fsize = filesize($this->filemap);
                   47679:         fclose($fp);
                   47680:         $data = file_get_contents($this->filemap);
                   47681:         set_magic_quotes_runtime($rt);
                   47682:         $tmp = unserialize($data);
                   47683:         if (!$tmp && $fsize > 7) {
                   47684:             return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
                   47685:         }
                   47686: 
                   47687:         $this->filemap_cache = $tmp;
                   47688:         return true;
                   47689:     }
                   47690: 
                   47691:     /**
                   47692:      * Lock the registry.
                   47693:      *
                   47694:      * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
                   47695:      *                See flock manual for more information.
                   47696:      *
                   47697:      * @return bool TRUE on success, FALSE if locking failed, or a
                   47698:      *              PEAR error if some other error occurs (such as the
                   47699:      *              lock file not being writable).
                   47700:      *
                   47701:      * @access private
                   47702:      */
                   47703:     function _lock($mode = LOCK_EX)
                   47704:     {
                   47705:         if (stristr(php_uname(), 'Windows 9')) {
                   47706:             return true;
                   47707:         }
                   47708: 
                   47709:         if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
                   47710:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   47711:             return true;
                   47712:         }
                   47713: 
                   47714:         if (!$this->_assertStateDir()) {
                   47715:             if ($mode == LOCK_EX) {
                   47716:                 return $this->raiseError('Registry directory is not writeable by the current user');
                   47717:             }
                   47718: 
                   47719:             return true;
                   47720:         }
                   47721: 
                   47722:         $open_mode = 'w';
                   47723:         // XXX People reported problems with LOCK_SH and 'w'
                   47724:         if ($mode === LOCK_SH || $mode === LOCK_UN) {
                   47725:             if (!file_exists($this->lockfile)) {
                   47726:                 touch($this->lockfile);
                   47727:             }
                   47728:             $open_mode = 'r';
                   47729:         }
                   47730: 
                   47731:         if (!is_resource($this->lock_fp)) {
                   47732:             $this->lock_fp = @fopen($this->lockfile, $open_mode);
                   47733:         }
                   47734: 
                   47735:         if (!is_resource($this->lock_fp)) {
                   47736:             $this->lock_fp = null;
                   47737:             return $this->raiseError("could not create lock file" .
                   47738:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   47739:         }
                   47740: 
                   47741:         if (!(int)flock($this->lock_fp, $mode)) {
                   47742:             switch ($mode) {
                   47743:                 case LOCK_SH: $str = 'shared';    break;
                   47744:                 case LOCK_EX: $str = 'exclusive'; break;
                   47745:                 case LOCK_UN: $str = 'unlock';    break;
                   47746:                 default:      $str = 'unknown';   break;
                   47747:             }
                   47748: 
                   47749:             //is resource at this point, close it on error.
                   47750:             fclose($this->lock_fp);
                   47751:             $this->lock_fp = null;
                   47752:             return $this->raiseError("could not acquire $str lock ($this->lockfile)",
                   47753:                                      PEAR_REGISTRY_ERROR_LOCK);
                   47754:         }
                   47755: 
                   47756:         return true;
                   47757:     }
                   47758: 
                   47759:     function _unlock()
                   47760:     {
                   47761:         $ret = $this->_lock(LOCK_UN);
                   47762:         if (is_resource($this->lock_fp)) {
                   47763:             fclose($this->lock_fp);
                   47764:         }
                   47765: 
                   47766:         $this->lock_fp = null;
                   47767:         return $ret;
                   47768:     }
                   47769: 
                   47770:     function _packageExists($package, $channel = false)
                   47771:     {
                   47772:         return file_exists($this->_packageFileName($package, $channel));
                   47773:     }
                   47774: 
                   47775:     /**
                   47776:      * Determine whether a channel exists in the registry
                   47777:      *
                   47778:      * @param string Channel name
                   47779:      * @param bool if true, then aliases will be ignored
                   47780:      * @return boolean
                   47781:      */
                   47782:     function _channelExists($channel, $noaliases = false)
                   47783:     {
                   47784:         $a = file_exists($this->_channelFileName($channel, $noaliases));
                   47785:         if (!$a && $channel == 'pear.php.net') {
                   47786:             return true;
                   47787:         }
                   47788: 
                   47789:         if (!$a && $channel == 'pecl.php.net') {
                   47790:             return true;
                   47791:         }
                   47792: 
                   47793:         if (!$a && $channel == 'doc.php.net') {
                   47794:             return true;
                   47795:         }
                   47796: 
                   47797:         return $a;
                   47798:     }
                   47799: 
                   47800:     /**
                   47801:      * Determine whether a mirror exists within the deafult channel in the registry
                   47802:      *
                   47803:      * @param string Channel name
                   47804:      * @param string Mirror name
                   47805:      *
                   47806:      * @return boolean
                   47807:      */
                   47808:     function _mirrorExists($channel, $mirror)
                   47809:     {
                   47810:         $data = $this->_channelInfo($channel);
                   47811:         if (!isset($data['servers']['mirror'])) {
                   47812:             return false;
                   47813:         }
                   47814: 
                   47815:         foreach ($data['servers']['mirror'] as $m) {
                   47816:             if ($m['attribs']['host'] == $mirror) {
                   47817:                 return true;
                   47818:             }
                   47819:         }
                   47820: 
                   47821:         return false;
                   47822:     }
                   47823: 
                   47824:     /**
                   47825:      * @param PEAR_ChannelFile Channel object
                   47826:      * @param donotuse
                   47827:      * @param string Last-Modified HTTP tag from remote request
                   47828:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   47829:      */
                   47830:     function _addChannel($channel, $update = false, $lastmodified = false)
                   47831:     {
                   47832:         if (!is_a($channel, 'PEAR_ChannelFile')) {
                   47833:             return false;
                   47834:         }
                   47835: 
                   47836:         if (!$channel->validate()) {
                   47837:             return false;
                   47838:         }
                   47839: 
                   47840:         if (file_exists($this->_channelFileName($channel->getName()))) {
                   47841:             if (!$update) {
                   47842:                 return false;
                   47843:             }
                   47844: 
                   47845:             $checker = $this->_getChannel($channel->getName());
                   47846:             if (PEAR::isError($checker)) {
                   47847:                 return $checker;
                   47848:             }
                   47849: 
                   47850:             if ($channel->getAlias() != $checker->getAlias()) {
                   47851:                 if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
                   47852:                     @unlink($this->_getChannelAliasFileName($checker->getAlias()));
                   47853:                 }
                   47854:             }
                   47855:         } else {
                   47856:             if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
                   47857:                 return false;
                   47858:             }
                   47859:         }
                   47860: 
                   47861:         $ret = $this->_assertChannelDir();
                   47862:         if (PEAR::isError($ret)) {
                   47863:             return $ret;
                   47864:         }
                   47865: 
                   47866:         $ret = $this->_assertChannelStateDir($channel->getName());
                   47867:         if (PEAR::isError($ret)) {
                   47868:             return $ret;
                   47869:         }
                   47870: 
                   47871:         if ($channel->getAlias() != $channel->getName()) {
                   47872:             if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
                   47873:                   $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
                   47874:                 $channel->setAlias($channel->getName());
                   47875:             }
                   47876: 
                   47877:             if (!$this->hasWriteAccess()) {
                   47878:                 return false;
                   47879:             }
                   47880: 
                   47881:             $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
                   47882:             if (!$fp) {
                   47883:                 return false;
                   47884:             }
                   47885: 
                   47886:             fwrite($fp, $channel->getName());
                   47887:             fclose($fp);
                   47888:         }
                   47889: 
                   47890:         if (!$this->hasWriteAccess()) {
                   47891:             return false;
                   47892:         }
                   47893: 
                   47894:         $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
                   47895:         if (!$fp) {
                   47896:             return false;
                   47897:         }
                   47898: 
                   47899:         $info = $channel->toArray();
                   47900:         if ($lastmodified) {
                   47901:             $info['_lastmodified'] = $lastmodified;
                   47902:         } else {
                   47903:             $info['_lastmodified'] = date('r');
                   47904:         }
                   47905: 
                   47906:         fwrite($fp, serialize($info));
                   47907:         fclose($fp);
                   47908:         return true;
                   47909:     }
                   47910: 
                   47911:     /**
                   47912:      * Deletion fails if there are any packages installed from the channel
                   47913:      * @param string|PEAR_ChannelFile channel name
                   47914:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   47915:      */
                   47916:     function _deleteChannel($channel)
                   47917:     {
                   47918:         if (!is_string($channel)) {
                   47919:             if (!is_a($channel, 'PEAR_ChannelFile')) {
                   47920:                 return false;
                   47921:             }
                   47922: 
                   47923:             if (!$channel->validate()) {
                   47924:                 return false;
                   47925:             }
                   47926:             $channel = $channel->getName();
                   47927:         }
                   47928: 
                   47929:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   47930:             return false;
                   47931:         }
                   47932: 
                   47933:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   47934:             return false;
                   47935:         }
                   47936: 
                   47937:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   47938:             return false;
                   47939:         }
                   47940: 
                   47941:         if (!$this->_channelExists($channel)) {
                   47942:             return false;
                   47943:         }
                   47944: 
                   47945:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   47946:             return false;
                   47947:         }
                   47948: 
                   47949:         $channel = $this->_getChannelFromAlias($channel);
                   47950:         if ($channel == 'pear.php.net') {
                   47951:             return false;
                   47952:         }
                   47953: 
                   47954:         $test = $this->_listChannelPackages($channel);
                   47955:         if (count($test)) {
                   47956:             return false;
                   47957:         }
                   47958: 
                   47959:         $test = @rmdir($this->_channelDirectoryName($channel));
                   47960:         if (!$test) {
                   47961:             return false;
                   47962:         }
                   47963: 
                   47964:         $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
                   47965:         if (file_exists($file)) {
                   47966:             $test = @unlink($file);
                   47967:             if (!$test) {
                   47968:                 return false;
                   47969:             }
                   47970:         }
                   47971: 
                   47972:         $file = $this->_channelFileName($channel);
                   47973:         $ret = true;
                   47974:         if (file_exists($file)) {
                   47975:             $ret = @unlink($file);
                   47976:         }
                   47977: 
                   47978:         return $ret;
                   47979:     }
                   47980: 
                   47981:     /**
                   47982:      * Determine whether a channel exists in the registry
                   47983:      * @param string Channel Alias
                   47984:      * @return boolean
                   47985:      */
                   47986:     function _isChannelAlias($alias)
                   47987:     {
                   47988:         return file_exists($this->_getChannelAliasFileName($alias));
                   47989:     }
                   47990: 
                   47991:     /**
                   47992:      * @param string|null
                   47993:      * @param string|null
                   47994:      * @param string|null
                   47995:      * @return array|null
                   47996:      * @access private
                   47997:      */
                   47998:     function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   47999:     {
                   48000:         if ($package === null) {
                   48001:             if ($channel === null) {
                   48002:                 $channels = $this->_listChannels();
                   48003:                 $ret = array();
                   48004:                 foreach ($channels as $channel) {
                   48005:                     $channel = strtolower($channel);
                   48006:                     $ret[$channel] = array();
                   48007:                     $packages = $this->_listPackages($channel);
                   48008:                     foreach ($packages as $package) {
                   48009:                         $ret[$channel][] = $this->_packageInfo($package, null, $channel);
                   48010:                     }
                   48011:                 }
                   48012: 
                   48013:                 return $ret;
                   48014:             }
                   48015: 
                   48016:             $ps = $this->_listPackages($channel);
                   48017:             if (!count($ps)) {
                   48018:                 return array();
                   48019:             }
                   48020:             return array_map(array(&$this, '_packageInfo'),
                   48021:                              $ps, array_fill(0, count($ps), null),
                   48022:                              array_fill(0, count($ps), $channel));
                   48023:         }
                   48024: 
                   48025:         $fp = $this->_openPackageFile($package, 'r', $channel);
                   48026:         if ($fp === null) {
                   48027:             return null;
                   48028:         }
                   48029: 
                   48030:         $rt = get_magic_quotes_runtime();
                   48031:         set_magic_quotes_runtime(0);
                   48032:         clearstatcache();
                   48033:         $this->_closePackageFile($fp);
                   48034:         $data = file_get_contents($this->_packageFileName($package, $channel));
                   48035:         set_magic_quotes_runtime($rt);
                   48036:         $data = unserialize($data);
                   48037:         if ($key === null) {
                   48038:             return $data;
                   48039:         }
                   48040: 
                   48041:         // compatibility for package.xml version 2.0
                   48042:         if (isset($data['old'][$key])) {
                   48043:             return $data['old'][$key];
                   48044:         }
                   48045: 
                   48046:         if (isset($data[$key])) {
                   48047:             return $data[$key];
                   48048:         }
                   48049: 
                   48050:         return null;
                   48051:     }
                   48052: 
                   48053:     /**
                   48054:      * @param string Channel name
                   48055:      * @param bool whether to strictly retrieve info of channels, not just aliases
                   48056:      * @return array|null
                   48057:      */
                   48058:     function _channelInfo($channel, $noaliases = false)
                   48059:     {
                   48060:         if (!$this->_channelExists($channel, $noaliases)) {
                   48061:             return null;
                   48062:         }
                   48063: 
                   48064:         $fp = $this->_openChannelFile($channel, 'r');
                   48065:         if ($fp === null) {
                   48066:             return null;
                   48067:         }
                   48068: 
                   48069:         $rt = get_magic_quotes_runtime();
                   48070:         set_magic_quotes_runtime(0);
                   48071:         clearstatcache();
                   48072:         $this->_closeChannelFile($fp);
                   48073:         $data = file_get_contents($this->_channelFileName($channel));
                   48074:         set_magic_quotes_runtime($rt);
                   48075:         $data = unserialize($data);
                   48076:         return $data;
                   48077:     }
                   48078: 
                   48079:     function _listChannels()
                   48080:     {
                   48081:         $channellist = array();
                   48082:         if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
                   48083:             return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
                   48084:         }
                   48085: 
                   48086:         $dp = opendir($this->channelsdir);
                   48087:         while ($ent = readdir($dp)) {
                   48088:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48089:                 continue;
                   48090:             }
                   48091: 
                   48092:             if ($ent == '__uri.reg') {
                   48093:                 $channellist[] = '__uri';
                   48094:                 continue;
                   48095:             }
                   48096: 
                   48097:             $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
                   48098:         }
                   48099: 
                   48100:         closedir($dp);
                   48101:         if (!in_array('pear.php.net', $channellist)) {
                   48102:             $channellist[] = 'pear.php.net';
                   48103:         }
                   48104: 
                   48105:         if (!in_array('pecl.php.net', $channellist)) {
                   48106:             $channellist[] = 'pecl.php.net';
                   48107:         }
                   48108: 
                   48109:         if (!in_array('doc.php.net', $channellist)) {
                   48110:             $channellist[] = 'doc.php.net';
                   48111:         }
                   48112: 
                   48113: 
                   48114:         if (!in_array('__uri', $channellist)) {
                   48115:             $channellist[] = '__uri';
                   48116:         }
                   48117: 
                   48118:         natsort($channellist);
                   48119:         return $channellist;
                   48120:     }
                   48121: 
                   48122:     function _listPackages($channel = false)
                   48123:     {
                   48124:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   48125:             return $this->_listChannelPackages($channel);
                   48126:         }
                   48127: 
                   48128:         if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
                   48129:             return array();
                   48130:         }
                   48131: 
                   48132:         $pkglist = array();
                   48133:         $dp = opendir($this->statedir);
                   48134:         if (!$dp) {
                   48135:             return $pkglist;
                   48136:         }
                   48137: 
                   48138:         while ($ent = readdir($dp)) {
                   48139:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48140:                 continue;
                   48141:             }
                   48142: 
                   48143:             $pkglist[] = substr($ent, 0, -4);
                   48144:         }
                   48145:         closedir($dp);
                   48146:         return $pkglist;
                   48147:     }
                   48148: 
                   48149:     function _listChannelPackages($channel)
                   48150:     {
                   48151:         $pkglist = array();
                   48152:         if (!file_exists($this->_channelDirectoryName($channel)) ||
                   48153:               !is_dir($this->_channelDirectoryName($channel))) {
                   48154:             return array();
                   48155:         }
                   48156: 
                   48157:         $dp = opendir($this->_channelDirectoryName($channel));
                   48158:         if (!$dp) {
                   48159:             return $pkglist;
                   48160:         }
                   48161: 
                   48162:         while ($ent = readdir($dp)) {
                   48163:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48164:                 continue;
                   48165:             }
                   48166:             $pkglist[] = substr($ent, 0, -4);
                   48167:         }
                   48168: 
                   48169:         closedir($dp);
                   48170:         return $pkglist;
                   48171:     }
                   48172: 
                   48173:     function _listAllPackages()
                   48174:     {
                   48175:         $ret = array();
                   48176:         foreach ($this->_listChannels() as $channel) {
                   48177:             $ret[$channel] = $this->_listPackages($channel);
                   48178:         }
                   48179: 
                   48180:         return $ret;
                   48181:     }
                   48182: 
                   48183:     /**
                   48184:      * Add an installed package to the registry
                   48185:      * @param string package name
                   48186:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   48187:      * @return bool success of saving
                   48188:      * @access private
                   48189:      */
                   48190:     function _addPackage($package, $info)
                   48191:     {
                   48192:         if ($this->_packageExists($package)) {
                   48193:             return false;
                   48194:         }
                   48195: 
                   48196:         $fp = $this->_openPackageFile($package, 'wb');
                   48197:         if ($fp === null) {
                   48198:             return false;
                   48199:         }
                   48200: 
                   48201:         $info['_lastmodified'] = time();
                   48202:         fwrite($fp, serialize($info));
                   48203:         $this->_closePackageFile($fp);
                   48204:         if (isset($info['filelist'])) {
                   48205:             $this->_rebuildFileMap();
                   48206:         }
                   48207: 
                   48208:         return true;
                   48209:     }
                   48210: 
                   48211:     /**
                   48212:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   48213:      * @return bool
                   48214:      * @access private
                   48215:      */
                   48216:     function _addPackage2($info)
                   48217:     {
                   48218:         if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
                   48219:             return false;
                   48220:         }
                   48221: 
                   48222:         if (!$info->validate()) {
                   48223:             if (class_exists('PEAR_Common')) {
                   48224:                 $ui = PEAR_Frontend::singleton();
                   48225:                 if ($ui) {
                   48226:                     foreach ($info->getValidationWarnings() as $err) {
                   48227:                         $ui->log($err['message'], true);
                   48228:                     }
                   48229:                 }
                   48230:             }
                   48231:             return false;
                   48232:         }
                   48233: 
                   48234:         $channel = $info->getChannel();
                   48235:         $package = $info->getPackage();
                   48236:         $save = $info;
                   48237:         if ($this->_packageExists($package, $channel)) {
                   48238:             return false;
                   48239:         }
                   48240: 
                   48241:         if (!$this->_channelExists($channel, true)) {
                   48242:             return false;
                   48243:         }
                   48244: 
                   48245:         $info = $info->toArray(true);
                   48246:         if (!$info) {
                   48247:             return false;
                   48248:         }
                   48249: 
                   48250:         $fp = $this->_openPackageFile($package, 'wb', $channel);
                   48251:         if ($fp === null) {
                   48252:             return false;
                   48253:         }
                   48254: 
                   48255:         $info['_lastmodified'] = time();
                   48256:         fwrite($fp, serialize($info));
                   48257:         $this->_closePackageFile($fp);
                   48258:         $this->_rebuildFileMap();
                   48259:         return true;
                   48260:     }
                   48261: 
                   48262:     /**
                   48263:      * @param string Package name
                   48264:      * @param array parsed package.xml 1.0
                   48265:      * @param bool this parameter is only here for BC.  Don't use it.
                   48266:      * @access private
                   48267:      */
                   48268:     function _updatePackage($package, $info, $merge = true)
                   48269:     {
                   48270:         $oldinfo = $this->_packageInfo($package);
                   48271:         if (empty($oldinfo)) {
                   48272:             return false;
                   48273:         }
                   48274: 
                   48275:         $fp = $this->_openPackageFile($package, 'w');
                   48276:         if ($fp === null) {
                   48277:             return false;
                   48278:         }
                   48279: 
                   48280:         if (is_object($info)) {
                   48281:             $info = $info->toArray();
                   48282:         }
                   48283:         $info['_lastmodified'] = time();
                   48284: 
                   48285:         $newinfo = $info;
                   48286:         if ($merge) {
                   48287:             $info = array_merge($oldinfo, $info);
                   48288:         } else {
                   48289:             $diff = $info;
                   48290:         }
                   48291: 
                   48292:         fwrite($fp, serialize($info));
                   48293:         $this->_closePackageFile($fp);
                   48294:         if (isset($newinfo['filelist'])) {
                   48295:             $this->_rebuildFileMap();
                   48296:         }
                   48297: 
                   48298:         return true;
                   48299:     }
                   48300: 
                   48301:     /**
                   48302:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   48303:      * @return bool
                   48304:      * @access private
                   48305:      */
                   48306:     function _updatePackage2($info)
                   48307:     {
                   48308:         if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
                   48309:             return false;
                   48310:         }
                   48311: 
                   48312:         $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
                   48313:         if ($fp === null) {
                   48314:             return false;
                   48315:         }
                   48316: 
                   48317:         $save = $info;
                   48318:         $info = $save->getArray(true);
                   48319:         $info['_lastmodified'] = time();
                   48320:         fwrite($fp, serialize($info));
                   48321:         $this->_closePackageFile($fp);
                   48322:         $this->_rebuildFileMap();
                   48323:         return true;
                   48324:     }
                   48325: 
                   48326:     /**
                   48327:      * @param string Package name
                   48328:      * @param string Channel name
                   48329:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   48330:      * @access private
                   48331:      */
                   48332:     function &_getPackage($package, $channel = 'pear.php.net')
                   48333:     {
                   48334:         $info = $this->_packageInfo($package, null, $channel);
                   48335:         if ($info === null) {
                   48336:             return $info;
                   48337:         }
                   48338: 
                   48339:         $a = $this->_config;
                   48340:         if (!$a) {
                   48341:             $this->_config = &new PEAR_Config;
                   48342:             $this->_config->set('php_dir', $this->statedir);
                   48343:         }
                   48344: 
                   48345:         if (!class_exists('PEAR_PackageFile')) {
                   48346:             require_once 'PEAR/PackageFile.php';
                   48347:         }
                   48348: 
                   48349:         $pkg = &new PEAR_PackageFile($this->_config);
                   48350:         $pf = &$pkg->fromArray($info);
                   48351:         return $pf;
                   48352:     }
                   48353: 
                   48354:     /**
                   48355:      * @param string channel name
                   48356:      * @param bool whether to strictly retrieve channel names
                   48357:      * @return PEAR_ChannelFile|PEAR_Error
                   48358:      * @access private
                   48359:      */
                   48360:     function &_getChannel($channel, $noaliases = false)
                   48361:     {
                   48362:         $ch = false;
                   48363:         if ($this->_channelExists($channel, $noaliases)) {
                   48364:             $chinfo = $this->_channelInfo($channel, $noaliases);
                   48365:             if ($chinfo) {
                   48366:                 if (!class_exists('PEAR_ChannelFile')) {
                   48367:                     require_once 'PEAR/ChannelFile.php';
                   48368:                 }
                   48369: 
                   48370:                 $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
                   48371:             }
                   48372:         }
                   48373: 
                   48374:         if ($ch) {
                   48375:             if ($ch->validate()) {
                   48376:                 return $ch;
                   48377:             }
                   48378: 
                   48379:             foreach ($ch->getErrors(true) as $err) {
                   48380:                 $message = $err['message'] . "\n";
                   48381:             }
                   48382: 
                   48383:             $ch = PEAR::raiseError($message);
                   48384:             return $ch;
                   48385:         }
                   48386: 
                   48387:         if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   48388:             // the registry is not properly set up, so use defaults
                   48389:             if (!class_exists('PEAR_ChannelFile')) {
                   48390:                 require_once 'PEAR/ChannelFile.php';
                   48391:             }
                   48392: 
                   48393:             $pear_channel = new PEAR_ChannelFile;
                   48394:             $pear_channel->setServer('pear.php.net');
                   48395:             $pear_channel->setAlias('pear');
                   48396:             $pear_channel->setSummary('PHP Extension and Application Repository');
                   48397:             $pear_channel->setDefaultPEARProtocols();
                   48398:             $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   48399:             $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   48400:             $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   48401:             return $pear_channel;
                   48402:         }
                   48403: 
                   48404:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   48405:             // the registry is not properly set up, so use defaults
                   48406:             if (!class_exists('PEAR_ChannelFile')) {
                   48407:                 require_once 'PEAR/ChannelFile.php';
                   48408:             }
                   48409:             $pear_channel = new PEAR_ChannelFile;
                   48410:             $pear_channel->setServer('pecl.php.net');
                   48411:             $pear_channel->setAlias('pecl');
                   48412:             $pear_channel->setSummary('PHP Extension Community Library');
                   48413:             $pear_channel->setDefaultPEARProtocols();
                   48414:             $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   48415:             $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   48416:             $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   48417:             return $pear_channel;
                   48418:         }
                   48419: 
                   48420:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   48421:             // the registry is not properly set up, so use defaults
                   48422:             if (!class_exists('PEAR_ChannelFile')) {
                   48423:                 require_once 'PEAR/ChannelFile.php';
                   48424:             }
                   48425: 
                   48426:             $doc_channel = new PEAR_ChannelFile;
                   48427:             $doc_channel->setServer('doc.php.net');
                   48428:             $doc_channel->setAlias('phpdocs');
                   48429:             $doc_channel->setSummary('PHP Documentation Team');
                   48430:             $doc_channel->setDefaultPEARProtocols();
                   48431:             $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   48432:             $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   48433:             $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   48434:             return $doc_channel;
                   48435:         }
                   48436: 
                   48437: 
                   48438:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   48439:             // the registry is not properly set up, so use defaults
                   48440:             if (!class_exists('PEAR_ChannelFile')) {
                   48441:                 require_once 'PEAR/ChannelFile.php';
                   48442:             }
                   48443: 
                   48444:             $private = new PEAR_ChannelFile;
                   48445:             $private->setName('__uri');
                   48446:             $private->setDefaultPEARProtocols();
                   48447:             $private->setBaseURL('REST1.0', '****');
                   48448:             $private->setSummary('Pseudo-channel for static packages');
                   48449:             return $private;
                   48450:         }
                   48451: 
                   48452:         return $ch;
                   48453:     }
                   48454: 
                   48455:     /**
                   48456:      * @param string Package name
                   48457:      * @param string Channel name
                   48458:      * @return bool
                   48459:      */
                   48460:     function packageExists($package, $channel = 'pear.php.net')
                   48461:     {
                   48462:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48463:             return $e;
                   48464:         }
                   48465:         $ret = $this->_packageExists($package, $channel);
                   48466:         $this->_unlock();
                   48467:         return $ret;
                   48468:     }
                   48469: 
                   48470:     // }}}
                   48471: 
                   48472:     // {{{ channelExists()
                   48473: 
                   48474:     /**
                   48475:      * @param string channel name
                   48476:      * @param bool if true, then aliases will be ignored
                   48477:      * @return bool
                   48478:      */
                   48479:     function channelExists($channel, $noaliases = false)
                   48480:     {
                   48481:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48482:             return $e;
                   48483:         }
                   48484:         $ret = $this->_channelExists($channel, $noaliases);
                   48485:         $this->_unlock();
                   48486:         return $ret;
                   48487:     }
                   48488: 
                   48489:     // }}}
                   48490: 
                   48491:     /**
                   48492:      * @param string channel name mirror is in
                   48493:      * @param string mirror name
                   48494:      *
                   48495:      * @return bool
                   48496:      */
                   48497:     function mirrorExists($channel, $mirror)
                   48498:     {
                   48499:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48500:             return $e;
                   48501:         }
                   48502: 
                   48503:         $ret = $this->_mirrorExists($channel, $mirror);
                   48504:         $this->_unlock();
                   48505:         return $ret;
                   48506:     }
                   48507: 
                   48508:     // {{{ isAlias()
                   48509: 
                   48510:     /**
                   48511:      * Determines whether the parameter is an alias of a channel
                   48512:      * @param string
                   48513:      * @return bool
                   48514:      */
                   48515:     function isAlias($alias)
                   48516:     {
                   48517:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48518:             return $e;
                   48519:         }
                   48520:         $ret = $this->_isChannelAlias($alias);
                   48521:         $this->_unlock();
                   48522:         return $ret;
                   48523:     }
                   48524: 
                   48525:     // }}}
                   48526:     // {{{ packageInfo()
                   48527: 
                   48528:     /**
                   48529:      * @param string|null
                   48530:      * @param string|null
                   48531:      * @param string
                   48532:      * @return array|null
                   48533:      */
                   48534:     function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   48535:     {
                   48536:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48537:             return $e;
                   48538:         }
                   48539:         $ret = $this->_packageInfo($package, $key, $channel);
                   48540:         $this->_unlock();
                   48541:         return $ret;
                   48542:     }
                   48543: 
                   48544:     // }}}
                   48545:     // {{{ channelInfo()
                   48546: 
                   48547:     /**
                   48548:      * Retrieve a raw array of channel data.
                   48549:      *
                   48550:      * Do not use this, instead use {@link getChannel()} for normal
                   48551:      * operations.  Array structure is undefined in this method
                   48552:      * @param string channel name
                   48553:      * @param bool whether to strictly retrieve information only on non-aliases
                   48554:      * @return array|null|PEAR_Error
                   48555:      */
                   48556:     function channelInfo($channel = null, $noaliases = false)
                   48557:     {
                   48558:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48559:             return $e;
                   48560:         }
                   48561:         $ret = $this->_channelInfo($channel, $noaliases);
                   48562:         $this->_unlock();
                   48563:         return $ret;
                   48564:     }
                   48565: 
                   48566:     // }}}
                   48567: 
                   48568:     /**
                   48569:      * @param string
                   48570:      */
                   48571:     function channelName($channel)
                   48572:     {
                   48573:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48574:             return $e;
                   48575:         }
                   48576:         $ret = $this->_getChannelFromAlias($channel);
                   48577:         $this->_unlock();
                   48578:         return $ret;
                   48579:     }
                   48580: 
                   48581:     /**
                   48582:      * @param string
                   48583:      */
                   48584:     function channelAlias($channel)
                   48585:     {
                   48586:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48587:             return $e;
                   48588:         }
                   48589:         $ret = $this->_getAlias($channel);
                   48590:         $this->_unlock();
                   48591:         return $ret;
                   48592:     }
                   48593:     // {{{ listPackages()
                   48594: 
                   48595:     function listPackages($channel = false)
                   48596:     {
                   48597:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48598:             return $e;
                   48599:         }
                   48600:         $ret = $this->_listPackages($channel);
                   48601:         $this->_unlock();
                   48602:         return $ret;
                   48603:     }
                   48604: 
                   48605:     // }}}
                   48606:     // {{{ listAllPackages()
                   48607: 
                   48608:     function listAllPackages()
                   48609:     {
                   48610:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48611:             return $e;
                   48612:         }
                   48613:         $ret = $this->_listAllPackages();
                   48614:         $this->_unlock();
                   48615:         return $ret;
                   48616:     }
                   48617: 
                   48618:     // }}}
                   48619:     // {{{ listChannel()
                   48620: 
                   48621:     function listChannels()
                   48622:     {
                   48623:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48624:             return $e;
                   48625:         }
                   48626:         $ret = $this->_listChannels();
                   48627:         $this->_unlock();
                   48628:         return $ret;
                   48629:     }
                   48630: 
                   48631:     // }}}
                   48632:     // {{{ addPackage()
                   48633: 
                   48634:     /**
                   48635:      * Add an installed package to the registry
                   48636:      * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
                   48637:      *               that will be passed to {@link addPackage2()}
                   48638:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   48639:      * @return bool success of saving
                   48640:      */
                   48641:     function addPackage($package, $info)
                   48642:     {
                   48643:         if (is_object($info)) {
                   48644:             return $this->addPackage2($info);
                   48645:         }
                   48646:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48647:             return $e;
                   48648:         }
                   48649:         $ret = $this->_addPackage($package, $info);
                   48650:         $this->_unlock();
                   48651:         if ($ret) {
                   48652:             if (!class_exists('PEAR_PackageFile_v1')) {
                   48653:                 require_once 'PEAR/PackageFile/v1.php';
                   48654:             }
                   48655:             $pf = new PEAR_PackageFile_v1;
                   48656:             $pf->setConfig($this->_config);
                   48657:             $pf->fromArray($info);
                   48658:             $this->_dependencyDB->uninstallPackage($pf);
                   48659:             $this->_dependencyDB->installPackage($pf);
                   48660:         }
                   48661:         return $ret;
                   48662:     }
                   48663: 
                   48664:     // }}}
                   48665:     // {{{ addPackage2()
                   48666: 
                   48667:     function addPackage2($info)
                   48668:     {
                   48669:         if (!is_object($info)) {
                   48670:             return $this->addPackage($info['package'], $info);
                   48671:         }
                   48672:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48673:             return $e;
                   48674:         }
                   48675:         $ret = $this->_addPackage2($info);
                   48676:         $this->_unlock();
                   48677:         if ($ret) {
                   48678:             $this->_dependencyDB->uninstallPackage($info);
                   48679:             $this->_dependencyDB->installPackage($info);
                   48680:         }
                   48681:         return $ret;
                   48682:     }
                   48683: 
                   48684:     // }}}
                   48685:     // {{{ updateChannel()
                   48686: 
                   48687:     /**
                   48688:      * For future expandibility purposes, separate this
                   48689:      * @param PEAR_ChannelFile
                   48690:      */
                   48691:     function updateChannel($channel, $lastmodified = null)
                   48692:     {
                   48693:         if ($channel->getName() == '__uri') {
                   48694:             return false;
                   48695:         }
                   48696:         return $this->addChannel($channel, $lastmodified, true);
                   48697:     }
                   48698: 
                   48699:     // }}}
                   48700:     // {{{ deleteChannel()
                   48701: 
                   48702:     /**
                   48703:      * Deletion fails if there are any packages installed from the channel
                   48704:      * @param string|PEAR_ChannelFile channel name
                   48705:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   48706:      */
                   48707:     function deleteChannel($channel)
                   48708:     {
                   48709:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48710:             return $e;
                   48711:         }
                   48712: 
                   48713:         $ret = $this->_deleteChannel($channel);
                   48714:         $this->_unlock();
                   48715:         if ($ret && is_a($this->_config, 'PEAR_Config')) {
                   48716:             $this->_config->setChannels($this->listChannels());
                   48717:         }
                   48718: 
                   48719:         return $ret;
                   48720:     }
                   48721: 
                   48722:     // }}}
                   48723:     // {{{ addChannel()
                   48724: 
                   48725:     /**
                   48726:      * @param PEAR_ChannelFile Channel object
                   48727:      * @param string Last-Modified header from HTTP for caching
                   48728:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   48729:      */
                   48730:     function addChannel($channel, $lastmodified = false, $update = false)
                   48731:     {
                   48732:         if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
                   48733:             return false;
                   48734:         }
                   48735: 
                   48736:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48737:             return $e;
                   48738:         }
                   48739: 
                   48740:         $ret = $this->_addChannel($channel, $update, $lastmodified);
                   48741:         $this->_unlock();
                   48742:         if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
                   48743:             $this->_config->setChannels($this->listChannels());
                   48744:         }
                   48745: 
                   48746:         return $ret;
                   48747:     }
                   48748: 
                   48749:     // }}}
                   48750:     // {{{ deletePackage()
                   48751: 
                   48752:     function deletePackage($package, $channel = 'pear.php.net')
                   48753:     {
                   48754:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48755:             return $e;
                   48756:         }
                   48757: 
                   48758:         $file = $this->_packageFileName($package, $channel);
                   48759:         $ret  = file_exists($file) ? @unlink($file) : false;
                   48760:         $this->_rebuildFileMap();
                   48761:         $this->_unlock();
                   48762:         $p = array('channel' => $channel, 'package' => $package);
                   48763:         $this->_dependencyDB->uninstallPackage($p);
                   48764:         return $ret;
                   48765:     }
                   48766: 
                   48767:     // }}}
                   48768:     // {{{ updatePackage()
                   48769: 
                   48770:     function updatePackage($package, $info, $merge = true)
                   48771:     {
                   48772:         if (is_object($info)) {
                   48773:             return $this->updatePackage2($info, $merge);
                   48774:         }
                   48775:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48776:             return $e;
                   48777:         }
                   48778:         $ret = $this->_updatePackage($package, $info, $merge);
                   48779:         $this->_unlock();
                   48780:         if ($ret) {
                   48781:             if (!class_exists('PEAR_PackageFile_v1')) {
                   48782:                 require_once 'PEAR/PackageFile/v1.php';
                   48783:             }
                   48784:             $pf = new PEAR_PackageFile_v1;
                   48785:             $pf->setConfig($this->_config);
                   48786:             $pf->fromArray($this->packageInfo($package));
                   48787:             $this->_dependencyDB->uninstallPackage($pf);
                   48788:             $this->_dependencyDB->installPackage($pf);
                   48789:         }
                   48790:         return $ret;
                   48791:     }
                   48792: 
                   48793:     // }}}
                   48794:     // {{{ updatePackage2()
                   48795: 
                   48796:     function updatePackage2($info)
                   48797:     {
                   48798: 
                   48799:         if (!is_object($info)) {
                   48800:             return $this->updatePackage($info['package'], $info, $merge);
                   48801:         }
                   48802: 
                   48803:         if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
                   48804:             return false;
                   48805:         }
                   48806: 
                   48807:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48808:             return $e;
                   48809:         }
                   48810: 
                   48811:         $ret = $this->_updatePackage2($info);
                   48812:         $this->_unlock();
                   48813:         if ($ret) {
                   48814:             $this->_dependencyDB->uninstallPackage($info);
                   48815:             $this->_dependencyDB->installPackage($info);
                   48816:         }
                   48817: 
                   48818:         return $ret;
                   48819:     }
                   48820: 
                   48821:     // }}}
                   48822:     // {{{ getChannel()
                   48823:     /**
                   48824:      * @param string channel name
                   48825:      * @param bool whether to strictly return raw channels (no aliases)
                   48826:      * @return PEAR_ChannelFile|PEAR_Error
                   48827:      */
                   48828:     function &getChannel($channel, $noaliases = false)
                   48829:     {
                   48830:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48831:             return $e;
                   48832:         }
                   48833:         $ret = &$this->_getChannel($channel, $noaliases);
                   48834:         $this->_unlock();
                   48835:         if (!$ret) {
                   48836:             return PEAR::raiseError('Unknown channel: ' . $channel);
                   48837:         }
                   48838:         return $ret;
                   48839:     }
                   48840: 
                   48841:     // }}}
                   48842:     // {{{ getPackage()
                   48843:     /**
                   48844:      * @param string package name
                   48845:      * @param string channel name
                   48846:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   48847:      */
                   48848:     function &getPackage($package, $channel = 'pear.php.net')
                   48849:     {
                   48850:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48851:             return $e;
                   48852:         }
                   48853:         $pf = &$this->_getPackage($package, $channel);
                   48854:         $this->_unlock();
                   48855:         return $pf;
                   48856:     }
                   48857: 
                   48858:     // }}}
                   48859: 
                   48860:     /**
                   48861:      * Get PEAR_PackageFile_v[1/2] objects representing the contents of
                   48862:      * a dependency group that are installed.
                   48863:      *
                   48864:      * This is used at uninstall-time
                   48865:      * @param array
                   48866:      * @return array|false
                   48867:      */
                   48868:     function getInstalledGroup($group)
                   48869:     {
                   48870:         $ret = array();
                   48871:         if (isset($group['package'])) {
                   48872:             if (!isset($group['package'][0])) {
                   48873:                 $group['package'] = array($group['package']);
                   48874:             }
                   48875:             foreach ($group['package'] as $package) {
                   48876:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   48877:                 $p = &$this->getPackage($package['name'], $depchannel);
                   48878:                 if ($p) {
                   48879:                     $save = &$p;
                   48880:                     $ret[] = &$save;
                   48881:                 }
                   48882:             }
                   48883:         }
                   48884:         if (isset($group['subpackage'])) {
                   48885:             if (!isset($group['subpackage'][0])) {
                   48886:                 $group['subpackage'] = array($group['subpackage']);
                   48887:             }
                   48888:             foreach ($group['subpackage'] as $package) {
                   48889:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   48890:                 $p = &$this->getPackage($package['name'], $depchannel);
                   48891:                 if ($p) {
                   48892:                     $save = &$p;
                   48893:                     $ret[] = &$save;
                   48894:                 }
                   48895:             }
                   48896:         }
                   48897:         if (!count($ret)) {
                   48898:             return false;
                   48899:         }
                   48900:         return $ret;
                   48901:     }
                   48902: 
                   48903:     // {{{ getChannelValidator()
                   48904:     /**
                   48905:      * @param string channel name
                   48906:      * @return PEAR_Validate|false
                   48907:      */
                   48908:     function &getChannelValidator($channel)
                   48909:     {
                   48910:         $chan = $this->getChannel($channel);
                   48911:         if (PEAR::isError($chan)) {
                   48912:             return $chan;
                   48913:         }
                   48914:         $val = $chan->getValidationObject();
                   48915:         return $val;
                   48916:     }
                   48917:     // }}}
                   48918:     // {{{ getChannels()
                   48919:     /**
                   48920:      * @param string channel name
                   48921:      * @return array an array of PEAR_ChannelFile objects representing every installed channel
                   48922:      */
                   48923:     function &getChannels()
                   48924:     {
                   48925:         $ret = array();
                   48926:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48927:             return $e;
                   48928:         }
                   48929:         foreach ($this->_listChannels() as $channel) {
                   48930:             $e = &$this->_getChannel($channel);
                   48931:             if (!$e || PEAR::isError($e)) {
                   48932:                 continue;
                   48933:             }
                   48934:             $ret[] = $e;
                   48935:         }
                   48936:         $this->_unlock();
                   48937:         return $ret;
                   48938:     }
                   48939: 
                   48940:     // }}}
                   48941:     // {{{ checkFileMap()
                   48942: 
                   48943:     /**
                   48944:      * Test whether a file or set of files belongs to a package.
                   48945:      *
                   48946:      * If an array is passed in
                   48947:      * @param string|array file path, absolute or relative to the pear
                   48948:      *                     install dir
                   48949:      * @param string|array name of PEAR package or array('package' => name, 'channel' =>
                   48950:      *                     channel) of a package that will be ignored
                   48951:      * @param string API version - 1.1 will exclude any files belonging to a package
                   48952:      * @param array private recursion variable
                   48953:      * @return array|false which package and channel the file belongs to, or an empty
                   48954:      *                     string if the file does not belong to an installed package,
                   48955:      *                     or belongs to the second parameter's package
                   48956:      */
                   48957:     function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
                   48958:     {
                   48959:         if (is_array($path)) {
                   48960:             static $notempty;
                   48961:             if (empty($notempty)) {
                   48962:                 if (!class_exists('PEAR_Installer_Role')) {
                   48963:                     require_once 'PEAR/Installer/Role.php';
                   48964:                 }
                   48965:                 $notempty = create_function('$a','return !empty($a);');
                   48966:             }
                   48967:             $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
                   48968:                 : strtolower($package);
                   48969:             $pkgs = array();
                   48970:             foreach ($path as $name => $attrs) {
                   48971:                 if (is_array($attrs)) {
                   48972:                     if (isset($attrs['install-as'])) {
                   48973:                         $name = $attrs['install-as'];
                   48974:                     }
                   48975:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
                   48976:                         // these are not installed
                   48977:                         continue;
                   48978:                     }
                   48979:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
                   48980:                         $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
                   48981:                     }
                   48982:                     if (isset($attrs['baseinstalldir'])) {
                   48983:                         $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
                   48984:                     }
                   48985:                 }
                   48986:                 $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
                   48987:                 if (PEAR::isError($pkgs[$name])) {
                   48988:                     return $pkgs[$name];
                   48989:                 }
                   48990:             }
                   48991:             return array_filter($pkgs, $notempty);
                   48992:         }
                   48993:         if (empty($this->filemap_cache)) {
                   48994:             if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48995:                 return $e;
                   48996:             }
                   48997:             $err = $this->_readFileMap();
                   48998:             $this->_unlock();
                   48999:             if (PEAR::isError($err)) {
                   49000:                 return $err;
                   49001:             }
                   49002:         }
                   49003:         if (!$attrs) {
                   49004:             $attrs = array('role' => 'php'); // any old call would be for PHP role only
                   49005:         }
                   49006:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   49007:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   49008:                 return false;
                   49009:             }
                   49010:             return $this->filemap_cache[$attrs['role']][$path];
                   49011:         }
                   49012:         $l = strlen($this->install_dir);
                   49013:         if (substr($path, 0, $l) == $this->install_dir) {
                   49014:             $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
                   49015:         }
                   49016:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   49017:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   49018:                 return false;
                   49019:             }
                   49020:             return $this->filemap_cache[$attrs['role']][$path];
                   49021:         }
                   49022:         return false;
                   49023:     }
                   49024: 
                   49025:     // }}}
                   49026:     // {{{ flush()
                   49027:     /**
                   49028:      * Force a reload of the filemap
                   49029:      * @since 1.5.0RC3
                   49030:      */
                   49031:     function flushFileMap()
                   49032:     {
                   49033:         $this->filemap_cache = null;
                   49034:         clearstatcache(); // ensure that the next read gets the full, current filemap
                   49035:     }
                   49036: 
                   49037:     // }}}
                   49038:     // {{{ apiVersion()
                   49039:     /**
                   49040:      * Get the expected API version.  Channels API is version 1.1, as it is backwards
                   49041:      * compatible with 1.0
                   49042:      * @return string
                   49043:      */
                   49044:     function apiVersion()
                   49045:     {
                   49046:         return '1.1';
                   49047:     }
                   49048:     // }}}
                   49049: 
                   49050: 
                   49051:     /**
                   49052:      * Parse a package name, or validate a parsed package name array
                   49053:      * @param string|array pass in an array of format
                   49054:      *                     array(
                   49055:      *                      'package' => 'pname',
                   49056:      *                     ['channel' => 'channame',]
                   49057:      *                     ['version' => 'version',]
                   49058:      *                     ['state' => 'state',]
                   49059:      *                     ['group' => 'groupname'])
                   49060:      *                     or a string of format
                   49061:      *                     [channel://][channame/]pname[-version|-state][/group=groupname]
                   49062:      * @return array|PEAR_Error
                   49063:      */
                   49064:     function parsePackageName($param, $defaultchannel = 'pear.php.net')
                   49065:     {
                   49066:         $saveparam = $param;
                   49067:         if (is_array($param)) {
                   49068:             // convert to string for error messages
                   49069:             $saveparam = $this->parsedPackageNameToString($param);
                   49070:             // process the array
                   49071:             if (!isset($param['package'])) {
                   49072:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   49073:                     'must contain a valid package name in index "param"',
                   49074:                     'package', null, null, $param);
                   49075:             }
                   49076:             if (!isset($param['uri'])) {
                   49077:                 if (!isset($param['channel'])) {
                   49078:                     $param['channel'] = $defaultchannel;
                   49079:                 }
                   49080:             } else {
                   49081:                 $param['channel'] = '__uri';
                   49082:             }
                   49083:         } else {
                   49084:             $components = @parse_url((string) $param);
                   49085:             if (isset($components['scheme'])) {
                   49086:                 if ($components['scheme'] == 'http') {
                   49087:                     // uri package
                   49088:                     $param = array('uri' => $param, 'channel' => '__uri');
                   49089:                 } elseif($components['scheme'] != 'channel') {
                   49090:                     return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
                   49091:                         'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
                   49092:                 }
                   49093:             }
                   49094:             if (!isset($components['path'])) {
                   49095:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   49096:                     'must contain a valid package name in "' . $param . '"',
                   49097:                     'package', null, null, $param);
                   49098:             }
                   49099:             if (isset($components['host'])) {
                   49100:                 // remove the leading "/"
                   49101:                 $components['path'] = substr($components['path'], 1);
                   49102:             }
                   49103:             if (!isset($components['scheme'])) {
                   49104:                 if (strpos($components['path'], '/') !== false) {
                   49105:                     if ($components['path']{0} == '/') {
                   49106:                         return PEAR::raiseError('parsePackageName(): this is not ' .
                   49107:                             'a package name, it begins with "/" in "' . $param . '"',
                   49108:                             'invalid', null, null, $param);
                   49109:                     }
                   49110:                     $parts = explode('/', $components['path']);
                   49111:                     $components['host'] = array_shift($parts);
                   49112:                     if (count($parts) > 1) {
                   49113:                         $components['path'] = array_pop($parts);
                   49114:                         $components['host'] .= '/' . implode('/', $parts);
                   49115:                     } else {
                   49116:                         $components['path'] = implode('/', $parts);
                   49117:                     }
                   49118:                 } else {
                   49119:                     $components['host'] = $defaultchannel;
                   49120:                 }
                   49121:             } else {
                   49122:                 if (strpos($components['path'], '/')) {
                   49123:                     $parts = explode('/', $components['path']);
                   49124:                     $components['path'] = array_pop($parts);
                   49125:                     $components['host'] .= '/' . implode('/', $parts);
                   49126:                 }
                   49127:             }
                   49128: 
                   49129:             if (is_array($param)) {
                   49130:                 $param['package'] = $components['path'];
                   49131:             } else {
                   49132:                 $param = array(
                   49133:                     'package' => $components['path']
                   49134:                     );
                   49135:                 if (isset($components['host'])) {
                   49136:                     $param['channel'] = $components['host'];
                   49137:                 }
                   49138:             }
                   49139:             if (isset($components['fragment'])) {
                   49140:                 $param['group'] = $components['fragment'];
                   49141:             }
                   49142:             if (isset($components['user'])) {
                   49143:                 $param['user'] = $components['user'];
                   49144:             }
                   49145:             if (isset($components['pass'])) {
                   49146:                 $param['pass'] = $components['pass'];
                   49147:             }
                   49148:             if (isset($components['query'])) {
                   49149:                 parse_str($components['query'], $param['opts']);
                   49150:             }
                   49151:             // check for extension
                   49152:             $pathinfo = pathinfo($param['package']);
                   49153:             if (isset($pathinfo['extension']) &&
                   49154:                   in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
                   49155:                 $param['extension'] = $pathinfo['extension'];
                   49156:                 $param['package'] = substr($pathinfo['basename'], 0,
                   49157:                     strlen($pathinfo['basename']) - 4);
                   49158:             }
                   49159:             // check for version
                   49160:             if (strpos($param['package'], '-')) {
                   49161:                 $test = explode('-', $param['package']);
                   49162:                 if (count($test) != 2) {
                   49163:                     return PEAR::raiseError('parsePackageName(): only one version/state ' .
                   49164:                         'delimiter "-" is allowed in "' . $saveparam . '"',
                   49165:                         'version', null, null, $param);
                   49166:                 }
                   49167:                 list($param['package'], $param['version']) = $test;
                   49168:             }
                   49169:         }
                   49170:         // validation
                   49171:         $info = $this->channelExists($param['channel']);
                   49172:         if (PEAR::isError($info)) {
                   49173:             return $info;
                   49174:         }
                   49175:         if (!$info) {
                   49176:             return PEAR::raiseError('unknown channel "' . $param['channel'] .
                   49177:                 '" in "' . $saveparam . '"', 'channel', null, null, $param);
                   49178:         }
                   49179:         $chan = $this->getChannel($param['channel']);
                   49180:         if (PEAR::isError($chan)) {
                   49181:             return $chan;
                   49182:         }
                   49183:         if (!$chan) {
                   49184:             return PEAR::raiseError("Exception: corrupt registry, could not " .
                   49185:                 "retrieve channel " . $param['channel'] . " information",
                   49186:                 'registry', null, null, $param);
                   49187:         }
                   49188:         $param['channel'] = $chan->getName();
                   49189:         $validate = $chan->getValidationObject();
                   49190:         $vpackage = $chan->getValidationPackage();
                   49191:         // validate package name
                   49192:         if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
                   49193:             return PEAR::raiseError('parsePackageName(): invalid package name "' .
                   49194:                 $param['package'] . '" in "' . $saveparam . '"',
                   49195:                 'package', null, null, $param);
                   49196:         }
                   49197:         if (isset($param['group'])) {
                   49198:             if (!PEAR_Validate::validGroupName($param['group'])) {
                   49199:                 return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
                   49200:                     '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
                   49201:                     $param);
                   49202:             }
                   49203:         }
                   49204:         if (isset($param['state'])) {
                   49205:             if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
                   49206:                 return PEAR::raiseError('parsePackageName(): state "' . $param['state']
                   49207:                     . '" is not a valid state in "' . $saveparam . '"',
                   49208:                     'state', null, null, $param);
                   49209:             }
                   49210:         }
                   49211:         if (isset($param['version'])) {
                   49212:             if (isset($param['state'])) {
                   49213:                 return PEAR::raiseError('parsePackageName(): cannot contain both ' .
                   49214:                     'a version and a stability (state) in "' . $saveparam . '"',
                   49215:                     'version/state', null, null, $param);
                   49216:             }
                   49217:             // check whether version is actually a state
                   49218:             if (in_array(strtolower($param['version']), $validate->getValidStates())) {
                   49219:                 $param['state'] = strtolower($param['version']);
                   49220:                 unset($param['version']);
                   49221:             } else {
                   49222:                 if (!$validate->validVersion($param['version'])) {
                   49223:                     return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
                   49224:                         '" is neither a valid version nor a valid state in "' .
                   49225:                         $saveparam . '"', 'version/state', null, null, $param);
                   49226:                 }
                   49227:             }
                   49228:         }
                   49229:         return $param;
                   49230:     }
                   49231: 
                   49232:     /**
                   49233:      * @param array
                   49234:      * @return string
                   49235:      */
                   49236:     function parsedPackageNameToString($parsed, $brief = false)
                   49237:     {
                   49238:         if (is_string($parsed)) {
                   49239:             return $parsed;
                   49240:         }
                   49241:         if (is_object($parsed)) {
                   49242:             $p = $parsed;
                   49243:             $parsed = array(
                   49244:                 'package' => $p->getPackage(),
                   49245:                 'channel' => $p->getChannel(),
                   49246:                 'version' => $p->getVersion(),
                   49247:             );
                   49248:         }
                   49249:         if (isset($parsed['uri'])) {
                   49250:             return $parsed['uri'];
                   49251:         }
                   49252:         if ($brief) {
                   49253:             if ($channel = $this->channelAlias($parsed['channel'])) {
                   49254:                 return $channel . '/' . $parsed['package'];
                   49255:             }
                   49256:         }
                   49257:         $upass = '';
                   49258:         if (isset($parsed['user'])) {
                   49259:             $upass = $parsed['user'];
                   49260:             if (isset($parsed['pass'])) {
                   49261:                 $upass .= ':' . $parsed['pass'];
                   49262:             }
                   49263:             $upass = "$upass@";
                   49264:         }
                   49265:         $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
                   49266:         if (isset($parsed['version']) || isset($parsed['state'])) {
                   49267:             $ver = isset($parsed['version']) ? $parsed['version'] : '';
                   49268:             $ver .= isset($parsed['state']) ? $parsed['state'] : '';
                   49269:             $ret .= '-' . $ver;
                   49270:         }
                   49271:         if (isset($parsed['extension'])) {
                   49272:             $ret .= '.' . $parsed['extension'];
                   49273:         }
                   49274:         if (isset($parsed['opts'])) {
                   49275:             $ret .= '?';
                   49276:             foreach ($parsed['opts'] as $name => $value) {
                   49277:                 $parsed['opts'][$name] = "$name=$value";
                   49278:             }
                   49279:             $ret .= implode('&', $parsed['opts']);
                   49280:         }
                   49281:         if (isset($parsed['group'])) {
                   49282:             $ret .= '#' . $parsed['group'];
                   49283:         }
                   49284:         return $ret;
                   49285:     }
                   49286: }PEAR-1.9.4/PEAR/REST.php0000644000076500000240000004151711605156760013263 0ustar  helgistaff<?php
                   49287: /**
                   49288:  * PEAR_REST
                   49289:  *
                   49290:  * PHP versions 4 and 5
                   49291:  *
                   49292:  * @category   pear
                   49293:  * @package    PEAR
                   49294:  * @author     Greg Beaver <cellog@php.net>
                   49295:  * @copyright  1997-2009 The Authors
                   49296:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49297:  * @version    CVS: $Id: REST.php 313023 2011-07-06 19:17:11Z dufuz $
                   49298:  * @link       http://pear.php.net/package/PEAR
                   49299:  * @since      File available since Release 1.4.0a1
                   49300:  */
                   49301: 
                   49302: /**
                   49303:  * For downloading xml files
                   49304:  */
                   49305: require_once 'PEAR.php';
                   49306: require_once 'PEAR/XMLParser.php';
                   49307: 
                   49308: /**
                   49309:  * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
                   49310:  * as well
                   49311:  * @category   pear
                   49312:  * @package    PEAR
                   49313:  * @author     Greg Beaver <cellog@php.net>
                   49314:  * @copyright  1997-2009 The Authors
                   49315:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49316:  * @version    Release: 1.9.4
                   49317:  * @link       http://pear.php.net/package/PEAR
                   49318:  * @since      Class available since Release 1.4.0a1
                   49319:  */
                   49320: class PEAR_REST
                   49321: {
                   49322:     var $config;
                   49323:     var $_options;
                   49324: 
                   49325:     function PEAR_REST(&$config, $options = array())
                   49326:     {
                   49327:         $this->config   = &$config;
                   49328:         $this->_options = $options;
                   49329:     }
                   49330: 
                   49331:     /**
                   49332:      * Retrieve REST data, but always retrieve the local cache if it is available.
                   49333:      *
                   49334:      * This is useful for elements that should never change, such as information on a particular
                   49335:      * release
                   49336:      * @param string full URL to this resource
                   49337:      * @param array|false contents of the accept-encoding header
                   49338:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   49339:      *                    parsed using PEAR_XMLParser
                   49340:      * @return string|array
                   49341:      */
                   49342:     function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
                   49343:     {
                   49344:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49345:             md5($url) . 'rest.cachefile';
                   49346: 
                   49347:         if (file_exists($cachefile)) {
                   49348:             return unserialize(implode('', file($cachefile)));
                   49349:         }
                   49350: 
                   49351:         return $this->retrieveData($url, $accept, $forcestring, $channel);
                   49352:     }
                   49353: 
                   49354:     /**
                   49355:      * Retrieve a remote REST resource
                   49356:      * @param string full URL to this resource
                   49357:      * @param array|false contents of the accept-encoding header
                   49358:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   49359:      *                    parsed using PEAR_XMLParser
                   49360:      * @return string|array
                   49361:      */
                   49362:     function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
                   49363:     {
                   49364:         $cacheId = $this->getCacheId($url);
                   49365:         if ($ret = $this->useLocalCache($url, $cacheId)) {
                   49366:             return $ret;
                   49367:         }
                   49368: 
                   49369:         $file = $trieddownload = false;
                   49370:         if (!isset($this->_options['offline'])) {
                   49371:             $trieddownload = true;
                   49372:             $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
                   49373:         }
                   49374: 
                   49375:         if (PEAR::isError($file)) {
                   49376:             if ($file->getCode() !== -9276) {
                   49377:                 return $file;
                   49378:             }
                   49379: 
                   49380:             $trieddownload = false;
                   49381:             $file = false; // use local copy if available on socket connect error
                   49382:         }
                   49383: 
                   49384:         if (!$file) {
                   49385:             $ret = $this->getCache($url);
                   49386:             if (!PEAR::isError($ret) && $trieddownload) {
                   49387:                 // reset the age of the cache if the server says it was unmodified
                   49388:                 $result = $this->saveCache($url, $ret, null, true, $cacheId);
                   49389:                 if (PEAR::isError($result)) {
                   49390:                     return PEAR::raiseError($result->getMessage());
                   49391:                 }
                   49392:             }
                   49393: 
                   49394:             return $ret;
                   49395:         }
                   49396: 
                   49397:         if (is_array($file)) {
                   49398:             $headers      = $file[2];
                   49399:             $lastmodified = $file[1];
                   49400:             $content      = $file[0];
                   49401:         } else {
                   49402:             $headers      = array();
                   49403:             $lastmodified = false;
                   49404:             $content      = $file;
                   49405:         }
                   49406: 
                   49407:         if ($forcestring) {
                   49408:             $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   49409:             if (PEAR::isError($result)) {
                   49410:                 return PEAR::raiseError($result->getMessage());
                   49411:             }
                   49412: 
                   49413:             return $content;
                   49414:         }
                   49415: 
                   49416:         if (isset($headers['content-type'])) {
                   49417:             switch ($headers['content-type']) {
                   49418:                 case 'text/xml' :
                   49419:                 case 'application/xml' :
                   49420:                 case 'text/plain' :
                   49421:                     if ($headers['content-type'] === 'text/plain') {
                   49422:                         $check = substr($content, 0, 5);
                   49423:                         if ($check !== '<?xml') {
                   49424:                             break;
                   49425:                         }
                   49426:                     }
                   49427: 
                   49428:                     $parser = new PEAR_XMLParser;
                   49429:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   49430:                     $err = $parser->parse($content);
                   49431:                     PEAR::popErrorHandling();
                   49432:                     if (PEAR::isError($err)) {
                   49433:                         return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
                   49434:                             $err->getMessage());
                   49435:                     }
                   49436:                     $content = $parser->getData();
                   49437:                 case 'text/html' :
                   49438:                 default :
                   49439:                     // use it as a string
                   49440:             }
                   49441:         } else {
                   49442:             // assume XML
                   49443:             $parser = new PEAR_XMLParser;
                   49444:             $parser->parse($content);
                   49445:             $content = $parser->getData();
                   49446:         }
                   49447: 
                   49448:         $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   49449:         if (PEAR::isError($result)) {
                   49450:             return PEAR::raiseError($result->getMessage());
                   49451:         }
                   49452: 
                   49453:         return $content;
                   49454:     }
                   49455: 
                   49456:     function useLocalCache($url, $cacheid = null)
                   49457:     {
                   49458:         if ($cacheid === null) {
                   49459:             $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49460:                 md5($url) . 'rest.cacheid';
                   49461:             if (!file_exists($cacheidfile)) {
                   49462:                 return false;
                   49463:             }
                   49464: 
                   49465:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   49466:         }
                   49467: 
                   49468:         $cachettl = $this->config->get('cache_ttl');
                   49469:         // If cache is newer than $cachettl seconds, we use the cache!
                   49470:         if (time() - $cacheid['age'] < $cachettl) {
                   49471:             return $this->getCache($url);
                   49472:         }
                   49473: 
                   49474:         return false;
                   49475:     }
                   49476: 
                   49477:     function getCacheId($url)
                   49478:     {
                   49479:         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49480:             md5($url) . 'rest.cacheid';
                   49481: 
                   49482:         if (!file_exists($cacheidfile)) {
                   49483:             return false;
                   49484:         }
                   49485: 
                   49486:         $ret = unserialize(implode('', file($cacheidfile)));
                   49487:         return $ret;
                   49488:     }
                   49489: 
                   49490:     function getCache($url)
                   49491:     {
                   49492:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49493:             md5($url) . 'rest.cachefile';
                   49494: 
                   49495:         if (!file_exists($cachefile)) {
                   49496:             return PEAR::raiseError('No cached content available for "' . $url . '"');
                   49497:         }
                   49498: 
                   49499:         return unserialize(implode('', file($cachefile)));
                   49500:     }
                   49501: 
                   49502:     /**
                   49503:      * @param string full URL to REST resource
                   49504:      * @param string original contents of the REST resource
                   49505:      * @param array  HTTP Last-Modified and ETag headers
                   49506:      * @param bool   if true, then the cache id file should be regenerated to
                   49507:      *               trigger a new time-to-live value
                   49508:      */
                   49509:     function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
                   49510:     {
                   49511:         $cache_dir   = $this->config->get('cache_dir');
                   49512:         $d           = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
                   49513:         $cacheidfile = $d . 'rest.cacheid';
                   49514:         $cachefile   = $d . 'rest.cachefile';
                   49515: 
                   49516:         if (!is_dir($cache_dir)) {
                   49517:             if (System::mkdir(array('-p', $cache_dir)) === false) {
                   49518:               return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
                   49519:             }
                   49520:         }
                   49521: 
                   49522:         if ($cacheid === null && $nochange) {
                   49523:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   49524:         }
                   49525: 
                   49526:         $idData = serialize(array(
                   49527:             'age'        => time(),
                   49528:             'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
                   49529:         ));
                   49530: 
                   49531:         $result = $this->saveCacheFile($cacheidfile, $idData);
                   49532:         if (PEAR::isError($result)) {
                   49533:             return $result;
                   49534:         } elseif ($nochange) {
                   49535:             return true;
                   49536:         }
                   49537: 
                   49538:         $result = $this->saveCacheFile($cachefile, serialize($contents));
                   49539:         if (PEAR::isError($result)) {
                   49540:             if (file_exists($cacheidfile)) {
                   49541:               @unlink($cacheidfile);
                   49542:             }
                   49543: 
                   49544:             return $result;
                   49545:         }
                   49546: 
                   49547:         return true;
                   49548:     }
                   49549: 
                   49550:     function saveCacheFile($file, $contents)
                   49551:     {
                   49552:         $len = strlen($contents);
                   49553: 
                   49554:         $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
                   49555:         if ($cachefile_fp !== false) { // create file
                   49556:             if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   49557:                 fclose($cachefile_fp);
                   49558:                 return PEAR::raiseError("Could not write $file.");
                   49559:             }
                   49560:         } else { // update file
                   49561:             $cachefile_lstat = lstat($file);
                   49562:             $cachefile_fp = @fopen($file, 'wb');
                   49563:             if (!$cachefile_fp) {
                   49564:                 return PEAR::raiseError("Could not open $file for writing.");
                   49565:             }
                   49566: 
                   49567:             $cachefile_fstat = fstat($cachefile_fp);
                   49568:             if (
                   49569:               $cachefile_lstat['mode'] == $cachefile_fstat['mode'] &&
                   49570:               $cachefile_lstat['ino']  == $cachefile_fstat['ino'] &&
                   49571:               $cachefile_lstat['dev']  == $cachefile_fstat['dev'] &&
                   49572:               $cachefile_fstat['nlink'] === 1
                   49573:             ) {
                   49574:                 if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   49575:                     fclose($cachefile_fp);
                   49576:                     return PEAR::raiseError("Could not write $file.");
                   49577:                 }
                   49578:             } else {
                   49579:                 fclose($cachefile_fp);
                   49580:                 $link = function_exists('readlink') ? readlink($file) : $file;
                   49581:                 return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
                   49582:             }
                   49583:         }
                   49584: 
                   49585:         fclose($cachefile_fp);
                   49586:         return true;
                   49587:     }
                   49588: 
                   49589:     /**
                   49590:      * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
                   49591:      * This is best used for small files
                   49592:      *
                   49593:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   49594:      * setting), the proxy will be used.
                   49595:      *
                   49596:      * @param string  $url       the URL to download
                   49597:      * @param string  $save_dir  directory to save file in
                   49598:      * @param false|string|array $lastmodified header values to check against for caching
                   49599:      *                           use false to return the header values from this download
                   49600:      * @param false|array $accept Accept headers to send
                   49601:      * @return string|array  Returns the contents of the downloaded file or a PEAR
                   49602:      *                       error on failure.  If the error is caused by
                   49603:      *                       socket-related errors, the error object will
                   49604:      *                       have the fsockopen error code available through
                   49605:      *                       getCode().  If caching is requested, then return the header
                   49606:      *                       values.
                   49607:      *
                   49608:      * @access public
                   49609:      */
                   49610:     function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
                   49611:     {
                   49612:         static $redirect = 0;
                   49613:         // always reset , so we are clean case of error
                   49614:         $wasredirect = $redirect;
                   49615:         $redirect = 0;
                   49616: 
                   49617:         $info = parse_url($url);
                   49618:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   49619:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   49620:         }
                   49621: 
                   49622:         if (!isset($info['host'])) {
                   49623:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   49624:         }
                   49625: 
                   49626:         $host   = isset($info['host']) ? $info['host'] : null;
                   49627:         $port   = isset($info['port']) ? $info['port'] : null;
                   49628:         $path   = isset($info['path']) ? $info['path'] : null;
                   49629:         $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   49630: 
                   49631:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   49632:         if ($this->config->get('http_proxy')&&
                   49633:               $proxy = parse_url($this->config->get('http_proxy'))
                   49634:         ) {
                   49635:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   49636:             if ($schema === 'https') {
                   49637:                 $proxy_host = 'ssl://' . $proxy_host;
                   49638:             }
                   49639: 
                   49640:             $proxy_port   = isset($proxy['port']) ? $proxy['port'] : 8080;
                   49641:             $proxy_user   = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   49642:             $proxy_pass   = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   49643:             $proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
                   49644:         }
                   49645: 
                   49646:         if (empty($port)) {
                   49647:             $port = (isset($info['scheme']) && $info['scheme'] == 'https')  ? 443 : 80;
                   49648:         }
                   49649: 
                   49650:         if (isset($proxy['host'])) {
                   49651:             $request = "GET $url HTTP/1.1\r\n";
                   49652:         } else {
                   49653:             $request = "GET $path HTTP/1.1\r\n";
                   49654:         }
                   49655: 
                   49656:         $request .= "Host: $host\r\n";
                   49657:         $ifmodifiedsince = '';
                   49658:         if (is_array($lastmodified)) {
                   49659:             if (isset($lastmodified['Last-Modified'])) {
                   49660:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   49661:             }
                   49662: 
                   49663:             if (isset($lastmodified['ETag'])) {
                   49664:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   49665:             }
                   49666:         } else {
                   49667:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   49668:         }
                   49669: 
                   49670:         $request .= $ifmodifiedsince .
                   49671:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
                   49672: 
                   49673:         $username = $this->config->get('username', null, $channel);
                   49674:         $password = $this->config->get('password', null, $channel);
                   49675: 
                   49676:         if ($username && $password) {
                   49677:             $tmp = base64_encode("$username:$password");
                   49678:             $request .= "Authorization: Basic $tmp\r\n";
                   49679:         }
                   49680: 
                   49681:         if ($proxy_host != '' && $proxy_user != '') {
                   49682:             $request .= 'Proxy-Authorization: Basic ' .
                   49683:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   49684:         }
                   49685: 
                   49686:         if ($accept) {
                   49687:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   49688:         }
                   49689: 
                   49690:         $request .= "Accept-Encoding:\r\n";
                   49691:         $request .= "Connection: close\r\n";
                   49692:         $request .= "\r\n";
                   49693: 
                   49694:         if ($proxy_host != '') {
                   49695:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
                   49696:             if (!$fp) {
                   49697:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276);
                   49698:             }
                   49699:         } else {
                   49700:             if ($schema === 'https') {
                   49701:                 $host = 'ssl://' . $host;
                   49702:             }
                   49703: 
                   49704:             $fp = @fsockopen($host, $port, $errno, $errstr);
                   49705:             if (!$fp) {
                   49706:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   49707:             }
                   49708:         }
                   49709: 
                   49710:         fwrite($fp, $request);
                   49711: 
                   49712:         $headers = array();
                   49713:         $reply   = 0;
                   49714:         while ($line = trim(fgets($fp, 1024))) {
                   49715:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   49716:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   49717:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   49718:                 $reply = (int)$matches[1];
                   49719:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   49720:                     return false;
                   49721:                 }
                   49722: 
                   49723:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   49724:                     return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
                   49725:                 }
                   49726:             }
                   49727:         }
                   49728: 
                   49729:         if ($reply != 200) {
                   49730:             if (!isset($headers['location'])) {
                   49731:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
                   49732:             }
                   49733: 
                   49734:             if ($wasredirect > 4) {
                   49735:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
                   49736:             }
                   49737: 
                   49738:             $redirect = $wasredirect + 1;
                   49739:             return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
                   49740:         }
                   49741: 
                   49742:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   49743: 
                   49744:         $data = '';
                   49745:         while ($chunk = @fread($fp, 8192)) {
                   49746:             $data .= $chunk;
                   49747:         }
                   49748:         fclose($fp);
                   49749: 
                   49750:         if ($lastmodified === false || $lastmodified) {
                   49751:             if (isset($headers['etag'])) {
                   49752:                 $lastmodified = array('ETag' => $headers['etag']);
                   49753:             }
                   49754: 
                   49755:             if (isset($headers['last-modified'])) {
                   49756:                 if (is_array($lastmodified)) {
                   49757:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   49758:                 } else {
                   49759:                     $lastmodified = $headers['last-modified'];
                   49760:                 }
                   49761:             }
                   49762: 
                   49763:             return array($data, $lastmodified, $headers);
                   49764:         }
                   49765: 
                   49766:         return $data;
                   49767:     }
                   49768: }PEAR-1.9.4/PEAR/RunTest.php0000644000076500000240000010660211605156760014107 0ustar  helgistaff<?php
                   49769: /**
                   49770:  * PEAR_RunTest
                   49771:  *
                   49772:  * PHP versions 4 and 5
                   49773:  *
                   49774:  * @category   pear
                   49775:  * @package    PEAR
                   49776:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   49777:  * @author     Greg Beaver <cellog@php.net>
                   49778:  * @copyright  1997-2009 The Authors
                   49779:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49780:  * @version    CVS: $Id: RunTest.php 313024 2011-07-06 19:51:24Z dufuz $
                   49781:  * @link       http://pear.php.net/package/PEAR
                   49782:  * @since      File available since Release 1.3.3
                   49783:  */
                   49784: 
                   49785: /**
                   49786:  * for error handling
                   49787:  */
                   49788: require_once 'PEAR.php';
                   49789: require_once 'PEAR/Config.php';
                   49790: 
                   49791: define('DETAILED', 1);
                   49792: putenv("PHP_PEAR_RUNTESTS=1");
                   49793: 
                   49794: /**
                   49795:  * Simplified version of PHP's test suite
                   49796:  *
                   49797:  * Try it with:
                   49798:  *
                   49799:  * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
                   49800:  *
                   49801:  *
                   49802:  * @category   pear
                   49803:  * @package    PEAR
                   49804:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   49805:  * @author     Greg Beaver <cellog@php.net>
                   49806:  * @copyright  1997-2009 The Authors
                   49807:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49808:  * @version    Release: 1.9.4
                   49809:  * @link       http://pear.php.net/package/PEAR
                   49810:  * @since      Class available since Release 1.3.3
                   49811:  */
                   49812: class PEAR_RunTest
                   49813: {
                   49814:     var $_headers = array();
                   49815:     var $_logger;
                   49816:     var $_options;
                   49817:     var $_php;
                   49818:     var $tests_count;
                   49819:     var $xdebug_loaded;
                   49820:     /**
                   49821:      * Saved value of php executable, used to reset $_php when we
                   49822:      * have a test that uses cgi
                   49823:      *
                   49824:      * @var unknown_type
                   49825:      */
                   49826:     var $_savephp;
                   49827:     var $ini_overwrites = array(
                   49828:         'output_handler=',
                   49829:         'open_basedir=',
                   49830:         'safe_mode=0',
                   49831:         'disable_functions=',
                   49832:         'output_buffering=Off',
                   49833:         'display_errors=1',
                   49834:         'log_errors=0',
                   49835:         'html_errors=0',
                   49836:         'track_errors=1',
                   49837:         'report_memleaks=0',
                   49838:         'report_zend_debug=0',
                   49839:         'docref_root=',
                   49840:         'docref_ext=.html',
                   49841:         'error_prepend_string=',
                   49842:         'error_append_string=',
                   49843:         'auto_prepend_file=',
                   49844:         'auto_append_file=',
                   49845:         'magic_quotes_runtime=0',
                   49846:         'xdebug.default_enable=0',
                   49847:         'allow_url_fopen=1',
                   49848:     );
                   49849: 
                   49850:     /**
                   49851:      * An object that supports the PEAR_Common->log() signature, or null
                   49852:      * @param PEAR_Common|null
                   49853:      */
                   49854:     function PEAR_RunTest($logger = null, $options = array())
                   49855:     {
                   49856:         if (!defined('E_DEPRECATED')) {
                   49857:             define('E_DEPRECATED', 0);
                   49858:         }
                   49859:         if (!defined('E_STRICT')) {
                   49860:             define('E_STRICT', 0);
                   49861:         }
                   49862:         $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
                   49863:         if (is_null($logger)) {
                   49864:             require_once 'PEAR/Common.php';
                   49865:             $logger = new PEAR_Common;
                   49866:         }
                   49867:         $this->_logger  = $logger;
                   49868:         $this->_options = $options;
                   49869: 
                   49870:         $conf = &PEAR_Config::singleton();
                   49871:         $this->_php = $conf->get('php_bin');
                   49872:     }
                   49873: 
                   49874:     /**
                   49875:      * Taken from php-src/run-tests.php
                   49876:      *
                   49877:      * @param string $commandline command name
                   49878:      * @param array $env
                   49879:      * @param string $stdin standard input to pass to the command
                   49880:      * @return unknown
                   49881:      */
                   49882:     function system_with_timeout($commandline, $env = null, $stdin = null)
                   49883:     {
                   49884:         $data = '';
                   49885:         if (version_compare(phpversion(), '5.0.0', '<')) {
                   49886:             $proc = proc_open($commandline, array(
                   49887:                 0 => array('pipe', 'r'),
                   49888:                 1 => array('pipe', 'w'),
                   49889:                 2 => array('pipe', 'w')
                   49890:                 ), $pipes);
                   49891:         } else {
                   49892:             $proc = proc_open($commandline, array(
                   49893:                 0 => array('pipe', 'r'),
                   49894:                 1 => array('pipe', 'w'),
                   49895:                 2 => array('pipe', 'w')
                   49896:                 ), $pipes, null, $env, array('suppress_errors' => true));
                   49897:         }
                   49898: 
                   49899:         if (!$proc) {
                   49900:             return false;
                   49901:         }
                   49902: 
                   49903:         if (is_string($stdin)) {
                   49904:             fwrite($pipes[0], $stdin);
                   49905:         }
                   49906:         fclose($pipes[0]);
                   49907: 
                   49908:         while (true) {
                   49909:             /* hide errors from interrupted syscalls */
                   49910:             $r = $pipes;
                   49911:             $e = $w = null;
                   49912:             $n = @stream_select($r, $w, $e, 60);
                   49913: 
                   49914:             if ($n === 0) {
                   49915:                 /* timed out */
                   49916:                 $data .= "\n ** ERROR: process timed out **\n";
                   49917:                 proc_terminate($proc);
                   49918:                 return array(1234567890, $data);
                   49919:             } else if ($n > 0) {
                   49920:                 $line = fread($pipes[1], 8192);
                   49921:                 if (strlen($line) == 0) {
                   49922:                     /* EOF */
                   49923:                     break;
                   49924:                 }
                   49925:                 $data .= $line;
                   49926:             }
                   49927:         }
                   49928:         if (function_exists('proc_get_status')) {
                   49929:             $stat = proc_get_status($proc);
                   49930:             if ($stat['signaled']) {
                   49931:                 $data .= "\nTermsig=".$stat['stopsig'];
                   49932:             }
                   49933:         }
                   49934:         $code = proc_close($proc);
                   49935:         if (function_exists('proc_get_status')) {
                   49936:             $code = $stat['exitcode'];
                   49937:         }
                   49938:         return array($code, $data);
                   49939:     }
                   49940: 
                   49941:     /**
                   49942:      * Turns a PHP INI string into an array
                   49943:      *
                   49944:      * Turns -d "include_path=/foo/bar" into this:
                   49945:      * array(
                   49946:      *   'include_path' => array(
                   49947:      *          'operator' => '-d',
                   49948:      *          'value'    => '/foo/bar',
                   49949:      *   )
                   49950:      * )
                   49951:      * Works both with quotes and without
                   49952:      *
                   49953:      * @param string an PHP INI string, -d "include_path=/foo/bar"
                   49954:      * @return array
                   49955:      */
                   49956:     function iniString2array($ini_string)
                   49957:     {
                   49958:         if (!$ini_string) {
                   49959:             return array();
                   49960:         }
                   49961:         $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
                   49962:         $key   = $split[1][0] == '"'                     ? substr($split[1], 1)     : $split[1];
                   49963:         $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
                   49964:         // FIXME review if this is really the struct to go with
                   49965:         $array = array($key => array('operator' => $split[0], 'value' => $value));
                   49966:         return $array;
                   49967:     }
                   49968: 
                   49969:     function settings2array($settings, $ini_settings)
                   49970:     {
                   49971:         foreach ($settings as $setting) {
                   49972:             if (strpos($setting, '=') !== false) {
                   49973:                 $setting = explode('=', $setting, 2);
                   49974:                 $name  = trim(strtolower($setting[0]));
                   49975:                 $value = trim($setting[1]);
                   49976:                 $ini_settings[$name] = $value;
                   49977:             }
                   49978:         }
                   49979:         return $ini_settings;
                   49980:     }
                   49981: 
                   49982:     function settings2params($ini_settings)
                   49983:     {
                   49984:         $settings = '';
                   49985:         foreach ($ini_settings as $name => $value) {
                   49986:             if (is_array($value)) {
                   49987:                 $operator = $value['operator'];
                   49988:                 $value    = $value['value'];
                   49989:             } else {
                   49990:                 $operator = '-d';
                   49991:             }
                   49992:             $value = addslashes($value);
                   49993:             $settings .= " $operator \"$name=$value\"";
                   49994:         }
                   49995:         return $settings;
                   49996:     }
                   49997: 
                   49998:     function _preparePhpBin($php, $file, $ini_settings)
                   49999:     {
                   50000:         $file = escapeshellarg($file);
                   50001:         // This was fixed in php 5.3 and is not needed after that
                   50002:         if (OS_WINDOWS && version_compare(PHP_VERSION, '5.3', '<')) {
                   50003:             $cmd = '"'.escapeshellarg($php).' '.$ini_settings.' -f ' . $file .'"';
                   50004:         } else {
                   50005:             $cmd = $php . $ini_settings . ' -f ' . $file;
                   50006:         }
                   50007: 
                   50008:         return $cmd;
                   50009:     }
                   50010: 
                   50011:     function runPHPUnit($file, $ini_settings = '')
                   50012:     {
                   50013:         if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
                   50014:             $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
                   50015:         } elseif (file_exists($file)) {
                   50016:             $file = realpath($file);
                   50017:         }
                   50018: 
                   50019:         $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
                   50020:         if (isset($this->_logger)) {
                   50021:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
                   50022:         }
                   50023: 
                   50024:         $savedir = getcwd(); // in case the test moves us around
                   50025:         chdir(dirname($file));
                   50026:         echo `$cmd`;
                   50027:         chdir($savedir);
                   50028:         return 'PASSED'; // we have no way of knowing this information so assume passing
                   50029:     }
                   50030: 
                   50031:     /**
                   50032:      * Runs an individual test case.
                   50033:      *
                   50034:      * @param string       The filename of the test
                   50035:      * @param array|string INI settings to be applied to the test run
                   50036:      * @param integer      Number what the current running test is of the
                   50037:      *                     whole test suite being runned.
                   50038:      *
                   50039:      * @return string|object Returns PASSED, WARNED, FAILED depending on how the
                   50040:      *                       test came out.
                   50041:      *                       PEAR Error when the tester it self fails
                   50042:      */
                   50043:     function run($file, $ini_settings = array(), $test_number = 1)
                   50044:     {
                   50045:         if (isset($this->_savephp)) {
                   50046:             $this->_php = $this->_savephp;
                   50047:             unset($this->_savephp);
                   50048:         }
                   50049:         if (empty($this->_options['cgi'])) {
                   50050:             // try to see if php-cgi is in the path
                   50051:             $res = $this->system_with_timeout('php-cgi -v');
                   50052:             if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
                   50053:                 $this->_options['cgi'] = 'php-cgi';
                   50054:             }
                   50055:         }
                   50056:         if (1 < $len = strlen($this->tests_count)) {
                   50057:             $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
                   50058:             $test_nr = "[$test_number/$this->tests_count] ";
                   50059:         } else {
                   50060:             $test_nr = '';
                   50061:         }
                   50062: 
                   50063:         $file = realpath($file);
                   50064:         $section_text = $this->_readFile($file);
                   50065:         if (PEAR::isError($section_text)) {
                   50066:             return $section_text;
                   50067:         }
                   50068: 
                   50069:         if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
                   50070:             return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
                   50071:         }
                   50072: 
                   50073:         $cwd = getcwd();
                   50074: 
                   50075:         $pass_options = '';
                   50076:         if (!empty($this->_options['ini'])) {
                   50077:             $pass_options = $this->_options['ini'];
                   50078:         }
                   50079: 
                   50080:         if (is_string($ini_settings)) {
                   50081:             $ini_settings = $this->iniString2array($ini_settings);
                   50082:         }
                   50083: 
                   50084:         $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
                   50085:         if ($section_text['INI']) {
                   50086:             if (strpos($section_text['INI'], '{PWD}') !== false) {
                   50087:                 $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
                   50088:             }
                   50089:             $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
                   50090:             $ini_settings = $this->settings2array($ini, $ini_settings);
                   50091:         }
                   50092:         $ini_settings = $this->settings2params($ini_settings);
                   50093:         $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
                   50094: 
                   50095:         $tested = trim($section_text['TEST']);
                   50096:         $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
                   50097: 
                   50098:         if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
                   50099:               !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
                   50100:               !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
                   50101:             if (empty($this->_options['cgi'])) {
                   50102:                 if (!isset($this->_options['quiet'])) {
                   50103:                     $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
                   50104:                 }
                   50105:                 if (isset($this->_options['tapoutput'])) {
                   50106:                     return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
                   50107:                 }
                   50108:                 return 'SKIPPED';
                   50109:             }
                   50110:             $this->_savephp = $this->_php;
                   50111:             $this->_php = $this->_options['cgi'];
                   50112:         }
                   50113: 
                   50114:         $temp_dir = realpath(dirname($file));
                   50115:         $main_file_name = basename($file, 'phpt');
                   50116:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
                   50117:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
                   50118:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
                   50119:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
                   50120:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
                   50121:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
                   50122:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
                   50123:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
                   50124:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
                   50125: 
                   50126:         // unlink old test results
                   50127:         $this->_cleanupOldFiles($file);
                   50128: 
                   50129:         // Check if test should be skipped.
                   50130:         $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
                   50131:         if (count($res) != 2) {
                   50132:             return $res;
                   50133:         }
                   50134:         $info = $res['info'];
                   50135:         $warn = $res['warn'];
                   50136: 
                   50137:         // We've satisfied the preconditions - run the test!
                   50138:         if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
                   50139:             $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
                   50140:             $text = "\n" . 'function coverage_shutdown() {' .
                   50141:                     "\n" . '    $xdebug = var_export(xdebug_get_code_coverage(), true);';
                   50142:             if (!function_exists('file_put_contents')) {
                   50143:                 $text .= "\n" . '    $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
                   50144:                         "\n" . '    if ($fh !== false) {' .
                   50145:                         "\n" . '        fwrite($fh, $xdebug);' .
                   50146:                         "\n" . '        fclose($fh);' .
                   50147:                         "\n" . '    }';
                   50148:             } else {
                   50149:                 $text .= "\n" . '    file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
                   50150:             }
                   50151: 
                   50152:             // Workaround for http://pear.php.net/bugs/bug.php?id=17292
                   50153:             $lines             = explode("\n", $section_text['FILE']);
                   50154:             $numLines          = count($lines);
                   50155:             $namespace         = '';
                   50156:             $coverage_shutdown = 'coverage_shutdown';
                   50157: 
                   50158:             if (
                   50159:                 substr($lines[0], 0, 2) == '<?' ||
                   50160:                 substr($lines[0], 0, 5) == '<?php'
                   50161:             ) {
                   50162:                 unset($lines[0]);
                   50163:             }
                   50164: 
                   50165: 
                   50166:             for ($i = 0; $i < $numLines; $i++) {
                   50167:                 if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
                   50168:                     $namespace         = substr($lines[$i], 10, -1);
                   50169:                     $coverage_shutdown = $namespace . '\\coverage_shutdown';
                   50170:                     $namespace         = "namespace " . $namespace . ";\n";
                   50171: 
                   50172:                     unset($lines[$i]);
                   50173:                     break;
                   50174:                 }
                   50175:             }
                   50176: 
                   50177:             $text .= "\n    xdebug_stop_code_coverage();" .
                   50178:                 "\n" . '} // end coverage_shutdown()' .
                   50179:                 "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
                   50180:             $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
                   50181: 
                   50182:             $this->save_text($temp_file, "<?php\n" . $namespace . $text  . "\n" . implode("\n", $lines));
                   50183:         } else {
                   50184:             $this->save_text($temp_file, $section_text['FILE']);
                   50185:         }
                   50186: 
                   50187:         $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
                   50188:         $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
                   50189:         $cmd.= "$args 2>&1";
                   50190:         if (isset($this->_logger)) {
                   50191:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
                   50192:         }
                   50193: 
                   50194:         // Reset environment from any previous test.
                   50195:         $env = $this->_resetEnv($section_text, $temp_file);
                   50196: 
                   50197:         $section_text = $this->_processUpload($section_text, $file);
                   50198:         if (PEAR::isError($section_text)) {
                   50199:             return $section_text;
                   50200:         }
                   50201: 
                   50202:         if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
                   50203:             $post = trim($section_text['POST_RAW']);
                   50204:             $raw_lines = explode("\n", $post);
                   50205: 
                   50206:             $request = '';
                   50207:             $started = false;
                   50208:             foreach ($raw_lines as $i => $line) {
                   50209:                 if (empty($env['CONTENT_TYPE']) &&
                   50210:                     preg_match('/^Content-Type:(.*)/i', $line, $res)) {
                   50211:                     $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
                   50212:                     continue;
                   50213:                 }
                   50214:                 if ($started) {
                   50215:                     $request .= "\n";
                   50216:                 }
                   50217:                 $started = true;
                   50218:                 $request .= $line;
                   50219:             }
                   50220: 
                   50221:             $env['CONTENT_LENGTH'] = strlen($request);
                   50222:             $env['REQUEST_METHOD'] = 'POST';
                   50223: 
                   50224:             $this->save_text($tmp_post, $request);
                   50225:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
                   50226:         } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                   50227:             $post = trim($section_text['POST']);
                   50228:             $this->save_text($tmp_post, $post);
                   50229:             $content_length = strlen($post);
                   50230: 
                   50231:             $env['REQUEST_METHOD'] = 'POST';
                   50232:             $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
                   50233:             $env['CONTENT_LENGTH'] = $content_length;
                   50234: 
                   50235:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
                   50236:         } else {
                   50237:             $env['REQUEST_METHOD'] = 'GET';
                   50238:             $env['CONTENT_TYPE']   = '';
                   50239:             $env['CONTENT_LENGTH'] = '';
                   50240:         }
                   50241: 
                   50242:         if (OS_WINDOWS && isset($section_text['RETURNS'])) {
                   50243:             ob_start();
                   50244:             system($cmd, $return_value);
                   50245:             $out = ob_get_contents();
                   50246:             ob_end_clean();
                   50247:             $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
                   50248:             $returnfail = ($return_value != $section_text['RETURNS']);
                   50249:         } else {
                   50250:             $returnfail = false;
                   50251:             $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
                   50252:             $out = $this->system_with_timeout($cmd, $env, $stdin);
                   50253:             $return_value = $out[0];
                   50254:             $out = $out[1];
                   50255:         }
                   50256: 
                   50257:         $output = preg_replace('/\r\n/', "\n", trim($out));
                   50258: 
                   50259:         if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
                   50260:             @unlink(realpath($tmp_post));
                   50261:         }
                   50262:         chdir($cwd); // in case the test moves us around
                   50263: 
                   50264:         $this->_testCleanup($section_text, $temp_clean);
                   50265: 
                   50266:         /* when using CGI, strip the headers from the output */
                   50267:         $output = $this->_stripHeadersCGI($output);
                   50268: 
                   50269:         if (isset($section_text['EXPECTHEADERS'])) {
                   50270:             $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
                   50271:             $missing = array_diff_assoc($testheaders, $this->_headers);
                   50272:             $changed = '';
                   50273:             foreach ($missing as $header => $value) {
                   50274:                 if (isset($this->_headers[$header])) {
                   50275:                     $changed .= "-$header: $value\n+$header: ";
                   50276:                     $changed .= $this->_headers[$header];
                   50277:                 } else {
                   50278:                     $changed .= "-$header: $value\n";
                   50279:                 }
                   50280:             }
                   50281:             if ($missing) {
                   50282:                 // tack on failed headers to output:
                   50283:                 $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
                   50284:             }
                   50285:         }
                   50286:         // Does the output match what is expected?
                   50287:         do {
                   50288:             if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
                   50289:                 if (isset($section_text['EXPECTF'])) {
                   50290:                     $wanted = trim($section_text['EXPECTF']);
                   50291:                 } else {
                   50292:                     $wanted = trim($section_text['EXPECTREGEX']);
                   50293:                 }
                   50294:                 $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
                   50295:                 if (isset($section_text['EXPECTF'])) {
                   50296:                     $wanted_re = preg_quote($wanted_re, '/');
                   50297:                     // Stick to basics
                   50298:                     $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
                   50299:                     $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
                   50300:                     $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
                   50301:                     $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
                   50302:                     $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
                   50303:                     $wanted_re = str_replace("%c", ".", $wanted_re);
                   50304:                     // %f allows two points "-.0.0" but that is the best *simple* expression
                   50305:                 }
                   50306: 
                   50307:     /* DEBUG YOUR REGEX HERE
                   50308:             var_dump($wanted_re);
                   50309:             print(str_repeat('=', 80) . "\n");
                   50310:             var_dump($output);
                   50311:     */
                   50312:                 if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
                   50313:                     if (file_exists($temp_file)) {
                   50314:                         unlink($temp_file);
                   50315:                     }
                   50316:                     if (array_key_exists('FAIL', $section_text)) {
                   50317:                         break;
                   50318:                     }
                   50319:                     if (!isset($this->_options['quiet'])) {
                   50320:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50321:                     }
                   50322:                     if (isset($this->_options['tapoutput'])) {
                   50323:                         return array('ok', ' - ' . $tested);
                   50324:                     }
                   50325:                     return 'PASSED';
                   50326:                 }
                   50327:             } else {
                   50328:                 if (isset($section_text['EXPECTFILE'])) {
                   50329:                     $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
                   50330:                     if (!($fp = @fopen($f, 'rb'))) {
                   50331:                         return PEAR::raiseError('--EXPECTFILE-- section file ' .
                   50332:                             $f . ' not found');
                   50333:                     }
                   50334:                     fclose($fp);
                   50335:                     $section_text['EXPECT'] = file_get_contents($f);
                   50336:                 }
                   50337: 
                   50338:                 if (isset($section_text['EXPECT'])) {
                   50339:                     $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
                   50340:                 } else {
                   50341:                     $wanted = '';
                   50342:                 }
                   50343: 
                   50344:                 // compare and leave on success
                   50345:                 if (!$returnfail && 0 == strcmp($output, $wanted)) {
                   50346:                     if (file_exists($temp_file)) {
                   50347:                         unlink($temp_file);
                   50348:                     }
                   50349:                     if (array_key_exists('FAIL', $section_text)) {
                   50350:                         break;
                   50351:                     }
                   50352:                     if (!isset($this->_options['quiet'])) {
                   50353:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50354:                     }
                   50355:                     if (isset($this->_options['tapoutput'])) {
                   50356:                         return array('ok', ' - ' . $tested);
                   50357:                     }
                   50358:                     return 'PASSED';
                   50359:                 }
                   50360:             }
                   50361:         } while (false);
                   50362: 
                   50363:         if (array_key_exists('FAIL', $section_text)) {
                   50364:             // we expect a particular failure
                   50365:             // this is only used for testing PEAR_RunTest
                   50366:             $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
                   50367:             $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
                   50368:             $faildiff = preg_replace('/\r/', '', $faildiff);
                   50369:             $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
                   50370:             if ($faildiff == $wanted) {
                   50371:                 if (!isset($this->_options['quiet'])) {
                   50372:                     $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50373:                 }
                   50374:                 if (isset($this->_options['tapoutput'])) {
                   50375:                     return array('ok', ' - ' . $tested);
                   50376:                 }
                   50377:                 return 'PASSED';
                   50378:             }
                   50379:             unset($section_text['EXPECTF']);
                   50380:             $output = $faildiff;
                   50381:             if (isset($section_text['RETURNS'])) {
                   50382:                 return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
                   50383:                     $file);
                   50384:             }
                   50385:         }
                   50386: 
                   50387:         // Test failed so we need to report details.
                   50388:         $txt = $warn ? 'WARN ' : 'FAIL ';
                   50389:         $this->_logger->log(0, $txt . $test_nr . $tested . $info);
                   50390: 
                   50391:         // write .exp
                   50392:         $res = $this->_writeLog($exp_filename, $wanted);
                   50393:         if (PEAR::isError($res)) {
                   50394:             return $res;
                   50395:         }
                   50396: 
                   50397:         // write .out
                   50398:         $res = $this->_writeLog($output_filename, $output);
                   50399:         if (PEAR::isError($res)) {
                   50400:             return $res;
                   50401:         }
                   50402: 
                   50403:         // write .diff
                   50404:         $returns = isset($section_text['RETURNS']) ?
                   50405:                         array(trim($section_text['RETURNS']), $return_value) : null;
                   50406:         $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
                   50407:         $data = $this->generate_diff($wanted, $output, $returns, $expectf);
                   50408:         $res  = $this->_writeLog($diff_filename, $data);
                   50409:         if (PEAR::isError($res)) {
                   50410:             return $res;
                   50411:         }
                   50412: 
                   50413:         // write .log
                   50414:         $data = "
                   50415: ---- EXPECTED OUTPUT
                   50416: $wanted
                   50417: ---- ACTUAL OUTPUT
                   50418: $output
                   50419: ---- FAILED
                   50420: ";
                   50421: 
                   50422:         if ($returnfail) {
                   50423:             $data .= "
                   50424: ---- EXPECTED RETURN
                   50425: $section_text[RETURNS]
                   50426: ---- ACTUAL RETURN
                   50427: $return_value
                   50428: ";
                   50429:         }
                   50430: 
                   50431:         $res = $this->_writeLog($log_filename, $data);
                   50432:         if (PEAR::isError($res)) {
                   50433:             return $res;
                   50434:         }
                   50435: 
                   50436:         if (isset($this->_options['tapoutput'])) {
                   50437:             $wanted = explode("\n", $wanted);
                   50438:             $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
                   50439:             $output = explode("\n", $output);
                   50440:             $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
                   50441:             return array($wanted . $output . 'not ok', ' - ' . $tested);
                   50442:         }
                   50443:         return $warn ? 'WARNED' : 'FAILED';
                   50444:     }
                   50445: 
                   50446:     function generate_diff($wanted, $output, $rvalue, $wanted_re)
                   50447:     {
                   50448:         $w  = explode("\n", $wanted);
                   50449:         $o  = explode("\n", $output);
                   50450:         $wr = explode("\n", $wanted_re);
                   50451:         $w1 = array_diff_assoc($w, $o);
                   50452:         $o1 = array_diff_assoc($o, $w);
                   50453:         $o2 = $w2 = array();
                   50454:         foreach ($w1 as $idx => $val) {
                   50455:             if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
                   50456:                   !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
                   50457:                 $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
                   50458:             }
                   50459:         }
                   50460:         foreach ($o1 as $idx => $val) {
                   50461:             if (!$wanted_re || !isset($wr[$idx]) ||
                   50462:                   !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
                   50463:                 $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
                   50464:             }
                   50465:         }
                   50466:         $diff = array_merge($w2, $o2);
                   50467:         ksort($diff);
                   50468:         $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
                   50469:         return implode("\r\n", $diff) . $extra;
                   50470:     }
                   50471: 
                   50472:     //  Write the given text to a temporary file, and return the filename.
                   50473:     function save_text($filename, $text)
                   50474:     {
                   50475:         if (!$fp = fopen($filename, 'w')) {
                   50476:             return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
                   50477:         }
                   50478:         fwrite($fp, $text);
                   50479:         fclose($fp);
                   50480:     if (1 < DETAILED) echo "
                   50481: FILE $filename {{{
                   50482: $text
                   50483: }}}
                   50484: ";
                   50485:     }
                   50486: 
                   50487:     function _cleanupOldFiles($file)
                   50488:     {
                   50489:         $temp_dir = realpath(dirname($file));
                   50490:         $mainFileName = basename($file, 'phpt');
                   50491:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
                   50492:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
                   50493:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
                   50494:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
                   50495:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
                   50496:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
                   50497:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
                   50498:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
                   50499:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
                   50500: 
                   50501:         // unlink old test results
                   50502:         @unlink($diff_filename);
                   50503:         @unlink($log_filename);
                   50504:         @unlink($exp_filename);
                   50505:         @unlink($output_filename);
                   50506:         @unlink($memcheck_filename);
                   50507:         @unlink($temp_file);
                   50508:         @unlink($temp_skipif);
                   50509:         @unlink($tmp_post);
                   50510:         @unlink($temp_clean);
                   50511:     }
                   50512: 
                   50513:     function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
                   50514:     {
                   50515:         $info = '';
                   50516:         $warn = false;
                   50517:         if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
                   50518:             $this->save_text($temp_skipif, $section_text['SKIPIF']);
                   50519:             $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
                   50520:             $output = $output[1];
                   50521:             $loutput = ltrim($output);
                   50522:             unlink($temp_skipif);
                   50523:             if (!strncasecmp('skip', $loutput, 4)) {
                   50524:                 $skipreason = "SKIP $tested";
                   50525:                 if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
                   50526:                     $skipreason .= '(reason: ' . $m[1] . ')';
                   50527:                 }
                   50528:                 if (!isset($this->_options['quiet'])) {
                   50529:                     $this->_logger->log(0, $skipreason);
                   50530:                 }
                   50531:                 if (isset($this->_options['tapoutput'])) {
                   50532:                     return array('ok', ' # skip ' . $reason);
                   50533:                 }
                   50534:                 return 'SKIPPED';
                   50535:             }
                   50536: 
                   50537:             if (!strncasecmp('info', $loutput, 4)
                   50538:                 && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
                   50539:                 $info = " (info: $m[1])";
                   50540:             }
                   50541: 
                   50542:             if (!strncasecmp('warn', $loutput, 4)
                   50543:                 && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
                   50544:                 $warn = true; /* only if there is a reason */
                   50545:                 $info = " (warn: $m[1])";
                   50546:             }
                   50547:         }
                   50548: 
                   50549:         return array('warn' => $warn, 'info' => $info);
                   50550:     }
                   50551: 
                   50552:     function _stripHeadersCGI($output)
                   50553:     {
                   50554:         $this->headers = array();
                   50555:         if (!empty($this->_options['cgi']) &&
                   50556:               $this->_php == $this->_options['cgi'] &&
                   50557:               preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
                   50558:             $output = isset($match[2]) ? trim($match[2]) : '';
                   50559:             $this->_headers = $this->_processHeaders($match[1]);
                   50560:         }
                   50561: 
                   50562:         return $output;
                   50563:     }
                   50564: 
                   50565:     /**
                   50566:      * Return an array that can be used with array_diff() to compare headers
                   50567:      *
                   50568:      * @param string $text
                   50569:      */
                   50570:     function _processHeaders($text)
                   50571:     {
                   50572:         $headers = array();
                   50573:         $rh = preg_split("/[\n\r]+/", $text);
                   50574:         foreach ($rh as $line) {
                   50575:             if (strpos($line, ':')!== false) {
                   50576:                 $line = explode(':', $line, 2);
                   50577:                 $headers[trim($line[0])] = trim($line[1]);
                   50578:             }
                   50579:         }
                   50580:         return $headers;
                   50581:     }
                   50582: 
                   50583:     function _readFile($file)
                   50584:     {
                   50585:         // Load the sections of the test file.
                   50586:         $section_text = array(
                   50587:             'TEST'   => '(unnamed test)',
                   50588:             'SKIPIF' => '',
                   50589:             'GET'    => '',
                   50590:             'COOKIE' => '',
                   50591:             'POST'   => '',
                   50592:             'ARGS'   => '',
                   50593:             'INI'    => '',
                   50594:             'CLEAN'  => '',
                   50595:         );
                   50596: 
                   50597:         if (!is_file($file) || !$fp = fopen($file, "r")) {
                   50598:             return PEAR::raiseError("Cannot open test file: $file");
                   50599:         }
                   50600: 
                   50601:         $section = '';
                   50602:         while (!feof($fp)) {
                   50603:             $line = fgets($fp);
                   50604: 
                   50605:             // Match the beginning of a section.
                   50606:             if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
                   50607:                 $section = $r[1];
                   50608:                 $section_text[$section] = '';
                   50609:                 continue;
                   50610:             } elseif (empty($section)) {
                   50611:                 fclose($fp);
                   50612:                 return PEAR::raiseError("Invalid sections formats in test file: $file");
                   50613:             }
                   50614: 
                   50615:             // Add to the section text.
                   50616:             $section_text[$section] .= $line;
                   50617:         }
                   50618:         fclose($fp);
                   50619: 
                   50620:         return $section_text;
                   50621:     }
                   50622: 
                   50623:     function _writeLog($logname, $data)
                   50624:     {
                   50625:         if (!$log = fopen($logname, 'w')) {
                   50626:             return PEAR::raiseError("Cannot create test log - $logname");
                   50627:         }
                   50628:         fwrite($log, $data);
                   50629:         fclose($log);
                   50630:     }
                   50631: 
                   50632:     function _resetEnv($section_text, $temp_file)
                   50633:     {
                   50634:         $env = $_ENV;
                   50635:         $env['REDIRECT_STATUS'] = '';
                   50636:         $env['QUERY_STRING']    = '';
                   50637:         $env['PATH_TRANSLATED'] = '';
                   50638:         $env['SCRIPT_FILENAME'] = '';
                   50639:         $env['REQUEST_METHOD']  = '';
                   50640:         $env['CONTENT_TYPE']    = '';
                   50641:         $env['CONTENT_LENGTH']  = '';
                   50642:         if (!empty($section_text['ENV'])) {
                   50643:             if (strpos($section_text['ENV'], '{PWD}') !== false) {
                   50644:                 $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
                   50645:             }
                   50646:             foreach (explode("\n", trim($section_text['ENV'])) as $e) {
                   50647:                 $e = explode('=', trim($e), 2);
                   50648:                 if (!empty($e[0]) && isset($e[1])) {
                   50649:                     $env[$e[0]] = $e[1];
                   50650:                 }
                   50651:             }
                   50652:         }
                   50653:         if (array_key_exists('GET', $section_text)) {
                   50654:             $env['QUERY_STRING'] = trim($section_text['GET']);
                   50655:         } else {
                   50656:             $env['QUERY_STRING'] = '';
                   50657:         }
                   50658:         if (array_key_exists('COOKIE', $section_text)) {
                   50659:             $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
                   50660:         } else {
                   50661:             $env['HTTP_COOKIE'] = '';
                   50662:         }
                   50663:         $env['REDIRECT_STATUS'] = '1';
                   50664:         $env['PATH_TRANSLATED'] = $temp_file;
                   50665:         $env['SCRIPT_FILENAME'] = $temp_file;
                   50666: 
                   50667:         return $env;
                   50668:     }
                   50669: 
                   50670:     function _processUpload($section_text, $file)
                   50671:     {
                   50672:         if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
                   50673:             $upload_files = trim($section_text['UPLOAD']);
                   50674:             $upload_files = explode("\n", $upload_files);
                   50675: 
                   50676:             $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
                   50677:                        "-----------------------------20896060251896012921717172737\n";
                   50678:             foreach ($upload_files as $fileinfo) {
                   50679:                 $fileinfo = explode('=', $fileinfo);
                   50680:                 if (count($fileinfo) != 2) {
                   50681:                     return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
                   50682:                 }
                   50683:                 if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
                   50684:                     return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
                   50685:                         "in test file: $file");
                   50686:                 }
                   50687:                 $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
                   50688:                 $fileinfo[1] = basename($fileinfo[1]);
                   50689:                 $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
                   50690:                 $request .= "Content-Type: text/plain\n\n";
                   50691:                 $request .= $file_contents . "\n" .
                   50692:                     "-----------------------------20896060251896012921717172737\n";
                   50693:             }
                   50694: 
                   50695:             if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                   50696:                 // encode POST raw
                   50697:                 $post = trim($section_text['POST']);
                   50698:                 $post = explode('&', $post);
                   50699:                 foreach ($post as $i => $post_info) {
                   50700:                     $post_info = explode('=', $post_info);
                   50701:                     if (count($post_info) != 2) {
                   50702:                         return PEAR::raiseError("Invalid POST data in test file: $file");
                   50703:                     }
                   50704:                     $post_info[0] = rawurldecode($post_info[0]);
                   50705:                     $post_info[1] = rawurldecode($post_info[1]);
                   50706:                     $post[$i] = $post_info;
                   50707:                 }
                   50708:                 foreach ($post as $post_info) {
                   50709:                     $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
                   50710:                     $request .= $post_info[1] . "\n" .
                   50711:                         "-----------------------------20896060251896012921717172737\n";
                   50712:                 }
                   50713:                 unset($section_text['POST']);
                   50714:             }
                   50715:             $section_text['POST_RAW'] = $request;
                   50716:         }
                   50717: 
                   50718:         return $section_text;
                   50719:     }
                   50720: 
                   50721:     function _testCleanup($section_text, $temp_clean)
                   50722:     {
                   50723:         if ($section_text['CLEAN']) {
                   50724:             // perform test cleanup
                   50725:             $this->save_text($temp_clean, $section_text['CLEAN']);
                   50726:             $output = $this->system_with_timeout("$this->_php $temp_clean  2>&1");
                   50727:             if (strlen($output[1])) {
                   50728:                 echo "BORKED --CLEAN-- section! output:\n", $output[1];
                   50729:             }
                   50730:             if (file_exists($temp_clean)) {
                   50731:                 unlink($temp_clean);
                   50732:             }
                   50733:         }
                   50734:     }
                   50735: }
                   50736: PEAR-1.9.4/PEAR/Validate.php0000644000076500000240000005305511605156760014237 0ustar  helgistaff<?php
                   50737: /**
                   50738:  * PEAR_Validate
                   50739:  *
                   50740:  * PHP versions 4 and 5
                   50741:  *
                   50742:  * @category   pear
                   50743:  * @package    PEAR
                   50744:  * @author     Greg Beaver <cellog@php.net>
                   50745:  * @copyright  1997-2009 The Authors
                   50746:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   50747:  * @version    CVS: $Id: Validate.php 313023 2011-07-06 19:17:11Z dufuz $
                   50748:  * @link       http://pear.php.net/package/PEAR
                   50749:  * @since      File available since Release 1.4.0a1
                   50750:  */
                   50751: /**#@+
                   50752:  * Constants for install stage
                   50753:  */
                   50754: define('PEAR_VALIDATE_INSTALLING', 1);
                   50755: define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
                   50756: define('PEAR_VALIDATE_NORMAL', 3);
                   50757: define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
                   50758: define('PEAR_VALIDATE_PACKAGING', 7);
                   50759: /**#@-*/
                   50760: require_once 'PEAR/Common.php';
                   50761: require_once 'PEAR/Validator/PECL.php';
                   50762: 
                   50763: /**
                   50764:  * Validation class for package.xml - channel-level advanced validation
                   50765:  * @category   pear
                   50766:  * @package    PEAR
                   50767:  * @author     Greg Beaver <cellog@php.net>
                   50768:  * @copyright  1997-2009 The Authors
                   50769:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   50770:  * @version    Release: 1.9.4
                   50771:  * @link       http://pear.php.net/package/PEAR
                   50772:  * @since      Class available since Release 1.4.0a1
                   50773:  */
                   50774: class PEAR_Validate
                   50775: {
                   50776:     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
                   50777:     /**
                   50778:      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   50779:      */
                   50780:     var $_packagexml;
                   50781:     /**
                   50782:      * @var int one of the PEAR_VALIDATE_* constants
                   50783:      */
                   50784:     var $_state = PEAR_VALIDATE_NORMAL;
                   50785:     /**
                   50786:      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
                   50787:      * @var array
                   50788:      * @access private
                   50789:      */
                   50790:     var $_failures = array('error' => array(), 'warning' => array());
                   50791: 
                   50792:     /**
                   50793:      * Override this method to handle validation of normal package names
                   50794:      * @param string
                   50795:      * @return bool
                   50796:      * @access protected
                   50797:      */
                   50798:     function _validPackageName($name)
                   50799:     {
                   50800:         return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
                   50801:     }
                   50802: 
                   50803:     /**
                   50804:      * @param string package name to validate
                   50805:      * @param string name of channel-specific validation package
                   50806:      * @final
                   50807:      */
                   50808:     function validPackageName($name, $validatepackagename = false)
                   50809:     {
                   50810:         if ($validatepackagename) {
                   50811:             if (strtolower($name) == strtolower($validatepackagename)) {
                   50812:                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
                   50813:             }
                   50814:         }
                   50815:         return $this->_validPackageName($name);
                   50816:     }
                   50817: 
                   50818:     /**
                   50819:      * This validates a bundle name, and bundle names must conform
                   50820:      * to the PEAR naming convention, so the method is final and static.
                   50821:      * @param string
                   50822:      * @final
                   50823:      * @static
                   50824:      */
                   50825:     function validGroupName($name)
                   50826:     {
                   50827:         return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
                   50828:     }
                   50829: 
                   50830:     /**
                   50831:      * Determine whether $state represents a valid stability level
                   50832:      * @param string
                   50833:      * @return bool
                   50834:      * @static
                   50835:      * @final
                   50836:      */
                   50837:     function validState($state)
                   50838:     {
                   50839:         return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
                   50840:     }
                   50841: 
                   50842:     /**
                   50843:      * Get a list of valid stability levels
                   50844:      * @return array
                   50845:      * @static
                   50846:      * @final
                   50847:      */
                   50848:     function getValidStates()
                   50849:     {
                   50850:         return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   50851:     }
                   50852: 
                   50853:     /**
                   50854:      * Determine whether a version is a properly formatted version number that can be used
                   50855:      * by version_compare
                   50856:      * @param string
                   50857:      * @return bool
                   50858:      * @static
                   50859:      * @final
                   50860:      */
                   50861:     function validVersion($ver)
                   50862:     {
                   50863:         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   50864:     }
                   50865: 
                   50866:     /**
                   50867:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   50868:      */
                   50869:     function setPackageFile(&$pf)
                   50870:     {
                   50871:         $this->_packagexml = &$pf;
                   50872:     }
                   50873: 
                   50874:     /**
                   50875:      * @access private
                   50876:      */
                   50877:     function _addFailure($field, $reason)
                   50878:     {
                   50879:         $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
                   50880:     }
                   50881: 
                   50882:     /**
                   50883:      * @access private
                   50884:      */
                   50885:     function _addWarning($field, $reason)
                   50886:     {
                   50887:         $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
                   50888:     }
                   50889: 
                   50890:     function getFailures()
                   50891:     {
                   50892:         $failures = $this->_failures;
                   50893:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   50894:         return $failures;
                   50895:     }
                   50896: 
                   50897:     /**
                   50898:      * @param int one of the PEAR_VALIDATE_* constants
                   50899:      */
                   50900:     function validate($state = null)
                   50901:     {
                   50902:         if (!isset($this->_packagexml)) {
                   50903:             return false;
                   50904:         }
                   50905:         if ($state !== null) {
                   50906:             $this->_state = $state;
                   50907:         }
                   50908:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   50909:         $this->validatePackageName();
                   50910:         $this->validateVersion();
                   50911:         $this->validateMaintainers();
                   50912:         $this->validateDate();
                   50913:         $this->validateSummary();
                   50914:         $this->validateDescription();
                   50915:         $this->validateLicense();
                   50916:         $this->validateNotes();
                   50917:         if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
                   50918:             $this->validateState();
                   50919:             $this->validateFilelist();
                   50920:         } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   50921:                   $this->_packagexml->getPackagexmlVersion() == '2.1') {
                   50922:             $this->validateTime();
                   50923:             $this->validateStability();
                   50924:             $this->validateDeps();
                   50925:             $this->validateMainFilelist();
                   50926:             $this->validateReleaseFilelist();
                   50927:             //$this->validateGlobalTasks();
                   50928:             $this->validateChangelog();
                   50929:         }
                   50930:         return !((bool) count($this->_failures['errors']));
                   50931:     }
                   50932: 
                   50933:     /**
                   50934:      * @access protected
                   50935:      */
                   50936:     function validatePackageName()
                   50937:     {
                   50938:         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
                   50939:               $this->_state == PEAR_VALIDATE_NORMAL) {
                   50940:             if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   50941:                  $this->_packagexml->getPackagexmlVersion() == '2.1') &&
                   50942:                   $this->_packagexml->getExtends()) {
                   50943:                 $version = $this->_packagexml->getVersion() . '';
                   50944:                 $name = $this->_packagexml->getPackage();
                   50945:                 $test = array_shift($a = explode('.', $version));
                   50946:                 if ($test == '0') {
                   50947:                     return true;
                   50948:                 }
                   50949:                 $vlen = strlen($test);
                   50950:                 $majver = substr($name, strlen($name) - $vlen);
                   50951:                 while ($majver && !is_numeric($majver{0})) {
                   50952:                     $majver = substr($majver, 1);
                   50953:                 }
                   50954:                 if ($majver != $test) {
                   50955:                     $this->_addWarning('package', "package $name extends package " .
                   50956:                         $this->_packagexml->getExtends() . ' and so the name should ' .
                   50957:                         'have a postfix equal to the major version like "' .
                   50958:                         $this->_packagexml->getExtends() . $test . '"');
                   50959:                     return true;
                   50960:                 } elseif (substr($name, 0, strlen($name) - $vlen) !=
                   50961:                             $this->_packagexml->getExtends()) {
                   50962:                     $this->_addWarning('package', "package $name extends package " .
                   50963:                         $this->_packagexml->getExtends() . ' and so the name must ' .
                   50964:                         'be an extension like "' . $this->_packagexml->getExtends() .
                   50965:                         $test . '"');
                   50966:                     return true;
                   50967:                 }
                   50968:             }
                   50969:         }
                   50970:         if (!$this->validPackageName($this->_packagexml->getPackage())) {
                   50971:             $this->_addFailure('name', 'package name "' .
                   50972:                 $this->_packagexml->getPackage() . '" is invalid');
                   50973:             return false;
                   50974:         }
                   50975:     }
                   50976: 
                   50977:     /**
                   50978:      * @access protected
                   50979:      */
                   50980:     function validateVersion()
                   50981:     {
                   50982:         if ($this->_state != PEAR_VALIDATE_PACKAGING) {
                   50983:             if (!$this->validVersion($this->_packagexml->getVersion())) {
                   50984:                 $this->_addFailure('version',
                   50985:                     'Invalid version number "' . $this->_packagexml->getVersion() . '"');
                   50986:             }
                   50987:             return false;
                   50988:         }
                   50989:         $version = $this->_packagexml->getVersion();
                   50990:         $versioncomponents = explode('.', $version);
                   50991:         if (count($versioncomponents) != 3) {
                   50992:             $this->_addWarning('version',
                   50993:                 'A version number should have 3 decimals (x.y.z)');
                   50994:             return true;
                   50995:         }
                   50996:         $name = $this->_packagexml->getPackage();
                   50997:         // version must be based upon state
                   50998:         switch ($this->_packagexml->getState()) {
                   50999:             case 'snapshot' :
                   51000:                 return true;
                   51001:             case 'devel' :
                   51002:                 if ($versioncomponents[0] . 'a' == '0a') {
                   51003:                     return true;
                   51004:                 }
                   51005:                 if ($versioncomponents[0] == 0) {
                   51006:                     $versioncomponents[0] = '0';
                   51007:                     $this->_addWarning('version',
                   51008:                         'version "' . $version . '" should be "' .
                   51009:                         implode('.' ,$versioncomponents) . '"');
                   51010:                 } else {
                   51011:                     $this->_addWarning('version',
                   51012:                         'packages with devel stability must be < version 1.0.0');
                   51013:                 }
                   51014:                 return true;
                   51015:             break;
                   51016:             case 'alpha' :
                   51017:             case 'beta' :
                   51018:                 // check for a package that extends a package,
                   51019:                 // like Foo and Foo2
                   51020:                 if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   51021:                     if (substr($versioncomponents[2], 1, 2) == 'rc') {
                   51022:                         $this->_addFailure('version', 'Release Candidate versions ' .
                   51023:                             'must have capital RC, not lower-case rc');
                   51024:                         return false;
                   51025:                     }
                   51026:                 }
                   51027:                 if (!$this->_packagexml->getExtends()) {
                   51028:                     if ($versioncomponents[0] == '1') {
                   51029:                         if ($versioncomponents[2]{0} == '0') {
                   51030:                             if ($versioncomponents[2] == '0') {
                   51031:                                 // version 1.*.0000
                   51032:                                 $this->_addWarning('version',
                   51033:                                     'version 1.' . $versioncomponents[1] .
                   51034:                                         '.0 probably should not be alpha or beta');
                   51035:                                 return true;
                   51036:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   51037:                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
                   51038:                                 return true;
                   51039:                             } else {
                   51040:                                 // version 1.*.0
                   51041:                                 $this->_addWarning('version',
                   51042:                                     'version 1.' . $versioncomponents[1] .
                   51043:                                         '.0 probably should not be alpha or beta');
                   51044:                                 return true;
                   51045:                             }
                   51046:                         } else {
                   51047:                             $this->_addWarning('version',
                   51048:                                 'bugfix versions (1.3.x where x > 0) probably should ' .
                   51049:                                 'not be alpha or beta');
                   51050:                             return true;
                   51051:                         }
                   51052:                     } elseif ($versioncomponents[0] != '0') {
                   51053:                         $this->_addWarning('version',
                   51054:                             'major versions greater than 1 are not allowed for packages ' .
                   51055:                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
                   51056:                         return true;
                   51057:                     }
                   51058:                     if ($versioncomponents[0] . 'a' == '0a') {
                   51059:                         return true;
                   51060:                     }
                   51061:                     if ($versioncomponents[0] == 0) {
                   51062:                         $versioncomponents[0] = '0';
                   51063:                         $this->_addWarning('version',
                   51064:                             'version "' . $version . '" should be "' .
                   51065:                             implode('.' ,$versioncomponents) . '"');
                   51066:                     }
                   51067:                 } else {
                   51068:                     $vlen = strlen($versioncomponents[0] . '');
                   51069:                     $majver = substr($name, strlen($name) - $vlen);
                   51070:                     while ($majver && !is_numeric($majver{0})) {
                   51071:                         $majver = substr($majver, 1);
                   51072:                     }
                   51073:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   51074:                         $this->_addWarning('version', 'first version number "' .
                   51075:                             $versioncomponents[0] . '" must match the postfix of ' .
                   51076:                             'package name "' . $name . '" (' .
                   51077:                             $majver . ')');
                   51078:                         return true;
                   51079:                     }
                   51080:                     if ($versioncomponents[0] == $majver) {
                   51081:                         if ($versioncomponents[2]{0} == '0') {
                   51082:                             if ($versioncomponents[2] == '0') {
                   51083:                                 // version 2.*.0000
                   51084:                                 $this->_addWarning('version',
                   51085:                                     "version $majver." . $versioncomponents[1] .
                   51086:                                         '.0 probably should not be alpha or beta');
                   51087:                                 return false;
                   51088:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   51089:                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
                   51090:                                 return true;
                   51091:                             } else {
                   51092:                                 // version 2.*.0
                   51093:                                 $this->_addWarning('version',
                   51094:                                     "version $majver." . $versioncomponents[1] .
                   51095:                                         '.0 cannot be alpha or beta');
                   51096:                                 return true;
                   51097:                             }
                   51098:                         } else {
                   51099:                             $this->_addWarning('version',
                   51100:                                 "bugfix versions ($majver.x.y where y > 0) should " .
                   51101:                                 'not be alpha or beta');
                   51102:                             return true;
                   51103:                         }
                   51104:                     } elseif ($versioncomponents[0] != '0') {
                   51105:                         $this->_addWarning('version',
                   51106:                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
                   51107:                         return true;
                   51108:                     }
                   51109:                     if ($versioncomponents[0] . 'a' == '0a') {
                   51110:                         return true;
                   51111:                     }
                   51112:                     if ($versioncomponents[0] == 0) {
                   51113:                         $versioncomponents[0] = '0';
                   51114:                         $this->_addWarning('version',
                   51115:                             'version "' . $version . '" should be "' .
                   51116:                             implode('.' ,$versioncomponents) . '"');
                   51117:                     }
                   51118:                 }
                   51119:                 return true;
                   51120:             break;
                   51121:             case 'stable' :
                   51122:                 if ($versioncomponents[0] == '0') {
                   51123:                     $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
                   51124:                     'be stable');
                   51125:                     return true;
                   51126:                 }
                   51127:                 if (!is_numeric($versioncomponents[2])) {
                   51128:                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
                   51129:                           $versioncomponents[2])) {
                   51130:                         $this->_addWarning('version', 'version "' . $version . '" or any ' .
                   51131:                             'RC/beta/alpha version cannot be stable');
                   51132:                         return true;
                   51133:                     }
                   51134:                 }
                   51135:                 // check for a package that extends a package,
                   51136:                 // like Foo and Foo2
                   51137:                 if ($this->_packagexml->getExtends()) {
                   51138:                     $vlen = strlen($versioncomponents[0] . '');
                   51139:                     $majver = substr($name, strlen($name) - $vlen);
                   51140:                     while ($majver && !is_numeric($majver{0})) {
                   51141:                         $majver = substr($majver, 1);
                   51142:                     }
                   51143:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   51144:                         $this->_addWarning('version', 'first version number "' .
                   51145:                             $versioncomponents[0] . '" must match the postfix of ' .
                   51146:                             'package name "' . $name . '" (' .
                   51147:                             $majver . ')');
                   51148:                         return true;
                   51149:                     }
                   51150:                 } elseif ($versioncomponents[0] > 1) {
                   51151:                     $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
                   51152:                         '1 for any package that does not have an <extends> tag');
                   51153:                 }
                   51154:                 return true;
                   51155:             break;
                   51156:             default :
                   51157:                 return false;
                   51158:             break;
                   51159:         }
                   51160:     }
                   51161: 
                   51162:     /**
                   51163:      * @access protected
                   51164:      */
                   51165:     function validateMaintainers()
                   51166:     {
                   51167:         // maintainers can only be truly validated server-side for most channels
                   51168:         // but allow this customization for those who wish it
                   51169:         return true;
                   51170:     }
                   51171: 
                   51172:     /**
                   51173:      * @access protected
                   51174:      */
                   51175:     function validateDate()
                   51176:     {
                   51177:         if ($this->_state == PEAR_VALIDATE_NORMAL ||
                   51178:               $this->_state == PEAR_VALIDATE_PACKAGING) {
                   51179: 
                   51180:             if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
                   51181:                   $this->_packagexml->getDate(), $res) ||
                   51182:                   count($res) < 4
                   51183:                   || !checkdate($res[2], $res[3], $res[1])
                   51184:                 ) {
                   51185:                 $this->_addFailure('date', 'invalid release date "' .
                   51186:                     $this->_packagexml->getDate() . '"');
                   51187:                 return false;
                   51188:             }
                   51189: 
                   51190:             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
                   51191:                   $this->_packagexml->getDate() != date('Y-m-d')) {
                   51192:                 $this->_addWarning('date', 'Release Date "' .
                   51193:                     $this->_packagexml->getDate() . '" is not today');
                   51194:             }
                   51195:         }
                   51196:         return true;
                   51197:     }
                   51198: 
                   51199:     /**
                   51200:      * @access protected
                   51201:      */
                   51202:     function validateTime()
                   51203:     {
                   51204:         if (!$this->_packagexml->getTime()) {
                   51205:             // default of no time value set
                   51206:             return true;
                   51207:         }
                   51208: 
                   51209:         // packager automatically sets time, so only validate if pear validate is called
                   51210:         if ($this->_state = PEAR_VALIDATE_NORMAL) {
                   51211:             if (!preg_match('/\d\d:\d\d:\d\d/',
                   51212:                   $this->_packagexml->getTime())) {
                   51213:                 $this->_addFailure('time', 'invalid release time "' .
                   51214:                     $this->_packagexml->getTime() . '"');
                   51215:                 return false;
                   51216:             }
                   51217: 
                   51218:             $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
                   51219:             if ($result === false || empty($matches)) {
                   51220:                 $this->_addFailure('time', 'invalid release time "' .
                   51221:                     $this->_packagexml->getTime() . '"');
                   51222:                 return false;
                   51223:             }
                   51224:         }
                   51225: 
                   51226:         return true;
                   51227:     }
                   51228: 
                   51229:     /**
                   51230:      * @access protected
                   51231:      */
                   51232:     function validateState()
                   51233:     {
                   51234:         // this is the closest to "final" php4 can get
                   51235:         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
                   51236:             if (strtolower($this->_packagexml->getState() == 'rc')) {
                   51237:                 $this->_addFailure('state', 'RC is not a state, it is a version ' .
                   51238:                     'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
                   51239:             }
                   51240:             $this->_addFailure('state', 'invalid release state "' .
                   51241:                 $this->_packagexml->getState() . '", must be one of: ' .
                   51242:                 implode(', ', PEAR_Validate::getValidStates()));
                   51243:             return false;
                   51244:         }
                   51245:         return true;
                   51246:     }
                   51247: 
                   51248:     /**
                   51249:      * @access protected
                   51250:      */
                   51251:     function validateStability()
                   51252:     {
                   51253:         $ret = true;
                   51254:         $packagestability = $this->_packagexml->getState();
                   51255:         $apistability = $this->_packagexml->getState('api');
                   51256:         if (!PEAR_Validate::validState($packagestability)) {
                   51257:             $this->_addFailure('state', 'invalid release stability "' .
                   51258:                 $this->_packagexml->getState() . '", must be one of: ' .
                   51259:                 implode(', ', PEAR_Validate::getValidStates()));
                   51260:             $ret = false;
                   51261:         }
                   51262:         $apistates = PEAR_Validate::getValidStates();
                   51263:         array_shift($apistates); // snapshot is not allowed
                   51264:         if (!in_array($apistability, $apistates)) {
                   51265:             $this->_addFailure('state', 'invalid API stability "' .
                   51266:                 $this->_packagexml->getState('api') . '", must be one of: ' .
                   51267:                 implode(', ', $apistates));
                   51268:             $ret = false;
                   51269:         }
                   51270:         return $ret;
                   51271:     }
                   51272: 
                   51273:     /**
                   51274:      * @access protected
                   51275:      */
                   51276:     function validateSummary()
                   51277:     {
                   51278:         return true;
                   51279:     }
                   51280: 
                   51281:     /**
                   51282:      * @access protected
                   51283:      */
                   51284:     function validateDescription()
                   51285:     {
                   51286:         return true;
                   51287:     }
                   51288: 
                   51289:     /**
                   51290:      * @access protected
                   51291:      */
                   51292:     function validateLicense()
                   51293:     {
                   51294:         return true;
                   51295:     }
                   51296: 
                   51297:     /**
                   51298:      * @access protected
                   51299:      */
                   51300:     function validateNotes()
                   51301:     {
                   51302:         return true;
                   51303:     }
                   51304: 
                   51305:     /**
                   51306:      * for package.xml 2.0 only - channels can't use package.xml 1.0
                   51307:      * @access protected
                   51308:      */
                   51309:     function validateDependencies()
                   51310:     {
                   51311:         return true;
                   51312:     }
                   51313: 
                   51314:     /**
                   51315:      * for package.xml 1.0 only
                   51316:      * @access private
                   51317:      */
                   51318:     function _validateFilelist()
                   51319:     {
                   51320:         return true; // placeholder for now
                   51321:     }
                   51322: 
                   51323:     /**
                   51324:      * for package.xml 2.0 only
                   51325:      * @access protected
                   51326:      */
                   51327:     function validateMainFilelist()
                   51328:     {
                   51329:         return true; // placeholder for now
                   51330:     }
                   51331: 
                   51332:     /**
                   51333:      * for package.xml 2.0 only
                   51334:      * @access protected
                   51335:      */
                   51336:     function validateReleaseFilelist()
                   51337:     {
                   51338:         return true; // placeholder for now
                   51339:     }
                   51340: 
                   51341:     /**
                   51342:      * @access protected
                   51343:      */
                   51344:     function validateChangelog()
                   51345:     {
                   51346:         return true;
                   51347:     }
                   51348: 
                   51349:     /**
                   51350:      * @access protected
                   51351:      */
                   51352:     function validateFilelist()
                   51353:     {
                   51354:         return true;
                   51355:     }
                   51356: 
                   51357:     /**
                   51358:      * @access protected
                   51359:      */
                   51360:     function validateDeps()
                   51361:     {
                   51362:         return true;
                   51363:     }
                   51364: }PEAR-1.9.4/PEAR/XMLParser.php0000644000076500000240000001600111605156760014311 0ustar  helgistaff<?php
                   51365: /**
                   51366:  * PEAR_XMLParser
                   51367:  *
                   51368:  * PHP versions 4 and 5
                   51369:  *
                   51370:  * @category   pear
                   51371:  * @package    PEAR
                   51372:  * @author     Greg Beaver <cellog@php.net>
                   51373:  * @author     Stephan Schmidt (original XML_Unserializer code)
                   51374:  * @copyright  1997-2009 The Authors
                   51375:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   51376:  * @version    CVS: $Id: XMLParser.php 313023 2011-07-06 19:17:11Z dufuz $
                   51377:  * @link       http://pear.php.net/package/PEAR
                   51378:  * @since      File available since Release 1.4.0a1
                   51379:  */
                   51380: 
                   51381: /**
                   51382:  * Parser for any xml file
                   51383:  * @category  pear
                   51384:  * @package   PEAR
                   51385:  * @author    Greg Beaver <cellog@php.net>
                   51386:  * @author    Stephan Schmidt (original XML_Unserializer code)
                   51387:  * @copyright 1997-2009 The Authors
                   51388:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   51389:  * @version   Release: 1.9.4
                   51390:  * @link      http://pear.php.net/package/PEAR
                   51391:  * @since     Class available since Release 1.4.0a1
                   51392:  */
                   51393: class PEAR_XMLParser
                   51394: {
                   51395:     /**
                   51396:      * unserilialized data
                   51397:      * @var string $_serializedData
                   51398:      */
                   51399:     var $_unserializedData = null;
                   51400: 
                   51401:     /**
                   51402:      * name of the root tag
                   51403:      * @var string $_root
                   51404:      */
                   51405:     var $_root = null;
                   51406: 
                   51407:     /**
                   51408:      * stack for all data that is found
                   51409:      * @var array    $_dataStack
                   51410:      */
                   51411:     var $_dataStack = array();
                   51412: 
                   51413:     /**
                   51414:      * stack for all values that are generated
                   51415:      * @var array    $_valStack
                   51416:      */
                   51417:     var $_valStack = array();
                   51418: 
                   51419:     /**
                   51420:      * current tag depth
                   51421:      * @var int    $_depth
                   51422:      */
                   51423:     var $_depth = 0;
                   51424: 
                   51425:     /**
                   51426:      * The XML encoding to use
                   51427:      * @var string $encoding
                   51428:      */
                   51429:     var $encoding = 'ISO-8859-1';
                   51430: 
                   51431:     /**
                   51432:      * @return array
                   51433:      */
                   51434:     function getData()
                   51435:     {
                   51436:         return $this->_unserializedData;
                   51437:     }
                   51438: 
                   51439:     /**
                   51440:      * @param string xml content
                   51441:      * @return true|PEAR_Error
                   51442:      */
                   51443:     function parse($data)
                   51444:     {
                   51445:         if (!extension_loaded('xml')) {
                   51446:             include_once 'PEAR.php';
                   51447:             return PEAR::raiseError("XML Extension not found", 1);
                   51448:         }
                   51449:         $this->_dataStack =  $this->_valStack = array();
                   51450:         $this->_depth = 0;
                   51451: 
                   51452:         if (
                   51453:             strpos($data, 'encoding="UTF-8"')
                   51454:             || strpos($data, 'encoding="utf-8"')
                   51455:             || strpos($data, "encoding='UTF-8'")
                   51456:             || strpos($data, "encoding='utf-8'")
                   51457:         ) {
                   51458:             $this->encoding = 'UTF-8';
                   51459:         }
                   51460: 
                   51461:         if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
                   51462:             $data = utf8_decode($data);
                   51463:             $this->encoding = 'ISO-8859-1';
                   51464:         }
                   51465: 
                   51466:         $xp = xml_parser_create($this->encoding);
                   51467:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
                   51468:         xml_set_object($xp, $this);
                   51469:         xml_set_element_handler($xp, 'startHandler', 'endHandler');
                   51470:         xml_set_character_data_handler($xp, 'cdataHandler');
                   51471:         if (!xml_parse($xp, $data)) {
                   51472:             $msg = xml_error_string(xml_get_error_code($xp));
                   51473:             $line = xml_get_current_line_number($xp);
                   51474:             xml_parser_free($xp);
                   51475:             include_once 'PEAR.php';
                   51476:             return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
                   51477:         }
                   51478:         xml_parser_free($xp);
                   51479:         return true;
                   51480:     }
                   51481: 
                   51482:     /**
                   51483:      * Start element handler for XML parser
                   51484:      *
                   51485:      * @access private
                   51486:      * @param  object $parser  XML parser object
                   51487:      * @param  string $element XML element
                   51488:      * @param  array  $attribs attributes of XML tag
                   51489:      * @return void
                   51490:      */
                   51491:     function startHandler($parser, $element, $attribs)
                   51492:     {
                   51493:         $this->_depth++;
                   51494:         $this->_dataStack[$this->_depth] = null;
                   51495: 
                   51496:         $val = array(
                   51497:             'name'         => $element,
                   51498:             'value'        => null,
                   51499:             'type'         => 'string',
                   51500:             'childrenKeys' => array(),
                   51501:             'aggregKeys'   => array()
                   51502:        );
                   51503: 
                   51504:         if (count($attribs) > 0) {
                   51505:             $val['children'] = array();
                   51506:             $val['type'] = 'array';
                   51507:             $val['children']['attribs'] = $attribs;
                   51508:         }
                   51509: 
                   51510:         array_push($this->_valStack, $val);
                   51511:     }
                   51512: 
                   51513:     /**
                   51514:      * post-process data
                   51515:      *
                   51516:      * @param string $data
                   51517:      * @param string $element element name
                   51518:      */
                   51519:     function postProcess($data, $element)
                   51520:     {
                   51521:         return trim($data);
                   51522:     }
                   51523: 
                   51524:     /**
                   51525:      * End element handler for XML parser
                   51526:      *
                   51527:      * @access private
                   51528:      * @param  object XML parser object
                   51529:      * @param  string
                   51530:      * @return void
                   51531:      */
                   51532:     function endHandler($parser, $element)
                   51533:     {
                   51534:         $value = array_pop($this->_valStack);
                   51535:         $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);
                   51536: 
                   51537:         // adjust type of the value
                   51538:         switch (strtolower($value['type'])) {
                   51539:             // unserialize an array
                   51540:             case 'array':
                   51541:                 if ($data !== '') {
                   51542:                     $value['children']['_content'] = $data;
                   51543:                 }
                   51544: 
                   51545:                 $value['value'] = isset($value['children']) ? $value['children'] : array();
                   51546:                 break;
                   51547: 
                   51548:             /*
                   51549:              * unserialize a null value
                   51550:              */
                   51551:             case 'null':
                   51552:                 $data = null;
                   51553:                 break;
                   51554: 
                   51555:             /*
                   51556:              * unserialize any scalar value
                   51557:              */
                   51558:             default:
                   51559:                 settype($data, $value['type']);
                   51560:                 $value['value'] = $data;
                   51561:                 break;
                   51562:         }
                   51563: 
                   51564:         $parent = array_pop($this->_valStack);
                   51565:         if ($parent === null) {
                   51566:             $this->_unserializedData = &$value['value'];
                   51567:             $this->_root = &$value['name'];
                   51568:             return true;
                   51569:         }
                   51570: 
                   51571:         // parent has to be an array
                   51572:         if (!isset($parent['children']) || !is_array($parent['children'])) {
                   51573:             $parent['children'] = array();
                   51574:             if ($parent['type'] != 'array') {
                   51575:                 $parent['type'] = 'array';
                   51576:             }
                   51577:         }
                   51578: 
                   51579:         if (!empty($value['name'])) {
                   51580:             // there already has been a tag with this name
                   51581:             if (in_array($value['name'], $parent['childrenKeys'])) {
                   51582:                 // no aggregate has been created for this tag
                   51583:                 if (!in_array($value['name'], $parent['aggregKeys'])) {
                   51584:                     if (isset($parent['children'][$value['name']])) {
                   51585:                         $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                   51586:                     } else {
                   51587:                         $parent['children'][$value['name']] = array();
                   51588:                     }
                   51589:                     array_push($parent['aggregKeys'], $value['name']);
                   51590:                 }
                   51591:                 array_push($parent['children'][$value['name']], $value['value']);
                   51592:             } else {
                   51593:                 $parent['children'][$value['name']] = &$value['value'];
                   51594:                 array_push($parent['childrenKeys'], $value['name']);
                   51595:             }
                   51596:         } else {
                   51597:             array_push($parent['children'],$value['value']);
                   51598:         }
                   51599:         array_push($this->_valStack, $parent);
                   51600: 
                   51601:         $this->_depth--;
                   51602:     }
                   51603: 
                   51604:     /**
                   51605:      * Handler for character data
                   51606:      *
                   51607:      * @access private
                   51608:      * @param  object XML parser object
                   51609:      * @param  string CDATA
                   51610:      * @return void
                   51611:      */
                   51612:     function cdataHandler($parser, $cdata)
                   51613:     {
                   51614:         $this->_dataStack[$this->_depth] .= $cdata;
                   51615:     }
                   51616: }PEAR-1.9.4/scripts/pear.bat0000755000076500000240000001036111605156760014350 0ustar  helgistaff@ECHO OFF
                   51617: 
                   51618: REM ----------------------------------------------------------------------
                   51619: REM PHP version 5
                   51620: REM ----------------------------------------------------------------------
                   51621: REM Copyright (c) 1997-2010 The Authors
                   51622: REM ----------------------------------------------------------------------
                   51623: REM http://opensource.org/licenses/bsd-license.php New BSD License
                   51624: REM ----------------------------------------------------------------------
                   51625: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   51626: REM ----------------------------------------------------------------------
                   51627: REM
                   51628: REM  Last updated 12/29/2004 ($Id$ is not replaced if the file is binary)
                   51629: 
                   51630: REM change this lines to match the paths of your system
                   51631: REM -------------------
                   51632: 
                   51633: 
                   51634: REM Test to see if this is a raw pear.bat (uninstalled version)
                   51635: SET TMPTMPTMPTMPT=@includ
                   51636: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   51637: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   51638: 
                   51639: REM Check PEAR global ENV, set them if they do not exist
                   51640: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   51641: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   51642: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   51643: 
                   51644: GOTO :INSTALLED
                   51645: 
                   51646: :NOTINSTALLED
                   51647: ECHO WARNING: This is a raw, uninstalled pear.bat
                   51648: 
                   51649: REM Check to see if we can grab the directory of this file (Windows NT+)
                   51650: IF %~n0 == pear (
                   51651: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   51652: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   51653: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   51654: "%PHP_PEAR_PHP_BIN%" -v
                   51655: GOTO :NEXTTEST
                   51656: ))
                   51657: GOTO :FAILAUTODETECT
                   51658: :NEXTTEST
                   51659: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   51660: 
                   51661: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   51662: 
                   51663: 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
                   51664: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   51665: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   51666: DEL ~a.a
                   51667: DEL ~~getloc.php
                   51668: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   51669: 
                   51670: REM Make sure there is a pearcmd.php at our disposal
                   51671: 
                   51672: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   51673: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51674: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51675: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51676: )
                   51677: )
                   51678: GOTO :INSTALLED
                   51679: ) ELSE (
                   51680: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   51681: )
                   51682: :FAILAUTODETECT
                   51683: echo WARNING: failed to auto-detect pear information
                   51684: :INSTALLED
                   51685: 
                   51686: REM Check Folders and files
                   51687: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   51688: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   51689: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   51690: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   51691: 
                   51692: REM launch pearcmd
                   51693: GOTO RUN
                   51694: :PEAR_INSTALL_ERROR
                   51695: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51696: ECHO Please fix it using your environment variable or modify
                   51697: ECHO the default value in pear.bat
                   51698: ECHO The current value is:
                   51699: ECHO %PHP_PEAR_INSTALL_DIR%
                   51700: GOTO END
                   51701: :PEAR_INSTALL_ERROR2
                   51702: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51703: ECHO pearcmd.php could not be found there.
                   51704: ECHO Please fix it using your environment variable or modify
                   51705: ECHO the default value in pear.bat
                   51706: ECHO The current value is:
                   51707: ECHO %PHP_PEAR_INSTALL_DIR%
                   51708: GOTO END
                   51709: :PEAR_BIN_ERROR
                   51710: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   51711: ECHO Please fix it using your environment variable or modify
                   51712: ECHO the default value in pear.bat
                   51713: ECHO The current value is:
                   51714: ECHO %PHP_PEAR_BIN_DIR%
                   51715: GOTO END
                   51716: :PEAR_PHPBIN_ERROR
                   51717: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   51718: ECHO Please fix it using your environment variable or modify
                   51719: ECHO the default value in pear.bat
                   51720: ECHO The current value is:
                   51721: ECHO %PHP_PEAR_PHP_BIN%
                   51722: GOTO END
                   51723: :RUN
                   51724: "%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
                   51725: :END
                   51726: @ECHO ONPEAR-1.9.4/scripts/peardev.bat0000644000076500000240000001113711605156760015046 0ustar  helgistaff@ECHO OFF
                   51727: 
                   51728: REM ----------------------------------------------------------------------
                   51729: REM PHP version 5
                   51730: REM ----------------------------------------------------------------------
                   51731: REM Copyright (c) 1997-2004 The PHP Group
                   51732: REM ----------------------------------------------------------------------
                   51733: REM  This source file is subject to version 3.0 of the PHP license,
                   51734: REM  that is bundled with this package in the file LICENSE, and is
                   51735: REM  available at through the world-wide-web at
                   51736: REM  http://www.php.net/license/3_0.txt.
                   51737: REM  If you did not receive a copy of the PHP license and are unable to
                   51738: REM  obtain it through the world-wide-web, please send a note to
                   51739: REM  license@php.net so we can mail you a copy immediately.
                   51740: REM ----------------------------------------------------------------------
                   51741: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   51742: REM ----------------------------------------------------------------------
                   51743: REM
                   51744: REM  $Id: peardev.bat,v 1.6 2007-09-03 03:00:17 cellog Exp $
                   51745: 
                   51746: REM change this lines to match the paths of your system
                   51747: REM -------------------
                   51748: 
                   51749: 
                   51750: REM Test to see if this is a raw pear.bat (uninstalled version)
                   51751: SET TMPTMPTMPTMPT=@includ
                   51752: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   51753: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   51754: 
                   51755: REM Check PEAR global ENV, set them if they do not exist
                   51756: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   51757: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   51758: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   51759: GOTO :INSTALLED
                   51760: 
                   51761: :NOTINSTALLED
                   51762: ECHO WARNING: This is a raw, uninstalled pear.bat
                   51763: 
                   51764: REM Check to see if we can grab the directory of this file (Windows NT+)
                   51765: IF %~n0 == pear (
                   51766: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   51767: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   51768: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   51769: "%PHP_PEAR_PHP_BIN%" -v
                   51770: GOTO :NEXTTEST
                   51771: ))
                   51772: GOTO :FAILAUTODETECT
                   51773: :NEXTTEST
                   51774: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   51775: 
                   51776: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   51777: 
                   51778: 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
                   51779: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   51780: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   51781: DEL ~a.a
                   51782: DEL ~~getloc.php
                   51783: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   51784: 
                   51785: REM Make sure there is a pearcmd.php at our disposal
                   51786: 
                   51787: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   51788: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51789: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51790: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51791: )
                   51792: )
                   51793: GOTO :INSTALLED
                   51794: ) ELSE (
                   51795: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   51796: )
                   51797: :FAILAUTODETECT
                   51798: echo WARNING: failed to auto-detect pear information
                   51799: :INSTALLED
                   51800: 
                   51801: REM Check Folders and files
                   51802: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   51803: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   51804: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   51805: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   51806: REM launch pearcmd
                   51807: GOTO RUN
                   51808: :PEAR_INSTALL_ERROR
                   51809: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51810: ECHO Please fix it using your environment variable or modify
                   51811: ECHO the default value in pear.bat
                   51812: ECHO The current value is:
                   51813: ECHO %PHP_PEAR_INSTALL_DIR%
                   51814: GOTO END
                   51815: :PEAR_INSTALL_ERROR2
                   51816: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51817: ECHO pearcmd.php could not be found there.
                   51818: ECHO Please fix it using your environment variable or modify
                   51819: ECHO the default value in pear.bat
                   51820: ECHO The current value is:
                   51821: ECHO %PHP_PEAR_INSTALL_DIR%
                   51822: GOTO END
                   51823: :PEAR_BIN_ERROR
                   51824: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   51825: ECHO Please fix it using your environment variable or modify
                   51826: ECHO the default value in pear.bat
                   51827: ECHO The current value is:
                   51828: ECHO %PHP_PEAR_BIN_DIR%
                   51829: GOTO END
                   51830: :PEAR_PHPBIN_ERROR
                   51831: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   51832: ECHO Please fix it using your environment variable or modify
                   51833: ECHO the default value in pear.bat
                   51834: ECHO The current value is:
                   51835: ECHO %PHP_PEAR_PHP_BIN%
                   51836: GOTO END
                   51837: :RUN
                   51838: "%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
                   51839: :END
                   51840: @ECHO ONPEAR-1.9.4/scripts/pecl.bat0000644000076500000240000001103011605156760014333 0ustar  helgistaff@ECHO OFF
                   51841: 
                   51842: REM ----------------------------------------------------------------------
                   51843: REM PHP version 5
                   51844: REM ----------------------------------------------------------------------
                   51845: REM Copyright (c) 1997-2004 The PHP Group
                   51846: REM ----------------------------------------------------------------------
                   51847: REM  This source file is subject to version 3.0 of the PHP license,
                   51848: REM  that is bundled with this package in the file LICENSE, and is
                   51849: REM  available at through the world-wide-web at
                   51850: REM  http://www.php.net/license/3_0.txt.
                   51851: REM  If you did not receive a copy of the PHP license and are unable to
                   51852: REM  obtain it through the world-wide-web, please send a note to
                   51853: REM  license@php.net so we can mail you a copy immediately.
                   51854: REM ----------------------------------------------------------------------
                   51855: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   51856: REM ----------------------------------------------------------------------
                   51857: REM
                   51858: REM  Last updated 02/08/2004 ($Id$ is not replaced if the file is binary)
                   51859: 
                   51860: REM change this lines to match the paths of your system
                   51861: REM -------------------
                   51862: 
                   51863: 
                   51864: REM Test to see if this is a raw pear.bat (uninstalled version)
                   51865: SET TMPTMPTMPTMPT=@includ
                   51866: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   51867: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   51868: 
                   51869: REM Check PEAR global ENV, set them if they do not exist
                   51870: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   51871: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   51872: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   51873: GOTO :INSTALLED
                   51874: 
                   51875: :NOTINSTALLED
                   51876: ECHO WARNING: This is a raw, uninstalled pear.bat
                   51877: 
                   51878: REM Check to see if we can grab the directory of this file (Windows NT+)
                   51879: IF %~n0 == pear (
                   51880: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   51881: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   51882: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   51883: "%PHP_PEAR_PHP_BIN%" -v
                   51884: GOTO :NEXTTEST
                   51885: ))
                   51886: GOTO :FAILAUTODETECT
                   51887: :NEXTTEST
                   51888: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   51889: 
                   51890: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   51891: 
                   51892: 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
                   51893: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   51894: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   51895: DEL ~a.a
                   51896: DEL ~~getloc.php
                   51897: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   51898: 
                   51899: REM Make sure there is a pearcmd.php at our disposal
                   51900: 
                   51901: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   51902: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51903: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51904: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51905: )
                   51906: )
                   51907: GOTO :INSTALLED
                   51908: ) ELSE (
                   51909: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   51910: )
                   51911: :FAILAUTODETECT
                   51912: echo WARNING: failed to auto-detect pear information
                   51913: :INSTALLED
                   51914: 
                   51915: REM Check Folders and files
                   51916: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   51917: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   51918: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   51919: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   51920: REM launch pearcmd
                   51921: GOTO RUN
                   51922: :PEAR_INSTALL_ERROR
                   51923: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51924: ECHO Please fix it using your environment variable or modify
                   51925: ECHO the default value in pear.bat
                   51926: ECHO The current value is:
                   51927: ECHO %PHP_PEAR_INSTALL_DIR%
                   51928: GOTO END
                   51929: :PEAR_INSTALL_ERROR2
                   51930: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51931: ECHO pearcmd.php could not be found there.
                   51932: ECHO Please fix it using your environment variable or modify
                   51933: ECHO the default value in pear.bat
                   51934: ECHO The current value is:
                   51935: ECHO %PHP_PEAR_INSTALL_DIR%
                   51936: GOTO END
                   51937: :PEAR_BIN_ERROR
                   51938: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   51939: ECHO Please fix it using your environment variable or modify
                   51940: ECHO the default value in pear.bat
                   51941: ECHO The current value is:
                   51942: ECHO %PHP_PEAR_BIN_DIR%
                   51943: GOTO END
                   51944: :PEAR_PHPBIN_ERROR
                   51945: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   51946: ECHO Please fix it using your environment variable or modify
                   51947: ECHO the default value in pear.bat
                   51948: ECHO The current value is:
                   51949: ECHO %PHP_PEAR_PHP_BIN%
                   51950: GOTO END
                   51951: :RUN
                   51952: "%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
                   51953: :END
                   51954: @ECHO ONPEAR-1.9.4/scripts/pear.sh0000644000076500000240000000140411605156760014207 0ustar  helgistaff#!/bin/sh
                   51955: 
                   51956: # first find which PHP binary to use
                   51957: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   51958:   PHP="$PHP_PEAR_PHP_BIN"
                   51959: else
                   51960:   if test "@php_bin@" = '@'php_bin'@'; then
                   51961:     PHP=php
                   51962:   else
                   51963:     PHP="@php_bin@"
                   51964:   fi
                   51965: fi
                   51966: 
                   51967: # then look for the right pear include dir
                   51968: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   51969:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   51970:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   51971: else
                   51972:   if test "@php_dir@" = '@'php_dir'@'; then
                   51973:     INCDIR=`dirname $0`
                   51974:     INCARG=""
                   51975:   else
                   51976:     INCDIR="@php_dir@"
                   51977:     INCARG="-d include_path=@php_dir@"
                   51978:   fi
                   51979: fi
                   51980: 
                   51981: 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 "$@"
                   51982: PEAR-1.9.4/scripts/peardev.sh0000644000076500000240000000143111605156760014706 0ustar  helgistaff#!/bin/sh
                   51983: 
                   51984: # first find which PHP binary to use
                   51985: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   51986:   PHP="$PHP_PEAR_PHP_BIN"
                   51987: else
                   51988:   if test "@php_bin@" = '@'php_bin'@'; then
                   51989:     PHP=php
                   51990:   else
                   51991:     PHP="@php_bin@"
                   51992:   fi
                   51993: fi
                   51994: 
                   51995: # then look for the right pear include dir
                   51996: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   51997:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   51998:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   51999: else
                   52000:   if test "@php_dir@" = '@'php_dir'@'; then
                   52001:     INCDIR=`dirname $0`
                   52002:     INCARG=""
                   52003:   else
                   52004:     INCDIR="@php_dir@"
                   52005:     INCARG="-d include_path=@php_dir@"
                   52006:   fi
                   52007: fi
                   52008: 
                   52009: 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 "$@"
                   52010: PEAR-1.9.4/scripts/pecl.sh0000644000076500000240000000130511605156760014203 0ustar  helgistaff#!/bin/sh
                   52011: 
                   52012: # first find which PHP binary to use
                   52013: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   52014:   PHP="$PHP_PEAR_PHP_BIN"
                   52015: else
                   52016:   if test "@php_bin@" = '@'php_bin'@'; then
                   52017:     PHP=php
                   52018:   else
                   52019:     PHP="@php_bin@"
                   52020:   fi
                   52021: fi
                   52022: 
                   52023: # then look for the right pear include dir
                   52024: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   52025:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   52026:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   52027: else
                   52028:   if test "@php_dir@" = '@'php_dir'@'; then
                   52029:     INCDIR=`dirname $0`
                   52030:     INCARG=""
                   52031:   else
                   52032:     INCDIR="@php_dir@"
                   52033:     INCARG="-d include_path=@php_dir@"
                   52034:   fi
                   52035: fi
                   52036: 
                   52037: 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 "$@"
                   52038: PEAR-1.9.4/scripts/pearcmd.php0000644000076500000240000003414511605156760015060 0ustar  helgistaff<?php
                   52039: /**
                   52040:  * PEAR, the PHP Extension and Application Repository
                   52041:  *
                   52042:  * Command line interface
                   52043:  *
                   52044:  * PHP versions 4 and 5
                   52045:  *
                   52046:  * @category   pear
                   52047:  * @package    PEAR
                   52048:  * @author     Stig Bakken <ssb@php.net>
                   52049:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   52050:  * @copyright  1997-2009 The Authors
                   52051:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52052:  * @version    CVS: $Id: pearcmd.php 313023 2011-07-06 19:17:11Z dufuz $
                   52053:  * @link       http://pear.php.net/package/PEAR
                   52054:  */
                   52055: 
                   52056: ob_end_clean();
                   52057: if (!defined('PEAR_RUNTYPE')) {
                   52058:     // this is defined in peclcmd.php as 'pecl'
                   52059:     define('PEAR_RUNTYPE', 'pear');
                   52060: }
                   52061: define('PEAR_IGNORE_BACKTRACE', 1);
                   52062: /**
                   52063:  * @nodep Gtk
                   52064:  */
                   52065: if ('@include_path@' != '@'.'include_path'.'@') {
                   52066:     ini_set('include_path', '@include_path@');
                   52067:     $raw = false;
                   52068: } else {
                   52069:     // this is a raw, uninstalled pear, either a cvs checkout, or php distro
                   52070:     $raw = true;
                   52071: }
                   52072: @ini_set('allow_url_fopen', true);
                   52073: if (!ini_get('safe_mode')) {
                   52074:     @set_time_limit(0);
                   52075: }
                   52076: ob_implicit_flush(true);
                   52077: @ini_set('track_errors', true);
                   52078: @ini_set('html_errors', false);
                   52079: @ini_set('magic_quotes_runtime', false);
                   52080: $_PEAR_PHPDIR = '#$%^&*';
                   52081: set_error_handler('error_handler');
                   52082: 
                   52083: $pear_package_version = "@pear_version@";
                   52084: 
                   52085: require_once 'PEAR.php';
                   52086: require_once 'PEAR/Frontend.php';
                   52087: require_once 'PEAR/Config.php';
                   52088: require_once 'PEAR/Command.php';
                   52089: require_once 'Console/Getopt.php';
                   52090: 
                   52091: 
                   52092: PEAR_Command::setFrontendType('CLI');
                   52093: $all_commands = PEAR_Command::getCommands();
                   52094: 
                   52095: // remove this next part when we stop supporting that crap-ass PHP 4.2
                   52096: if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) {
                   52097:     echo 'ERROR: either use the CLI php executable, or set register_argc_argv=On in php.ini';
                   52098:     exit(1);
                   52099: }
                   52100: 
                   52101: $argv = Console_Getopt::readPHPArgv();
                   52102: // fix CGI sapi oddity - the -- in pear.bat/pear is not removed
                   52103: if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
                   52104:     unset($argv[1]);
                   52105:     $argv = array_values($argv);
                   52106: }
                   52107: $progname = PEAR_RUNTYPE;
                   52108: array_shift($argv);
                   52109: $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
                   52110: if (PEAR::isError($options)) {
                   52111:     usage($options);
                   52112: }
                   52113: 
                   52114: $opts = $options[0];
                   52115: 
                   52116: $fetype = 'CLI';
                   52117: if ($progname == 'gpear' || $progname == 'pear-gtk') {
                   52118:     $fetype = 'Gtk';
                   52119: } else {
                   52120:     foreach ($opts as $opt) {
                   52121:         if ($opt[0] == 'G') {
                   52122:             $fetype = 'Gtk';
                   52123:         }
                   52124:     }
                   52125: }
                   52126: //Check if Gtk and PHP >= 5.1.0
                   52127: if ($fetype == 'Gtk' && version_compare(phpversion(), '5.1.0', '>=')) {
                   52128:     $fetype = 'Gtk2';
                   52129: }
                   52130: 
                   52131: $pear_user_config = '';
                   52132: $pear_system_config = '';
                   52133: $store_user_config = false;
                   52134: $store_system_config = false;
                   52135: $verbose = 1;
                   52136: 
                   52137: foreach ($opts as $opt) {
                   52138:     switch ($opt[0]) {
                   52139:         case 'c':
                   52140:             $pear_user_config = $opt[1];
                   52141:             break;
                   52142:         case 'C':
                   52143:             $pear_system_config = $opt[1];
                   52144:             break;
                   52145:     }
                   52146: }
                   52147: 
                   52148: PEAR_Command::setFrontendType($fetype);
                   52149: $ui = &PEAR_Command::getFrontendObject();
                   52150: $config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);
                   52151: 
                   52152: if (PEAR::isError($config)) {
                   52153:     $_file = '';
                   52154:     if ($pear_user_config !== false) {
                   52155:        $_file .= $pear_user_config;
                   52156:     }
                   52157:     if ($pear_system_config !== false) {
                   52158:        $_file .= '/' . $pear_system_config;
                   52159:     }
                   52160:     if ($_file == '/') {
                   52161:         $_file = 'The default config file';
                   52162:     }
                   52163:     $config->getMessage();
                   52164:     $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
                   52165:     // We stop, we have no idea where we are :)
                   52166:     exit(1);
                   52167: }
                   52168: 
                   52169: // this is used in the error handler to retrieve a relative path
                   52170: $_PEAR_PHPDIR = $config->get('php_dir');
                   52171: $ui->setConfig($config);
                   52172: PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
                   52173: if (ini_get('safe_mode')) {
                   52174:     $ui->outputData('WARNING: running in safe mode requires that all files created ' .
                   52175:         'be the same uid as the current script.  PHP reports this script is uid: ' .
                   52176:         @getmyuid() . ', and current user is: ' . @get_current_user());
                   52177: }
                   52178: 
                   52179: $verbose = $config->get("verbose");
                   52180: $cmdopts = array();
                   52181: 
                   52182: if ($raw) {
                   52183:     if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
                   52184:         $found = false;
                   52185:         foreach ($opts as $opt) {
                   52186:             if ($opt[0] == 'd' || $opt[0] == 'D') {
                   52187:                 $found = true; // the user knows what they are doing, and are setting config values
                   52188:             }
                   52189:         }
                   52190:         if (!$found) {
                   52191:             // no prior runs, try to install PEAR
                   52192:             if (strpos(dirname(__FILE__), 'scripts')) {
                   52193:                 $packagexml = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'package2.xml';
                   52194:                 $pearbase = dirname(dirname(__FILE__));
                   52195:             } else {
                   52196:                 $packagexml = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'package2.xml';
                   52197:                 $pearbase = dirname(__FILE__);
                   52198:             }
                   52199:             if (file_exists($packagexml)) {
                   52200:                 $options[1] = array(
                   52201:                     'install',
                   52202:                     $packagexml
                   52203:                 );
                   52204:                 $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                   52205:                 $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                   52206:                 $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                   52207:                 $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                   52208:                 $config->set('ext_dir', $pearbase . DIRECTORY_SEPARATOR . 'extensions');
                   52209:                 $config->set('bin_dir', $pearbase);
                   52210:                 $config->mergeConfigFile($pearbase . 'pear.ini', false);
                   52211:                 $config->store();
                   52212:                 $config->set('auto_discover', 1);
                   52213:             }
                   52214:         }
                   52215:     }
                   52216: }
                   52217: foreach ($opts as $opt) {
                   52218:     $param = !empty($opt[1]) ? $opt[1] : true;
                   52219:     switch ($opt[0]) {
                   52220:         case 'd':
                   52221:             if ($param === true) {
                   52222:                 die('Invalid usage of "-d" option, expected -d config_value=value, ' .
                   52223:                     'received "-d"' . "\n");
                   52224:             }
                   52225:             $possible = explode('=', $param);
                   52226:             if (count($possible) != 2) {
                   52227:                 die('Invalid usage of "-d" option, expected -d config_value=value, received "' .
                   52228:                     $param . '"' . "\n");
                   52229:             }
                   52230:             list($key, $value) = explode('=', $param);
                   52231:             $config->set($key, $value, 'user');
                   52232:             break;
                   52233:         case 'D':
                   52234:             if ($param === true) {
                   52235:                 die('Invalid usage of "-d" option, expected -d config_value=value, ' .
                   52236:                     'received "-d"' . "\n");
                   52237:             }
                   52238:             $possible = explode('=', $param);
                   52239:             if (count($possible) != 2) {
                   52240:                 die('Invalid usage of "-d" option, expected -d config_value=value, received "' .
                   52241:                     $param . '"' . "\n");
                   52242:             }
                   52243:             list($key, $value) = explode('=', $param);
                   52244:             $config->set($key, $value, 'system');
                   52245:             break;
                   52246:         case 's':
                   52247:             $store_user_config = true;
                   52248:             break;
                   52249:         case 'S':
                   52250:             $store_system_config = true;
                   52251:             break;
                   52252:         case 'u':
                   52253:             $config->remove($param, 'user');
                   52254:             break;
                   52255:         case 'v':
                   52256:             $config->set('verbose', $config->get('verbose') + 1);
                   52257:             break;
                   52258:         case 'q':
                   52259:             $config->set('verbose', $config->get('verbose') - 1);
                   52260:             break;
                   52261:         case 'V':
                   52262:             usage(null, 'version');
                   52263:         case 'c':
                   52264:         case 'C':
                   52265:             break;
                   52266:         default:
                   52267:             // all non pear params goes to the command
                   52268:             $cmdopts[$opt[0]] = $param;
                   52269:             break;
                   52270:     }
                   52271: }
                   52272: 
                   52273: if ($store_system_config) {
                   52274:     $config->store('system');
                   52275: }
                   52276: 
                   52277: if ($store_user_config) {
                   52278:     $config->store('user');
                   52279: }
                   52280: 
                   52281: $command = (isset($options[1][0])) ? $options[1][0] : null;
                   52282: if (empty($command) && ($store_user_config || $store_system_config)) {
                   52283:     exit;
                   52284: }
                   52285: 
                   52286: if ($fetype == 'Gtk' || $fetype == 'Gtk2') {
                   52287:     if (!$config->validConfiguration()) {
                   52288:         PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' .
                   52289:             "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" .
                   52290:             'file to one of these locations, or use the -c and -s options to create one');
                   52291:     }
                   52292:     Gtk::main();
                   52293: } else do {
                   52294:     if ($command == 'help') {
                   52295:         usage(null, @$options[1][1]);
                   52296:     }
                   52297: 
                   52298:     if (!$config->validConfiguration()) {
                   52299:         PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' .
                   52300:             "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" .
                   52301:             'file to one of these locations, or use the -c and -s options to create one');
                   52302:     }
                   52303: 
                   52304:     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   52305:     $cmd = PEAR_Command::factory($command, $config);
                   52306:     PEAR::popErrorHandling();
                   52307:     if (PEAR::isError($cmd)) {
                   52308:         usage(null, @$options[1][0]);
                   52309:     }
                   52310: 
                   52311:     $short_args = $long_args = null;
                   52312:     PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
                   52313:     array_shift($options[1]);
                   52314:     $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);
                   52315: 
                   52316:     if (PEAR::isError($tmp)) {
                   52317:         break;
                   52318:     }
                   52319: 
                   52320:     list($tmpopt, $params) = $tmp;
                   52321:     $opts = array();
                   52322:     foreach ($tmpopt as $foo => $tmp2) {
                   52323:         list($opt, $value) = $tmp2;
                   52324:         if ($value === null) {
                   52325:             $value = true; // options without args
                   52326:         }
                   52327: 
                   52328:         if (strlen($opt) == 1) {
                   52329:             $cmdoptions = $cmd->getOptions($command);
                   52330:             foreach ($cmdoptions as $o => $d) {
                   52331:                 if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                   52332:                     $opts[$o] = $value;
                   52333:                 }
                   52334:             }
                   52335:         } else {
                   52336:             if (substr($opt, 0, 2) == '--') {
                   52337:                 $opts[substr($opt, 2)] = $value;
                   52338:             }
                   52339:         }
                   52340:     }
                   52341: 
                   52342:     $ok = $cmd->run($command, $opts, $params);
                   52343:     if ($ok === false) {
                   52344:         PEAR::raiseError("unknown command `$command'");
                   52345:     }
                   52346: 
                   52347:     if (PEAR::isError($ok)) {
                   52348:         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
                   52349:         PEAR::raiseError($ok);
                   52350:     }
                   52351: } while (false);
                   52352: 
                   52353: // {{{ usage()
                   52354: 
                   52355: function usage($error = null, $helpsubject = null)
                   52356: {
                   52357:     global $progname, $all_commands;
                   52358:     $stdout = fopen('php://stdout', 'w');
                   52359:     if (PEAR::isError($error)) {
                   52360:         fputs($stdout, $error->getMessage() . "\n");
                   52361:     } elseif ($error !== null) {
                   52362:         fputs($stdout, "$error\n");
                   52363:     }
                   52364: 
                   52365:     if ($helpsubject != null) {
                   52366:         $put = cmdHelp($helpsubject);
                   52367:     } else {
                   52368:         $put = "Commands:\n";
                   52369:         $maxlen = max(array_map("strlen", $all_commands));
                   52370:         $formatstr = "%-{$maxlen}s  %s\n";
                   52371:         ksort($all_commands);
                   52372:         foreach ($all_commands as $cmd => $class) {
                   52373:             $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
                   52374:         }
                   52375:         $put .=
                   52376:             "Usage: $progname [options] command [command-options] <parameters>\n".
                   52377:             "Type \"$progname help options\" to list all options.\n".
                   52378:             "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
                   52379:             "Type \"$progname help <command>\" to get the help for the specified command.";
                   52380:     }
                   52381:     fputs($stdout, "$put\n");
                   52382:     fclose($stdout);
                   52383: 
                   52384:     if ($error === null) {
                   52385:         exit(0);
                   52386:     }
                   52387:     exit(1);
                   52388: }
                   52389: 
                   52390: function cmdHelp($command)
                   52391: {
                   52392:     global $progname, $all_commands, $config;
                   52393:     if ($command == "options") {
                   52394:         return
                   52395:         "Options:\n".
                   52396:         "     -v         increase verbosity level (default 1)\n".
                   52397:         "     -q         be quiet, decrease verbosity level\n".
                   52398:         "     -c file    find user configuration in `file'\n".
                   52399:         "     -C file    find system configuration in `file'\n".
                   52400:         "     -d foo=bar set user config variable `foo' to `bar'\n".
                   52401:         "     -D foo=bar set system config variable `foo' to `bar'\n".
                   52402:         "     -G         start in graphical (Gtk) mode\n".
                   52403:         "     -s         store user configuration\n".
                   52404:         "     -S         store system configuration\n".
                   52405:         "     -u foo     unset `foo' in the user configuration\n".
                   52406:         "     -h, -?     display help/usage (this message)\n".
                   52407:         "     -V         version information\n";
                   52408:     } elseif ($command == "shortcuts") {
                   52409:         $sc = PEAR_Command::getShortcuts();
                   52410:         $ret = "Shortcuts:\n";
                   52411:         foreach ($sc as $s => $c) {
                   52412:             $ret .= sprintf("     %-8s %s\n", $s, $c);
                   52413:         }
                   52414:         return $ret;
                   52415: 
                   52416:     } elseif ($command == "version") {
                   52417:         return "PEAR Version: ".$GLOBALS['pear_package_version'].
                   52418:                "\nPHP Version: ".phpversion().
                   52419:                "\nZend Engine Version: ".zend_version().
                   52420:                "\nRunning on: ".php_uname();
                   52421: 
                   52422:     } elseif ($help = PEAR_Command::getHelp($command)) {
                   52423:         if (is_string($help)) {
                   52424:             return "$progname $command [options] $help\n";
                   52425:         }
                   52426: 
                   52427:         if ($help[1] === null) {
                   52428:             return "$progname $command $help[0]";
                   52429:         }
                   52430: 
                   52431:         return "$progname $command [options] $help[0]\n$help[1]";
                   52432:     }
                   52433: 
                   52434:     return "Command '$command' is not valid, try '$progname help'";
                   52435: }
                   52436: 
                   52437: // }}}
                   52438: 
                   52439: function error_handler($errno, $errmsg, $file, $line, $vars) {
                   52440:     if ((defined('E_STRICT') && $errno & E_STRICT) || (defined('E_DEPRECATED') &&
                   52441:           $errno & E_DEPRECATED) || !error_reporting()) {
                   52442:         if (defined('E_STRICT') && $errno & E_STRICT) {
                   52443:             return; // E_STRICT
                   52444:         }
                   52445:         if (defined('E_DEPRECATED') && $errno & E_DEPRECATED) {
                   52446:             return; // E_DEPRECATED
                   52447:         }
                   52448:         if ($GLOBALS['config']->get('verbose') < 4) {
                   52449:             return false; // @silenced error, show all if debug is high enough
                   52450:         }
                   52451:     }
                   52452:     $errortype = array (
                   52453:         E_ERROR   =>  "Error",
                   52454:         E_WARNING   =>  "Warning",
                   52455:         E_PARSE   =>  "Parsing Error",
                   52456:         E_NOTICE   =>  "Notice",
                   52457:         E_CORE_ERROR  =>  "Core Error",
                   52458:         E_CORE_WARNING  =>  "Core Warning",
                   52459:         E_COMPILE_ERROR  =>  "Compile Error",
                   52460:         E_COMPILE_WARNING =>  "Compile Warning",
                   52461:         E_USER_ERROR =>  "User Error",
                   52462:         E_USER_WARNING =>  "User Warning",
                   52463:         E_USER_NOTICE =>  "User Notice"
                   52464:     );
                   52465:     $prefix = $errortype[$errno];
                   52466:     global $_PEAR_PHPDIR;
                   52467:     if (stristr($file, $_PEAR_PHPDIR)) {
                   52468:         $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
                   52469:     } else {
                   52470:         $file = basename($file);
                   52471:     }
                   52472:     print "\n$prefix: $errmsg in $file on line $line\n";
                   52473:     return false;
                   52474: }
                   52475: 
                   52476: 
                   52477: /*
                   52478:  * Local variables:
                   52479:  * tab-width: 4
                   52480:  * c-basic-offset: 4
                   52481:  * indent-tabs-mode: nil
                   52482:  * mode: php
                   52483:  * End:
                   52484:  */
                   52485: // vim600:syn=phpPEAR-1.9.4/scripts/peclcmd.php0000644000076500000240000000163611605156760015053 0ustar  helgistaff<?php
                   52486: /**
                   52487:  * PEAR, the PHP Extension and Application Repository
                   52488:  *
                   52489:  * Command line interface
                   52490:  *
                   52491:  * PHP versions 4 and 5
                   52492:  *
                   52493:  * @category   pear
                   52494:  * @package    PEAR
                   52495:  * @author     Stig Bakken <ssb@php.net>
                   52496:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   52497:  * @copyright  1997-2009 The Authors
                   52498:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52499:  * @version    CVS: $Id: peclcmd.php 313023 2011-07-06 19:17:11Z dufuz $
                   52500:  * @link       http://pear.php.net/package/PEAR
                   52501:  */
                   52502: 
                   52503: /**
                   52504:  * @nodep Gtk
                   52505:  */
                   52506: if ('@include_path@' != '@'.'include_path'.'@') {
                   52507:     ini_set('include_path', '@include_path@');
                   52508:     $raw = false;
                   52509: } else {
                   52510:     // this is a raw, uninstalled pear, either a cvs checkout, or php distro
                   52511:     $raw = true;
                   52512: }
                   52513: define('PEAR_RUNTYPE', 'pecl');
                   52514: require_once 'pearcmd.php';
                   52515: /*
                   52516:  * Local variables:
                   52517:  * tab-width: 4
                   52518:  * c-basic-offset: 4
                   52519:  * indent-tabs-mode: nil
                   52520:  * mode: php
                   52521:  * End:
                   52522:  */
                   52523: // vim600:syn=php
                   52524: 
                   52525: ?>
                   52526: PEAR-1.9.4/LICENSE0000644000076500000240000000270511605156760012247 0ustar  helgistaffCopyright (c) 1997-2009,
                   52527:  Stig Bakken <ssb@php.net>,
                   52528:  Gregory Beaver <cellog@php.net>,
                   52529:  Helgi 脼ormar 脼orbj枚rnsson <helgi@php.net>,
                   52530:  Tomas V.V.Cox <cox@idecnet.com>,
                   52531:  Martin Jansen <mj@php.net>.
                   52532: All rights reserved.
                   52533: 
                   52534: Redistribution and use in source and binary forms, with or without
                   52535: modification, are permitted provided that the following conditions are met:
                   52536: 
                   52537:     * Redistributions of source code must retain the above copyright notice,
                   52538:       this list of conditions and the following disclaimer.
                   52539:     * Redistributions in binary form must reproduce the above copyright
                   52540:       notice, this list of conditions and the following disclaimer in the
                   52541:       documentation and/or other materials provided with the distribution.
                   52542: 
                   52543: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   52544: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   52545: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   52546: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   52547: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   52548: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   52549: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   52550: CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   52551: OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   52552: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   52553: PEAR-1.9.4/INSTALL0000644000076500000240000000425111605156760012271 0ustar  helgistaffPEAR - The PEAR Installer
                   52554: =========================
                   52555: Installing the PEAR Installer.
                   52556: 
                   52557: You should install PEAR on a local development machine first.  Installing
                   52558: PEAR on a remote production machine should only be done after you are
                   52559: familiar with PEAR and have tested code using PEAR on your development
                   52560: machine.
                   52561: 
                   52562: There are two methods of installing PEAR
                   52563:  - PEAR bundled in PHP
                   52564:  - go-pear
                   52565: 
                   52566: We will first examine how to install PEAR that is bundled with PHP.
                   52567: 
                   52568: Microsoft Windows
                   52569: =================
                   52570: If you are running PHP 5.2.0 or newer, simply download and
                   52571: run the windows installer (.msi) and PEAR can be automatically
                   52572: installed.
                   52573: 
                   52574: Otherwise, for older PHP versions, download the .zip of windows,
                   52575: there is a script included with your PHP distribution that is called
                   52576: "go-pear".  You must open a command box in order to run it.  Click
                   52577: "start" then click "Run..." and type "cmd.exe" to open a command box.
                   52578: Use "cd" to change directory to the location of PHP where you unzipped it,
                   52579: and run the go-pear command.
                   52580: 
                   52581: Unix
                   52582: ====
                   52583: When compiling PHP from source, you simply need to include the
                   52584: --with-pear directive on the "./configure" command.  This is "on"
                   52585: by default in most PHP versions, but it doesn't hurt to list it
                   52586: explicitly.  You should also consider enabling the zlib extension via
                   52587: --enable-zlib, so that the PEAR installer will be able to handle gzipped
                   52588: files (i.e. smaller package files for faster downloads).  Later, when you
                   52589: run "make install" to install PHP itself, part of the process will be
                   52590: prompts that ask you where you want PEAR to be installed.
                   52591: 
                   52592: go-pear
                   52593: =======
                   52594: For users who cannot perform the above steps, or who wish to obtain the
                   52595: latest PEAR with a slightly higher risk of failure, use go-pear.  go-pear
                   52596: is obtained by downloading http://pear.php.net/go-pear and saving it as go-pear.php.
                   52597: After downloading, simply run "php go-pear.php" or open it in a web browser
                   52598: (windows only) to download and install PEAR.
                   52599: 
                   52600: You can always ask general installation questions on pear-general@lists.php.net,
                   52601: a public mailing list devoted to support for PEAR packages and installation-
                   52602: related issues.
                   52603: 
                   52604: Happy PHPing, we hope PEAR will be a great tool for your development work!
                   52605: 
                   52606: $Id: INSTALL 313023 2011-07-06 19:17:11Z dufuz $PEAR-1.9.4/package.dtd0000644000076500000240000000647711605156760013344 0ustar  helgistaff<!--
                   52607:      $Id: package.dtd,v 1.38 2005-11-12 02:23:07 cellog Exp $
                   52608: 
                   52609:      This is the PEAR package description, version 1.0.
                   52610:      It should be used with the informal public identifier:
                   52611: 
                   52612:          "-//PHP Group//DTD PEAR Package 1.0//EN//XML"
                   52613: 
                   52614:      Copyright (c) 1997-2005 The PHP Group             
                   52615: 
                   52616:      This source file is subject to version 3.00 of the PHP license,
                   52617:      that is bundled with this package in the file LICENSE, and is
                   52618:      available at through the world-wide-web at
                   52619:      http://www.php.net/license/3_0.txt. 
                   52620:      If you did not receive a copy of the PHP license and are unable to
                   52621:      obtain it through the world-wide-web, please send a note to
                   52622:      license@php.net so we can mail you a copy immediately.
                   52623: 
                   52624:      Authors:
                   52625:          Stig S. Bakken <ssb@fast.no>
                   52626:          Gregory Beaver <cellog@php.net>
                   52627: 
                   52628:   -->
                   52629: <!ENTITY % NUMBER "CDATA">
                   52630: <!ELEMENT package (name,summary,description,license?,maintainers,release,changelog?)>
                   52631: <!ATTLIST package type    (source|binary|empty) "empty"
                   52632:                   version CDATA                 #REQUIRED
                   52633:                   packagerversion CDATA         #IMPLIED>
                   52634: 
                   52635: <!ELEMENT name (#PCDATA)>
                   52636: 
                   52637: <!ELEMENT summary (#PCDATA)>
                   52638: 
                   52639: <!ELEMENT license (#PCDATA)>
                   52640: 
                   52641: <!ELEMENT description (#PCDATA)>
                   52642: 
                   52643: <!ELEMENT maintainers (maintainer)+>
                   52644: 
                   52645: <!ELEMENT maintainer (user|role|name|email)+>
                   52646: 
                   52647: <!ELEMENT user (#PCDATA)>
                   52648: 
                   52649: <!ELEMENT role (#PCDATA)>
                   52650: 
                   52651: <!ELEMENT email (#PCDATA)>
                   52652: 
                   52653: <!ELEMENT changelog (release)+>
                   52654: 
                   52655: <!ELEMENT release (version,date,license,state,notes,warnings?,provides*,deps?,configureoptions?,filelist?)>
                   52656: 
                   52657: <!ELEMENT version (#PCDATA)>
                   52658: 
                   52659: <!ELEMENT date (#PCDATA)>
                   52660: 
                   52661: <!ELEMENT state (#PCDATA)>
                   52662: 
                   52663: <!ELEMENT notes (#PCDATA)>
                   52664: 
                   52665: <!ELEMENT warnings (#PCDATA)>
                   52666: 
                   52667: <!ELEMENT deps (dep*)>
                   52668: 
                   52669: <!ELEMENT dep (#PCDATA)>
                   52670: <!ATTLIST dep type    (pkg|ext|php) #REQUIRED
                   52671:                               rel     (has|eq|lt|le|gt|ge)                          #IMPLIED
                   52672:                               version CDATA                                     #IMPLIED
                   52673:                               optional (yes|no)     'no'>
                   52674: 
                   52675: <!ELEMENT configureoptions (configureoption)+>
                   52676: 
                   52677: <!ELEMENT configureoption EMPTY>
                   52678: <!ATTLIST configureoption name CDATA #REQUIRED
                   52679:                                            default CDATA #IMPLIED
                   52680:                                            prompt CDATA #REQUIRED>
                   52681: 
                   52682: <!ELEMENT provides EMPTY>
                   52683: <!ATTLIST provides type (ext|prog|class|function|feature|api) #REQUIRED
                   52684:                                 name CDATA #REQUIRED
                   52685:                                 extends CDATA #IMPLIED>
                   52686: <!ELEMENT filelist (dir|file)+>
                   52687: 
                   52688: <!ELEMENT dir (dir|file)+>
                   52689: <!ATTLIST dir name           CDATA #REQUIRED
                   52690:               role           (php|ext|src|test|doc|data|script) 'php'
                   52691:               baseinstalldir CDATA #IMPLIED>
                   52692: 
                   52693: <!ELEMENT file (replace*)>
                   52694: <!ATTLIST file role           (php|ext|src|test|doc|data|script) 'php'
                   52695:                debug          (na|on|off)        'na'
                   52696:                format         CDATA              #IMPLIED
                   52697:                baseinstalldir CDATA              #IMPLIED
                   52698:                platform       CDATA              #IMPLIED
                   52699:                md5sum         CDATA              #IMPLIED
                   52700:                name           CDATA              #REQUIRED
                   52701:                install-as     CDATA              #IMPLIED>
                   52702: 
                   52703: <!ELEMENT replace EMPTY>
                   52704: <!ATTLIST replace type (php-const|pear-config|package-info) #REQUIRED
                   52705:                               from CDATA #REQUIRED
                   52706:                               to CDATA #REQUIRED>
                   52707: 
                   52708: 
                   52709: PEAR-1.9.4/PEAR5.php0000644000076500000240000000207711605156760012571 0ustar  helgistaff<?php
                   52710: /**
                   52711:  * This is only meant for PHP 5 to get rid of certain strict warning
                   52712:  * that doesn't get hidden since it's in the shutdown function
                   52713:  */
                   52714: class PEAR5
                   52715: {
                   52716:     /**
                   52717:     * If you have a class that's mostly/entirely static, and you need static
                   52718:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   52719:     * do this: $myVar = &PEAR5::getStaticProperty('myclass', 'myVar');
                   52720:     * You MUST use a reference, or they will not persist!
                   52721:     *
                   52722:     * @access public
                   52723:     * @param  string $class  The calling classname, to prevent clashes
                   52724:     * @param  string $var    The variable to retrieve.
                   52725:     * @return mixed   A reference to the variable. If not set it will be
                   52726:     *                 auto initialised to NULL.
                   52727:     */
                   52728:     static function &getStaticProperty($class, $var)
                   52729:     {
                   52730:         static $properties;
                   52731:         if (!isset($properties[$class])) {
                   52732:             $properties[$class] = array();
                   52733:         }
                   52734: 
                   52735:         if (!array_key_exists($var, $properties[$class])) {
                   52736:             $properties[$class][$var] = null;
                   52737:         }
                   52738: 
                   52739:         return $properties[$class][$var];
                   52740:     }
                   52741: }PEAR-1.9.4/PEAR.php0000644000076500000240000010215111605156760012476 0ustar  helgistaff<?php
                   52742: /**
                   52743:  * PEAR, the PHP Extension and Application Repository
                   52744:  *
                   52745:  * PEAR class and PEAR_Error class
                   52746:  *
                   52747:  * PHP versions 4 and 5
                   52748:  *
                   52749:  * @category   pear
                   52750:  * @package    PEAR
                   52751:  * @author     Sterling Hughes <sterling@php.net>
                   52752:  * @author     Stig Bakken <ssb@php.net>
                   52753:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   52754:  * @author     Greg Beaver <cellog@php.net>
                   52755:  * @copyright  1997-2010 The Authors
                   52756:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52757:  * @version    CVS: $Id: PEAR.php 313023 2011-07-06 19:17:11Z dufuz $
                   52758:  * @link       http://pear.php.net/package/PEAR
                   52759:  * @since      File available since Release 0.1
                   52760:  */
                   52761: 
                   52762: /**#@+
                   52763:  * ERROR constants
                   52764:  */
                   52765: define('PEAR_ERROR_RETURN',     1);
                   52766: define('PEAR_ERROR_PRINT',      2);
                   52767: define('PEAR_ERROR_TRIGGER',    4);
                   52768: define('PEAR_ERROR_DIE',        8);
                   52769: define('PEAR_ERROR_CALLBACK',  16);
                   52770: /**
                   52771:  * WARNING: obsolete
                   52772:  * @deprecated
                   52773:  */
                   52774: define('PEAR_ERROR_EXCEPTION', 32);
                   52775: /**#@-*/
                   52776: define('PEAR_ZE2', (function_exists('version_compare') &&
                   52777:                     version_compare(zend_version(), "2-dev", "ge")));
                   52778: 
                   52779: if (substr(PHP_OS, 0, 3) == 'WIN') {
                   52780:     define('OS_WINDOWS', true);
                   52781:     define('OS_UNIX',    false);
                   52782:     define('PEAR_OS',    'Windows');
                   52783: } else {
                   52784:     define('OS_WINDOWS', false);
                   52785:     define('OS_UNIX',    true);
                   52786:     define('PEAR_OS',    'Unix'); // blatant assumption
                   52787: }
                   52788: 
                   52789: $GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
                   52790: $GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
                   52791: $GLOBALS['_PEAR_destructor_object_list'] = array();
                   52792: $GLOBALS['_PEAR_shutdown_funcs']         = array();
                   52793: $GLOBALS['_PEAR_error_handler_stack']    = array();
                   52794: 
                   52795: @ini_set('track_errors', true);
                   52796: 
                   52797: /**
                   52798:  * Base class for other PEAR classes.  Provides rudimentary
                   52799:  * emulation of destructors.
                   52800:  *
                   52801:  * If you want a destructor in your class, inherit PEAR and make a
                   52802:  * destructor method called _yourclassname (same name as the
                   52803:  * constructor, but with a "_" prefix).  Also, in your constructor you
                   52804:  * have to call the PEAR constructor: $this->PEAR();.
                   52805:  * The destructor method will be called without parameters.  Note that
                   52806:  * at in some SAPI implementations (such as Apache), any output during
                   52807:  * the request shutdown (in which destructors are called) seems to be
                   52808:  * discarded.  If you need to get any debug information from your
                   52809:  * destructor, use error_log(), syslog() or something similar.
                   52810:  *
                   52811:  * IMPORTANT! To use the emulated destructors you need to create the
                   52812:  * objects by reference: $obj =& new PEAR_child;
                   52813:  *
                   52814:  * @category   pear
                   52815:  * @package    PEAR
                   52816:  * @author     Stig Bakken <ssb@php.net>
                   52817:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   52818:  * @author     Greg Beaver <cellog@php.net>
                   52819:  * @copyright  1997-2006 The PHP Group
                   52820:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52821:  * @version    Release: 1.9.4
                   52822:  * @link       http://pear.php.net/package/PEAR
                   52823:  * @see        PEAR_Error
                   52824:  * @since      Class available since PHP 4.0.2
                   52825:  * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
                   52826:  */
                   52827: class PEAR
                   52828: {
                   52829:     /**
                   52830:      * Whether to enable internal debug messages.
                   52831:      *
                   52832:      * @var     bool
                   52833:      * @access  private
                   52834:      */
                   52835:     var $_debug = false;
                   52836: 
                   52837:     /**
                   52838:      * Default error mode for this object.
                   52839:      *
                   52840:      * @var     int
                   52841:      * @access  private
                   52842:      */
                   52843:     var $_default_error_mode = null;
                   52844: 
                   52845:     /**
                   52846:      * Default error options used for this object when error mode
                   52847:      * is PEAR_ERROR_TRIGGER.
                   52848:      *
                   52849:      * @var     int
                   52850:      * @access  private
                   52851:      */
                   52852:     var $_default_error_options = null;
                   52853: 
                   52854:     /**
                   52855:      * Default error handler (callback) for this object, if error mode is
                   52856:      * PEAR_ERROR_CALLBACK.
                   52857:      *
                   52858:      * @var     string
                   52859:      * @access  private
                   52860:      */
                   52861:     var $_default_error_handler = '';
                   52862: 
                   52863:     /**
                   52864:      * Which class to use for error objects.
                   52865:      *
                   52866:      * @var     string
                   52867:      * @access  private
                   52868:      */
                   52869:     var $_error_class = 'PEAR_Error';
                   52870: 
                   52871:     /**
                   52872:      * An array of expected errors.
                   52873:      *
                   52874:      * @var     array
                   52875:      * @access  private
                   52876:      */
                   52877:     var $_expected_errors = array();
                   52878: 
                   52879:     /**
                   52880:      * Constructor.  Registers this object in
                   52881:      * $_PEAR_destructor_object_list for destructor emulation if a
                   52882:      * destructor object exists.
                   52883:      *
                   52884:      * @param string $error_class  (optional) which class to use for
                   52885:      *        error objects, defaults to PEAR_Error.
                   52886:      * @access public
                   52887:      * @return void
                   52888:      */
                   52889:     function PEAR($error_class = null)
                   52890:     {
                   52891:         $classname = strtolower(get_class($this));
                   52892:         if ($this->_debug) {
                   52893:             print "PEAR constructor called, class=$classname\n";
                   52894:         }
                   52895: 
                   52896:         if ($error_class !== null) {
                   52897:             $this->_error_class = $error_class;
                   52898:         }
                   52899: 
                   52900:         while ($classname && strcasecmp($classname, "pear")) {
                   52901:             $destructor = "_$classname";
                   52902:             if (method_exists($this, $destructor)) {
                   52903:                 global $_PEAR_destructor_object_list;
                   52904:                 $_PEAR_destructor_object_list[] = &$this;
                   52905:                 if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   52906:                     register_shutdown_function("_PEAR_call_destructors");
                   52907:                     $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   52908:                 }
                   52909:                 break;
                   52910:             } else {
                   52911:                 $classname = get_parent_class($classname);
                   52912:             }
                   52913:         }
                   52914:     }
                   52915: 
                   52916:     /**
                   52917:      * Destructor (the emulated type of...).  Does nothing right now,
                   52918:      * but is included for forward compatibility, so subclass
                   52919:      * destructors should always call it.
                   52920:      *
                   52921:      * See the note in the class desciption about output from
                   52922:      * destructors.
                   52923:      *
                   52924:      * @access public
                   52925:      * @return void
                   52926:      */
                   52927:     function _PEAR() {
                   52928:         if ($this->_debug) {
                   52929:             printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
                   52930:         }
                   52931:     }
                   52932: 
                   52933:     /**
                   52934:     * If you have a class that's mostly/entirely static, and you need static
                   52935:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   52936:     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
                   52937:     * You MUST use a reference, or they will not persist!
                   52938:     *
                   52939:     * @access public
                   52940:     * @param  string $class  The calling classname, to prevent clashes
                   52941:     * @param  string $var    The variable to retrieve.
                   52942:     * @return mixed   A reference to the variable. If not set it will be
                   52943:     *                 auto initialised to NULL.
                   52944:     */
                   52945:     function &getStaticProperty($class, $var)
                   52946:     {
                   52947:         static $properties;
                   52948:         if (!isset($properties[$class])) {
                   52949:             $properties[$class] = array();
                   52950:         }
                   52951: 
                   52952:         if (!array_key_exists($var, $properties[$class])) {
                   52953:             $properties[$class][$var] = null;
                   52954:         }
                   52955: 
                   52956:         return $properties[$class][$var];
                   52957:     }
                   52958: 
                   52959:     /**
                   52960:     * Use this function to register a shutdown method for static
                   52961:     * classes.
                   52962:     *
                   52963:     * @access public
                   52964:     * @param  mixed $func  The function name (or array of class/method) to call
                   52965:     * @param  mixed $args  The arguments to pass to the function
                   52966:     * @return void
                   52967:     */
                   52968:     function registerShutdownFunc($func, $args = array())
                   52969:     {
                   52970:         // if we are called statically, there is a potential
                   52971:         // that no shutdown func is registered.  Bug #6445
                   52972:         if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   52973:             register_shutdown_function("_PEAR_call_destructors");
                   52974:             $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   52975:         }
                   52976:         $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
                   52977:     }
                   52978: 
                   52979:     /**
                   52980:      * Tell whether a value is a PEAR error.
                   52981:      *
                   52982:      * @param   mixed $data   the value to test
                   52983:      * @param   int   $code   if $data is an error object, return true
                   52984:      *                        only if $code is a string and
                   52985:      *                        $obj->getMessage() == $code or
                   52986:      *                        $code is an integer and $obj->getCode() == $code
                   52987:      * @access  public
                   52988:      * @return  bool    true if parameter is an error
                   52989:      */
                   52990:     function isError($data, $code = null)
                   52991:     {
                   52992:         if (!is_a($data, 'PEAR_Error')) {
                   52993:             return false;
                   52994:         }
                   52995: 
                   52996:         if (is_null($code)) {
                   52997:             return true;
                   52998:         } elseif (is_string($code)) {
                   52999:             return $data->getMessage() == $code;
                   53000:         }
                   53001: 
                   53002:         return $data->getCode() == $code;
                   53003:     }
                   53004: 
                   53005:     /**
                   53006:      * Sets how errors generated by this object should be handled.
                   53007:      * Can be invoked both in objects and statically.  If called
                   53008:      * statically, setErrorHandling sets the default behaviour for all
                   53009:      * PEAR objects.  If called in an object, setErrorHandling sets
                   53010:      * the default behaviour for that object.
                   53011:      *
                   53012:      * @param int $mode
                   53013:      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   53014:      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   53015:      *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
                   53016:      *
                   53017:      * @param mixed $options
                   53018:      *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
                   53019:      *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   53020:      *
                   53021:      *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
                   53022:      *        to be the callback function or method.  A callback
                   53023:      *        function is a string with the name of the function, a
                   53024:      *        callback method is an array of two elements: the element
                   53025:      *        at index 0 is the object, and the element at index 1 is
                   53026:      *        the name of the method to call in the object.
                   53027:      *
                   53028:      *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
                   53029:      *        a printf format string used when printing the error
                   53030:      *        message.
                   53031:      *
                   53032:      * @access public
                   53033:      * @return void
                   53034:      * @see PEAR_ERROR_RETURN
                   53035:      * @see PEAR_ERROR_PRINT
                   53036:      * @see PEAR_ERROR_TRIGGER
                   53037:      * @see PEAR_ERROR_DIE
                   53038:      * @see PEAR_ERROR_CALLBACK
                   53039:      * @see PEAR_ERROR_EXCEPTION
                   53040:      *
                   53041:      * @since PHP 4.0.5
                   53042:      */
                   53043:     function setErrorHandling($mode = null, $options = null)
                   53044:     {
                   53045:         if (isset($this) && is_a($this, 'PEAR')) {
                   53046:             $setmode     = &$this->_default_error_mode;
                   53047:             $setoptions  = &$this->_default_error_options;
                   53048:         } else {
                   53049:             $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   53050:             $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   53051:         }
                   53052: 
                   53053:         switch ($mode) {
                   53054:             case PEAR_ERROR_EXCEPTION:
                   53055:             case PEAR_ERROR_RETURN:
                   53056:             case PEAR_ERROR_PRINT:
                   53057:             case PEAR_ERROR_TRIGGER:
                   53058:             case PEAR_ERROR_DIE:
                   53059:             case null:
                   53060:                 $setmode = $mode;
                   53061:                 $setoptions = $options;
                   53062:                 break;
                   53063: 
                   53064:             case PEAR_ERROR_CALLBACK:
                   53065:                 $setmode = $mode;
                   53066:                 // class/object method callback
                   53067:                 if (is_callable($options)) {
                   53068:                     $setoptions = $options;
                   53069:                 } else {
                   53070:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53071:                 }
                   53072:                 break;
                   53073: 
                   53074:             default:
                   53075:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53076:                 break;
                   53077:         }
                   53078:     }
                   53079: 
                   53080:     /**
                   53081:      * This method is used to tell which errors you expect to get.
                   53082:      * Expected errors are always returned with error mode
                   53083:      * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
                   53084:      * and this method pushes a new element onto it.  The list of
                   53085:      * expected errors are in effect until they are popped off the
                   53086:      * stack with the popExpect() method.
                   53087:      *
                   53088:      * Note that this method can not be called statically
                   53089:      *
                   53090:      * @param mixed $code a single error code or an array of error codes to expect
                   53091:      *
                   53092:      * @return int     the new depth of the "expected errors" stack
                   53093:      * @access public
                   53094:      */
                   53095:     function expectError($code = '*')
                   53096:     {
                   53097:         if (is_array($code)) {
                   53098:             array_push($this->_expected_errors, $code);
                   53099:         } else {
                   53100:             array_push($this->_expected_errors, array($code));
                   53101:         }
                   53102:         return count($this->_expected_errors);
                   53103:     }
                   53104: 
                   53105:     /**
                   53106:      * This method pops one element off the expected error codes
                   53107:      * stack.
                   53108:      *
                   53109:      * @return array   the list of error codes that were popped
                   53110:      */
                   53111:     function popExpect()
                   53112:     {
                   53113:         return array_pop($this->_expected_errors);
                   53114:     }
                   53115: 
                   53116:     /**
                   53117:      * This method checks unsets an error code if available
                   53118:      *
                   53119:      * @param mixed error code
                   53120:      * @return bool true if the error code was unset, false otherwise
                   53121:      * @access private
                   53122:      * @since PHP 4.3.0
                   53123:      */
                   53124:     function _checkDelExpect($error_code)
                   53125:     {
                   53126:         $deleted = false;
                   53127:         foreach ($this->_expected_errors as $key => $error_array) {
                   53128:             if (in_array($error_code, $error_array)) {
                   53129:                 unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
                   53130:                 $deleted = true;
                   53131:             }
                   53132: 
                   53133:             // clean up empty arrays
                   53134:             if (0 == count($this->_expected_errors[$key])) {
                   53135:                 unset($this->_expected_errors[$key]);
                   53136:             }
                   53137:         }
                   53138: 
                   53139:         return $deleted;
                   53140:     }
                   53141: 
                   53142:     /**
                   53143:      * This method deletes all occurences of the specified element from
                   53144:      * the expected error codes stack.
                   53145:      *
                   53146:      * @param  mixed $error_code error code that should be deleted
                   53147:      * @return mixed list of error codes that were deleted or error
                   53148:      * @access public
                   53149:      * @since PHP 4.3.0
                   53150:      */
                   53151:     function delExpect($error_code)
                   53152:     {
                   53153:         $deleted = false;
                   53154:         if ((is_array($error_code) && (0 != count($error_code)))) {
                   53155:             // $error_code is a non-empty array here; we walk through it trying
                   53156:             // to unset all values
                   53157:             foreach ($error_code as $key => $error) {
                   53158:                 $deleted =  $this->_checkDelExpect($error) ? true : false;
                   53159:             }
                   53160: 
                   53161:             return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   53162:         } elseif (!empty($error_code)) {
                   53163:             // $error_code comes alone, trying to unset it
                   53164:             if ($this->_checkDelExpect($error_code)) {
                   53165:                 return true;
                   53166:             }
                   53167: 
                   53168:             return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   53169:         }
                   53170: 
                   53171:         // $error_code is empty
                   53172:         return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
                   53173:     }
                   53174: 
                   53175:     /**
                   53176:      * This method is a wrapper that returns an instance of the
                   53177:      * configured error class with this object's default error
                   53178:      * handling applied.  If the $mode and $options parameters are not
                   53179:      * specified, the object's defaults are used.
                   53180:      *
                   53181:      * @param mixed $message a text error message or a PEAR error object
                   53182:      *
                   53183:      * @param int $code      a numeric error code (it is up to your class
                   53184:      *                  to define these if you want to use codes)
                   53185:      *
                   53186:      * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   53187:      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   53188:      *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
                   53189:      *
                   53190:      * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
                   53191:      *                  specifies the PHP-internal error level (one of
                   53192:      *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   53193:      *                  If $mode is PEAR_ERROR_CALLBACK, this
                   53194:      *                  parameter specifies the callback function or
                   53195:      *                  method.  In other error modes this parameter
                   53196:      *                  is ignored.
                   53197:      *
                   53198:      * @param string $userinfo If you need to pass along for example debug
                   53199:      *                  information, this parameter is meant for that.
                   53200:      *
                   53201:      * @param string $error_class The returned error object will be
                   53202:      *                  instantiated from this class, if specified.
                   53203:      *
                   53204:      * @param bool $skipmsg If true, raiseError will only pass error codes,
                   53205:      *                  the error message parameter will be dropped.
                   53206:      *
                   53207:      * @access public
                   53208:      * @return object   a PEAR error object
                   53209:      * @see PEAR::setErrorHandling
                   53210:      * @since PHP 4.0.5
                   53211:      */
                   53212:     function &raiseError($message = null,
                   53213:                          $code = null,
                   53214:                          $mode = null,
                   53215:                          $options = null,
                   53216:                          $userinfo = null,
                   53217:                          $error_class = null,
                   53218:                          $skipmsg = false)
                   53219:     {
                   53220:         // The error is yet a PEAR error object
                   53221:         if (is_object($message)) {
                   53222:             $code        = $message->getCode();
                   53223:             $userinfo    = $message->getUserInfo();
                   53224:             $error_class = $message->getType();
                   53225:             $message->error_message_prefix = '';
                   53226:             $message     = $message->getMessage();
                   53227:         }
                   53228: 
                   53229:         if (
                   53230:             isset($this) &&
                   53231:             isset($this->_expected_errors) &&
                   53232:             count($this->_expected_errors) > 0 &&
                   53233:             count($exp = end($this->_expected_errors))
                   53234:         ) {
                   53235:             if ($exp[0] == "*" ||
                   53236:                 (is_int(reset($exp)) && in_array($code, $exp)) ||
                   53237:                 (is_string(reset($exp)) && in_array($message, $exp))
                   53238:             ) {
                   53239:                 $mode = PEAR_ERROR_RETURN;
                   53240:             }
                   53241:         }
                   53242: 
                   53243:         // No mode given, try global ones
                   53244:         if ($mode === null) {
                   53245:             // Class error handler
                   53246:             if (isset($this) && isset($this->_default_error_mode)) {
                   53247:                 $mode    = $this->_default_error_mode;
                   53248:                 $options = $this->_default_error_options;
                   53249:             // Global error handler
                   53250:             } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
                   53251:                 $mode    = $GLOBALS['_PEAR_default_error_mode'];
                   53252:                 $options = $GLOBALS['_PEAR_default_error_options'];
                   53253:             }
                   53254:         }
                   53255: 
                   53256:         if ($error_class !== null) {
                   53257:             $ec = $error_class;
                   53258:         } elseif (isset($this) && isset($this->_error_class)) {
                   53259:             $ec = $this->_error_class;
                   53260:         } else {
                   53261:             $ec = 'PEAR_Error';
                   53262:         }
                   53263: 
                   53264:         if (intval(PHP_VERSION) < 5) {
                   53265:             // little non-eval hack to fix bug #12147
                   53266:             include 'PEAR/FixPHP5PEARWarnings.php';
                   53267:             return $a;
                   53268:         }
                   53269: 
                   53270:         if ($skipmsg) {
                   53271:             $a = new $ec($code, $mode, $options, $userinfo);
                   53272:         } else {
                   53273:             $a = new $ec($message, $code, $mode, $options, $userinfo);
                   53274:         }
                   53275: 
                   53276:         return $a;
                   53277:     }
                   53278: 
                   53279:     /**
                   53280:      * Simpler form of raiseError with fewer options.  In most cases
                   53281:      * message, code and userinfo are enough.
                   53282:      *
                   53283:      * @param mixed $message a text error message or a PEAR error object
                   53284:      *
                   53285:      * @param int $code      a numeric error code (it is up to your class
                   53286:      *                  to define these if you want to use codes)
                   53287:      *
                   53288:      * @param string $userinfo If you need to pass along for example debug
                   53289:      *                  information, this parameter is meant for that.
                   53290:      *
                   53291:      * @access public
                   53292:      * @return object   a PEAR error object
                   53293:      * @see PEAR::raiseError
                   53294:      */
                   53295:     function &throwError($message = null, $code = null, $userinfo = null)
                   53296:     {
                   53297:         if (isset($this) && is_a($this, 'PEAR')) {
                   53298:             $a = &$this->raiseError($message, $code, null, null, $userinfo);
                   53299:             return $a;
                   53300:         }
                   53301: 
                   53302:         $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
                   53303:         return $a;
                   53304:     }
                   53305: 
                   53306:     function staticPushErrorHandling($mode, $options = null)
                   53307:     {
                   53308:         $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
                   53309:         $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   53310:         $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   53311:         $stack[] = array($def_mode, $def_options);
                   53312:         switch ($mode) {
                   53313:             case PEAR_ERROR_EXCEPTION:
                   53314:             case PEAR_ERROR_RETURN:
                   53315:             case PEAR_ERROR_PRINT:
                   53316:             case PEAR_ERROR_TRIGGER:
                   53317:             case PEAR_ERROR_DIE:
                   53318:             case null:
                   53319:                 $def_mode = $mode;
                   53320:                 $def_options = $options;
                   53321:                 break;
                   53322: 
                   53323:             case PEAR_ERROR_CALLBACK:
                   53324:                 $def_mode = $mode;
                   53325:                 // class/object method callback
                   53326:                 if (is_callable($options)) {
                   53327:                     $def_options = $options;
                   53328:                 } else {
                   53329:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53330:                 }
                   53331:                 break;
                   53332: 
                   53333:             default:
                   53334:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53335:                 break;
                   53336:         }
                   53337:         $stack[] = array($mode, $options);
                   53338:         return true;
                   53339:     }
                   53340: 
                   53341:     function staticPopErrorHandling()
                   53342:     {
                   53343:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53344:         $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   53345:         $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   53346:         array_pop($stack);
                   53347:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   53348:         array_pop($stack);
                   53349:         switch ($mode) {
                   53350:             case PEAR_ERROR_EXCEPTION:
                   53351:             case PEAR_ERROR_RETURN:
                   53352:             case PEAR_ERROR_PRINT:
                   53353:             case PEAR_ERROR_TRIGGER:
                   53354:             case PEAR_ERROR_DIE:
                   53355:             case null:
                   53356:                 $setmode = $mode;
                   53357:                 $setoptions = $options;
                   53358:                 break;
                   53359: 
                   53360:             case PEAR_ERROR_CALLBACK:
                   53361:                 $setmode = $mode;
                   53362:                 // class/object method callback
                   53363:                 if (is_callable($options)) {
                   53364:                     $setoptions = $options;
                   53365:                 } else {
                   53366:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53367:                 }
                   53368:                 break;
                   53369: 
                   53370:             default:
                   53371:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53372:                 break;
                   53373:         }
                   53374:         return true;
                   53375:     }
                   53376: 
                   53377:     /**
                   53378:      * Push a new error handler on top of the error handler options stack. With this
                   53379:      * you can easily override the actual error handler for some code and restore
                   53380:      * it later with popErrorHandling.
                   53381:      *
                   53382:      * @param mixed $mode (same as setErrorHandling)
                   53383:      * @param mixed $options (same as setErrorHandling)
                   53384:      *
                   53385:      * @return bool Always true
                   53386:      *
                   53387:      * @see PEAR::setErrorHandling
                   53388:      */
                   53389:     function pushErrorHandling($mode, $options = null)
                   53390:     {
                   53391:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53392:         if (isset($this) && is_a($this, 'PEAR')) {
                   53393:             $def_mode    = &$this->_default_error_mode;
                   53394:             $def_options = &$this->_default_error_options;
                   53395:         } else {
                   53396:             $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   53397:             $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   53398:         }
                   53399:         $stack[] = array($def_mode, $def_options);
                   53400: 
                   53401:         if (isset($this) && is_a($this, 'PEAR')) {
                   53402:             $this->setErrorHandling($mode, $options);
                   53403:         } else {
                   53404:             PEAR::setErrorHandling($mode, $options);
                   53405:         }
                   53406:         $stack[] = array($mode, $options);
                   53407:         return true;
                   53408:     }
                   53409: 
                   53410:     /**
                   53411:     * Pop the last error handler used
                   53412:     *
                   53413:     * @return bool Always true
                   53414:     *
                   53415:     * @see PEAR::pushErrorHandling
                   53416:     */
                   53417:     function popErrorHandling()
                   53418:     {
                   53419:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53420:         array_pop($stack);
                   53421:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   53422:         array_pop($stack);
                   53423:         if (isset($this) && is_a($this, 'PEAR')) {
                   53424:             $this->setErrorHandling($mode, $options);
                   53425:         } else {
                   53426:             PEAR::setErrorHandling($mode, $options);
                   53427:         }
                   53428:         return true;
                   53429:     }
                   53430: 
                   53431:     /**
                   53432:     * OS independant PHP extension load. Remember to take care
                   53433:     * on the correct extension name for case sensitive OSes.
                   53434:     *
                   53435:     * @param string $ext The extension name
                   53436:     * @return bool Success or not on the dl() call
                   53437:     */
                   53438:     function loadExtension($ext)
                   53439:     {
                   53440:         if (extension_loaded($ext)) {
                   53441:             return true;
                   53442:         }
                   53443: 
                   53444:         // if either returns true dl() will produce a FATAL error, stop that
                   53445:         if (
                   53446:             function_exists('dl') === false ||
                   53447:             ini_get('enable_dl') != 1 ||
                   53448:             ini_get('safe_mode') == 1
                   53449:         ) {
                   53450:             return false;
                   53451:         }
                   53452: 
                   53453:         if (OS_WINDOWS) {
                   53454:             $suffix = '.dll';
                   53455:         } elseif (PHP_OS == 'HP-UX') {
                   53456:             $suffix = '.sl';
                   53457:         } elseif (PHP_OS == 'AIX') {
                   53458:             $suffix = '.a';
                   53459:         } elseif (PHP_OS == 'OSX') {
                   53460:             $suffix = '.bundle';
                   53461:         } else {
                   53462:             $suffix = '.so';
                   53463:         }
                   53464: 
                   53465:         return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
                   53466:     }
                   53467: }
                   53468: 
                   53469: if (PEAR_ZE2) {
                   53470:     include_once 'PEAR5.php';
                   53471: }
                   53472: 
                   53473: function _PEAR_call_destructors()
                   53474: {
                   53475:     global $_PEAR_destructor_object_list;
                   53476:     if (is_array($_PEAR_destructor_object_list) &&
                   53477:         sizeof($_PEAR_destructor_object_list))
                   53478:     {
                   53479:         reset($_PEAR_destructor_object_list);
                   53480:         if (PEAR_ZE2) {
                   53481:             $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
                   53482:         } else {
                   53483:             $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
                   53484:         }
                   53485: 
                   53486:         if ($destructLifoExists) {
                   53487:             $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
                   53488:         }
                   53489: 
                   53490:         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
                   53491:             $classname = get_class($objref);
                   53492:             while ($classname) {
                   53493:                 $destructor = "_$classname";
                   53494:                 if (method_exists($objref, $destructor)) {
                   53495:                     $objref->$destructor();
                   53496:                     break;
                   53497:                 } else {
                   53498:                     $classname = get_parent_class($classname);
                   53499:                 }
                   53500:             }
                   53501:         }
                   53502:         // Empty the object list to ensure that destructors are
                   53503:         // not called more than once.
                   53504:         $_PEAR_destructor_object_list = array();
                   53505:     }
                   53506: 
                   53507:     // Now call the shutdown functions
                   53508:     if (
                   53509:         isset($GLOBALS['_PEAR_shutdown_funcs']) &&
                   53510:         is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
                   53511:         !empty($GLOBALS['_PEAR_shutdown_funcs'])
                   53512:     ) {
                   53513:         foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
                   53514:             call_user_func_array($value[0], $value[1]);
                   53515:         }
                   53516:     }
                   53517: }
                   53518: 
                   53519: /**
                   53520:  * Standard PEAR error class for PHP 4
                   53521:  *
                   53522:  * This class is supserseded by {@link PEAR_Exception} in PHP 5
                   53523:  *
                   53524:  * @category   pear
                   53525:  * @package    PEAR
                   53526:  * @author     Stig Bakken <ssb@php.net>
                   53527:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   53528:  * @author     Gregory Beaver <cellog@php.net>
                   53529:  * @copyright  1997-2006 The PHP Group
                   53530:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53531:  * @version    Release: 1.9.4
                   53532:  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
                   53533:  * @see        PEAR::raiseError(), PEAR::throwError()
                   53534:  * @since      Class available since PHP 4.0.2
                   53535:  */
                   53536: class PEAR_Error
                   53537: {
                   53538:     var $error_message_prefix = '';
                   53539:     var $mode                 = PEAR_ERROR_RETURN;
                   53540:     var $level                = E_USER_NOTICE;
                   53541:     var $code                 = -1;
                   53542:     var $message              = '';
                   53543:     var $userinfo             = '';
                   53544:     var $backtrace            = null;
                   53545: 
                   53546:     /**
                   53547:      * PEAR_Error constructor
                   53548:      *
                   53549:      * @param string $message  message
                   53550:      *
                   53551:      * @param int $code     (optional) error code
                   53552:      *
                   53553:      * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
                   53554:      * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
                   53555:      * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
                   53556:      *
                   53557:      * @param mixed $options   (optional) error level, _OR_ in the case of
                   53558:      * PEAR_ERROR_CALLBACK, the callback function or object/method
                   53559:      * tuple.
                   53560:      *
                   53561:      * @param string $userinfo (optional) additional user/debug info
                   53562:      *
                   53563:      * @access public
                   53564:      *
                   53565:      */
                   53566:     function PEAR_Error($message = 'unknown error', $code = null,
                   53567:                         $mode = null, $options = null, $userinfo = null)
                   53568:     {
                   53569:         if ($mode === null) {
                   53570:             $mode = PEAR_ERROR_RETURN;
                   53571:         }
                   53572:         $this->message   = $message;
                   53573:         $this->code      = $code;
                   53574:         $this->mode      = $mode;
                   53575:         $this->userinfo  = $userinfo;
                   53576: 
                   53577:         if (PEAR_ZE2) {
                   53578:             $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
                   53579:         } else {
                   53580:             $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
                   53581:         }
                   53582: 
                   53583:         if (!$skiptrace) {
                   53584:             $this->backtrace = debug_backtrace();
                   53585:             if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
                   53586:                 unset($this->backtrace[0]['object']);
                   53587:             }
                   53588:         }
                   53589: 
                   53590:         if ($mode & PEAR_ERROR_CALLBACK) {
                   53591:             $this->level = E_USER_NOTICE;
                   53592:             $this->callback = $options;
                   53593:         } else {
                   53594:             if ($options === null) {
                   53595:                 $options = E_USER_NOTICE;
                   53596:             }
                   53597: 
                   53598:             $this->level = $options;
                   53599:             $this->callback = null;
                   53600:         }
                   53601: 
                   53602:         if ($this->mode & PEAR_ERROR_PRINT) {
                   53603:             if (is_null($options) || is_int($options)) {
                   53604:                 $format = "%s";
                   53605:             } else {
                   53606:                 $format = $options;
                   53607:             }
                   53608: 
                   53609:             printf($format, $this->getMessage());
                   53610:         }
                   53611: 
                   53612:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   53613:             trigger_error($this->getMessage(), $this->level);
                   53614:         }
                   53615: 
                   53616:         if ($this->mode & PEAR_ERROR_DIE) {
                   53617:             $msg = $this->getMessage();
                   53618:             if (is_null($options) || is_int($options)) {
                   53619:                 $format = "%s";
                   53620:                 if (substr($msg, -1) != "\n") {
                   53621:                     $msg .= "\n";
                   53622:                 }
                   53623:             } else {
                   53624:                 $format = $options;
                   53625:             }
                   53626:             die(sprintf($format, $msg));
                   53627:         }
                   53628: 
                   53629:         if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
                   53630:             call_user_func($this->callback, $this);
                   53631:         }
                   53632: 
                   53633:         if ($this->mode & PEAR_ERROR_EXCEPTION) {
                   53634:             trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
                   53635:             eval('$e = new Exception($this->message, $this->code);throw($e);');
                   53636:         }
                   53637:     }
                   53638: 
                   53639:     /**
                   53640:      * Get the error mode from an error object.
                   53641:      *
                   53642:      * @return int error mode
                   53643:      * @access public
                   53644:      */
                   53645:     function getMode()
                   53646:     {
                   53647:         return $this->mode;
                   53648:     }
                   53649: 
                   53650:     /**
                   53651:      * Get the callback function/method from an error object.
                   53652:      *
                   53653:      * @return mixed callback function or object/method array
                   53654:      * @access public
                   53655:      */
                   53656:     function getCallback()
                   53657:     {
                   53658:         return $this->callback;
                   53659:     }
                   53660: 
                   53661:     /**
                   53662:      * Get the error message from an error object.
                   53663:      *
                   53664:      * @return  string  full error message
                   53665:      * @access public
                   53666:      */
                   53667:     function getMessage()
                   53668:     {
                   53669:         return ($this->error_message_prefix . $this->message);
                   53670:     }
                   53671: 
                   53672:     /**
                   53673:      * Get error code from an error object
                   53674:      *
                   53675:      * @return int error code
                   53676:      * @access public
                   53677:      */
                   53678:      function getCode()
                   53679:      {
                   53680:         return $this->code;
                   53681:      }
                   53682: 
                   53683:     /**
                   53684:      * Get the name of this error/exception.
                   53685:      *
                   53686:      * @return string error/exception name (type)
                   53687:      * @access public
                   53688:      */
                   53689:     function getType()
                   53690:     {
                   53691:         return get_class($this);
                   53692:     }
                   53693: 
                   53694:     /**
                   53695:      * Get additional user-supplied information.
                   53696:      *
                   53697:      * @return string user-supplied information
                   53698:      * @access public
                   53699:      */
                   53700:     function getUserInfo()
                   53701:     {
                   53702:         return $this->userinfo;
                   53703:     }
                   53704: 
                   53705:     /**
                   53706:      * Get additional debug information supplied by the application.
                   53707:      *
                   53708:      * @return string debug information
                   53709:      * @access public
                   53710:      */
                   53711:     function getDebugInfo()
                   53712:     {
                   53713:         return $this->getUserInfo();
                   53714:     }
                   53715: 
                   53716:     /**
                   53717:      * Get the call backtrace from where the error was generated.
                   53718:      * Supported with PHP 4.3.0 or newer.
                   53719:      *
                   53720:      * @param int $frame (optional) what frame to fetch
                   53721:      * @return array Backtrace, or NULL if not available.
                   53722:      * @access public
                   53723:      */
                   53724:     function getBacktrace($frame = null)
                   53725:     {
                   53726:         if (defined('PEAR_IGNORE_BACKTRACE')) {
                   53727:             return null;
                   53728:         }
                   53729:         if ($frame === null) {
                   53730:             return $this->backtrace;
                   53731:         }
                   53732:         return $this->backtrace[$frame];
                   53733:     }
                   53734: 
                   53735:     function addUserInfo($info)
                   53736:     {
                   53737:         if (empty($this->userinfo)) {
                   53738:             $this->userinfo = $info;
                   53739:         } else {
                   53740:             $this->userinfo .= " ** $info";
                   53741:         }
                   53742:     }
                   53743: 
                   53744:     function __toString()
                   53745:     {
                   53746:         return $this->getMessage();
                   53747:     }
                   53748: 
                   53749:     /**
                   53750:      * Make a string representation of this object.
                   53751:      *
                   53752:      * @return string a string with an object summary
                   53753:      * @access public
                   53754:      */
                   53755:     function toString()
                   53756:     {
                   53757:         $modes = array();
                   53758:         $levels = array(E_USER_NOTICE  => 'notice',
                   53759:                         E_USER_WARNING => 'warning',
                   53760:                         E_USER_ERROR   => 'error');
                   53761:         if ($this->mode & PEAR_ERROR_CALLBACK) {
                   53762:             if (is_array($this->callback)) {
                   53763:                 $callback = (is_object($this->callback[0]) ?
                   53764:                     strtolower(get_class($this->callback[0])) :
                   53765:                     $this->callback[0]) . '::' .
                   53766:                     $this->callback[1];
                   53767:             } else {
                   53768:                 $callback = $this->callback;
                   53769:             }
                   53770:             return sprintf('[%s: message="%s" code=%d mode=callback '.
                   53771:                            'callback=%s prefix="%s" info="%s"]',
                   53772:                            strtolower(get_class($this)), $this->message, $this->code,
                   53773:                            $callback, $this->error_message_prefix,
                   53774:                            $this->userinfo);
                   53775:         }
                   53776:         if ($this->mode & PEAR_ERROR_PRINT) {
                   53777:             $modes[] = 'print';
                   53778:         }
                   53779:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   53780:             $modes[] = 'trigger';
                   53781:         }
                   53782:         if ($this->mode & PEAR_ERROR_DIE) {
                   53783:             $modes[] = 'die';
                   53784:         }
                   53785:         if ($this->mode & PEAR_ERROR_RETURN) {
                   53786:             $modes[] = 'return';
                   53787:         }
                   53788:         return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
                   53789:                        'prefix="%s" info="%s"]',
                   53790:                        strtolower(get_class($this)), $this->message, $this->code,
                   53791:                        implode("|", $modes), $levels[$this->level],
                   53792:                        $this->error_message_prefix,
                   53793:                        $this->userinfo);
                   53794:     }
                   53795: }
                   53796: 
                   53797: /*
                   53798:  * Local Variables:
                   53799:  * mode: php
                   53800:  * tab-width: 4
                   53801:  * c-basic-offset: 4
                   53802:  * End:
                   53803:  */
                   53804: PEAR-1.9.4/README0000644000076500000240000000224511605156760012121 0ustar  helgistaffPEAR - The PEAR Installer
                   53805: =========================
                   53806: 
                   53807: What is the PEAR Installer?  What is PEAR?
                   53808: 
                   53809: PEAR is the PHP Extension and Application Repository, found at
                   53810: http://pear.php.net.  The PEAR Installer is this software, which
                   53811: contains executable files and PHP code that is used to download
                   53812: and install PEAR code from pear.php.net.
                   53813: 
                   53814: PEAR contains useful software libraries and applications such as
                   53815: MDB2 (database abstraction), HTML_QuickForm (HTML forms management),
                   53816: PhpDocumentor (auto-documentation generator), DB_DataObject
                   53817: (Data Access Abstraction), and many hundreds more.  Browse all
                   53818: available packages at http://pear.php.net, the list is constantly
                   53819: growing and updating to reflect improvements in the PHP language.
                   53820: 
                   53821: DOCUMENTATION
                   53822: =============
                   53823: 
                   53824: Documentation for PEAR can be found at http://pear.php.net/manual/.
                   53825: Installation documentation can be found in the INSTALL file included
                   53826: in this tarball.
                   53827: 
                   53828: WARNING: DO NOT RUN PEAR WITHOUT INSTALLING IT - if you downloaded this
                   53829: tarball manually, you MUST install it.  Read the instructions in INSTALL
                   53830: prior to use.
                   53831: 
                   53832: 
                   53833: Happy PHPing, we hope PEAR will be a great tool for your development work!
                   53834: 
                   53835: $Id: README 313023 2011-07-06 19:17:11Z dufuz $PEAR-1.9.4/System.php0000644000076500000240000004742311605156760013245 0ustar  helgistaff<?php
                   53836: /**
                   53837:  * File/Directory manipulation
                   53838:  *
                   53839:  * PHP versions 4 and 5
                   53840:  *
                   53841:  * @category   pear
                   53842:  * @package    System
                   53843:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   53844:  * @copyright  1997-2009 The Authors
                   53845:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53846:  * @version    CVS: $Id: System.php 313024 2011-07-06 19:51:24Z dufuz $
                   53847:  * @link       http://pear.php.net/package/PEAR
                   53848:  * @since      File available since Release 0.1
                   53849:  */
                   53850: 
                   53851: /**
                   53852:  * base class
                   53853:  */
                   53854: require_once 'PEAR.php';
                   53855: require_once 'Console/Getopt.php';
                   53856: 
                   53857: $GLOBALS['_System_temp_files'] = array();
                   53858: 
                   53859: /**
                   53860: * System offers cross plattform compatible system functions
                   53861: *
                   53862: * Static functions for different operations. Should work under
                   53863: * Unix and Windows. The names and usage has been taken from its respectively
                   53864: * GNU commands. The functions will return (bool) false on error and will
                   53865: * trigger the error with the PHP trigger_error() function (you can silence
                   53866: * the error by prefixing a '@' sign after the function call, but this
                   53867: * is not recommended practice.  Instead use an error handler with
                   53868: * {@link set_error_handler()}).
                   53869: *
                   53870: * Documentation on this class you can find in:
                   53871: * http://pear.php.net/manual/
                   53872: *
                   53873: * Example usage:
                   53874: * if (!@System::rm('-r file1 dir1')) {
                   53875: *    print "could not delete file1 or dir1";
                   53876: * }
                   53877: *
                   53878: * In case you need to to pass file names with spaces,
                   53879: * pass the params as an array:
                   53880: *
                   53881: * System::rm(array('-r', $file1, $dir1));
                   53882: *
                   53883: * @category   pear
                   53884: * @package    System
                   53885: * @author     Tomas V.V. Cox <cox@idecnet.com>
                   53886: * @copyright  1997-2006 The PHP Group
                   53887: * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53888: * @version    Release: 1.9.4
                   53889: * @link       http://pear.php.net/package/PEAR
                   53890: * @since      Class available since Release 0.1
                   53891: * @static
                   53892: */
                   53893: class System
                   53894: {
                   53895:     /**
                   53896:      * returns the commandline arguments of a function
                   53897:      *
                   53898:      * @param    string  $argv           the commandline
                   53899:      * @param    string  $short_options  the allowed option short-tags
                   53900:      * @param    string  $long_options   the allowed option long-tags
                   53901:      * @return   array   the given options and there values
                   53902:      * @static
                   53903:      * @access private
                   53904:      */
                   53905:     function _parseArgs($argv, $short_options, $long_options = null)
                   53906:     {
                   53907:         if (!is_array($argv) && $argv !== null) {
                   53908:             // Find all items, quoted or otherwise
                   53909:             preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
                   53910:             $argv = $av[1];
                   53911:             foreach ($av[2] as $k => $a) {
                   53912:                 if (empty($a)) {
                   53913:                     continue;
                   53914:                 }
                   53915:                 $argv[$k] = trim($a) ;
                   53916:             }
                   53917:         }
                   53918:         return Console_Getopt::getopt2($argv, $short_options, $long_options);
                   53919:     }
                   53920: 
                   53921:     /**
                   53922:      * Output errors with PHP trigger_error(). You can silence the errors
                   53923:      * with prefixing a "@" sign to the function call: @System::mkdir(..);
                   53924:      *
                   53925:      * @param mixed $error a PEAR error or a string with the error message
                   53926:      * @return bool false
                   53927:      * @static
                   53928:      * @access private
                   53929:      */
                   53930:     function raiseError($error)
                   53931:     {
                   53932:         if (PEAR::isError($error)) {
                   53933:             $error = $error->getMessage();
                   53934:         }
                   53935:         trigger_error($error, E_USER_WARNING);
                   53936:         return false;
                   53937:     }
                   53938: 
                   53939:     /**
                   53940:      * Creates a nested array representing the structure of a directory
                   53941:      *
                   53942:      * System::_dirToStruct('dir1', 0) =>
                   53943:      *   Array
                   53944:      *    (
                   53945:      *    [dirs] => Array
                   53946:      *        (
                   53947:      *            [0] => dir1
                   53948:      *        )
                   53949:      *
                   53950:      *    [files] => Array
                   53951:      *        (
                   53952:      *            [0] => dir1/file2
                   53953:      *            [1] => dir1/file3
                   53954:      *        )
                   53955:      *    )
                   53956:      * @param    string  $sPath      Name of the directory
                   53957:      * @param    integer $maxinst    max. deep of the lookup
                   53958:      * @param    integer $aktinst    starting deep of the lookup
                   53959:      * @param    bool    $silent     if true, do not emit errors.
                   53960:      * @return   array   the structure of the dir
                   53961:      * @static
                   53962:      * @access   private
                   53963:      */
                   53964:     function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
                   53965:     {
                   53966:         $struct = array('dirs' => array(), 'files' => array());
                   53967:         if (($dir = @opendir($sPath)) === false) {
                   53968:             if (!$silent) {
                   53969:                 System::raiseError("Could not open dir $sPath");
                   53970:             }
                   53971:             return $struct; // XXX could not open error
                   53972:         }
                   53973: 
                   53974:         $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
                   53975:         $list = array();
                   53976:         while (false !== ($file = readdir($dir))) {
                   53977:             if ($file != '.' && $file != '..') {
                   53978:                 $list[] = $file;
                   53979:             }
                   53980:         }
                   53981: 
                   53982:         closedir($dir);
                   53983:         natsort($list);
                   53984:         if ($aktinst < $maxinst || $maxinst == 0) {
                   53985:             foreach ($list as $val) {
                   53986:                 $path = $sPath . DIRECTORY_SEPARATOR . $val;
                   53987:                 if (is_dir($path) && !is_link($path)) {
                   53988:                     $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
                   53989:                     $struct = array_merge_recursive($struct, $tmp);
                   53990:                 } else {
                   53991:                     $struct['files'][] = $path;
                   53992:                 }
                   53993:             }
                   53994:         }
                   53995: 
                   53996:         return $struct;
                   53997:     }
                   53998: 
                   53999:     /**
                   54000:      * Creates a nested array representing the structure of a directory and files
                   54001:      *
                   54002:      * @param    array $files Array listing files and dirs
                   54003:      * @return   array
                   54004:      * @static
                   54005:      * @see System::_dirToStruct()
                   54006:      */
                   54007:     function _multipleToStruct($files)
                   54008:     {
                   54009:         $struct = array('dirs' => array(), 'files' => array());
                   54010:         settype($files, 'array');
                   54011:         foreach ($files as $file) {
                   54012:             if (is_dir($file) && !is_link($file)) {
                   54013:                 $tmp    = System::_dirToStruct($file, 0);
                   54014:                 $struct = array_merge_recursive($tmp, $struct);
                   54015:             } else {
                   54016:                 if (!in_array($file, $struct['files'])) {
                   54017:                     $struct['files'][] = $file;
                   54018:                 }
                   54019:             }
                   54020:         }
                   54021:         return $struct;
                   54022:     }
                   54023: 
                   54024:     /**
                   54025:      * The rm command for removing files.
                   54026:      * Supports multiple files and dirs and also recursive deletes
                   54027:      *
                   54028:      * @param    string  $args   the arguments for rm
                   54029:      * @return   mixed   PEAR_Error or true for success
                   54030:      * @static
                   54031:      * @access   public
                   54032:      */
                   54033:     function rm($args)
                   54034:     {
                   54035:         $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
                   54036:         if (PEAR::isError($opts)) {
                   54037:             return System::raiseError($opts);
                   54038:         }
                   54039:         foreach ($opts[0] as $opt) {
                   54040:             if ($opt[0] == 'r') {
                   54041:                 $do_recursive = true;
                   54042:             }
                   54043:         }
                   54044:         $ret = true;
                   54045:         if (isset($do_recursive)) {
                   54046:             $struct = System::_multipleToStruct($opts[1]);
                   54047:             foreach ($struct['files'] as $file) {
                   54048:                 if (!@unlink($file)) {
                   54049:                     $ret = false;
                   54050:                 }
                   54051:             }
                   54052: 
                   54053:             rsort($struct['dirs']);
                   54054:             foreach ($struct['dirs'] as $dir) {
                   54055:                 if (!@rmdir($dir)) {
                   54056:                     $ret = false;
                   54057:                 }
                   54058:             }
                   54059:         } else {
                   54060:             foreach ($opts[1] as $file) {
                   54061:                 $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
                   54062:                 if (!@$delete($file)) {
                   54063:                     $ret = false;
                   54064:                 }
                   54065:             }
                   54066:         }
                   54067:         return $ret;
                   54068:     }
                   54069: 
                   54070:     /**
                   54071:      * Make directories.
                   54072:      *
                   54073:      * The -p option will create parent directories
                   54074:      * @param    string  $args    the name of the director(y|ies) to create
                   54075:      * @return   bool    True for success
                   54076:      * @static
                   54077:      * @access   public
                   54078:      */
                   54079:     function mkDir($args)
                   54080:     {
                   54081:         $opts = System::_parseArgs($args, 'pm:');
                   54082:         if (PEAR::isError($opts)) {
                   54083:             return System::raiseError($opts);
                   54084:         }
                   54085: 
                   54086:         $mode = 0777; // default mode
                   54087:         foreach ($opts[0] as $opt) {
                   54088:             if ($opt[0] == 'p') {
                   54089:                 $create_parents = true;
                   54090:             } elseif ($opt[0] == 'm') {
                   54091:                 // if the mode is clearly an octal number (starts with 0)
                   54092:                 // convert it to decimal
                   54093:                 if (strlen($opt[1]) && $opt[1]{0} == '0') {
                   54094:                     $opt[1] = octdec($opt[1]);
                   54095:                 } else {
                   54096:                     // convert to int
                   54097:                     $opt[1] += 0;
                   54098:                 }
                   54099:                 $mode = $opt[1];
                   54100:             }
                   54101:         }
                   54102: 
                   54103:         $ret = true;
                   54104:         if (isset($create_parents)) {
                   54105:             foreach ($opts[1] as $dir) {
                   54106:                 $dirstack = array();
                   54107:                 while ((!file_exists($dir) || !is_dir($dir)) &&
                   54108:                         $dir != DIRECTORY_SEPARATOR) {
                   54109:                     array_unshift($dirstack, $dir);
                   54110:                     $dir = dirname($dir);
                   54111:                 }
                   54112: 
                   54113:                 while ($newdir = array_shift($dirstack)) {
                   54114:                     if (!is_writeable(dirname($newdir))) {
                   54115:                         $ret = false;
                   54116:                         break;
                   54117:                     }
                   54118: 
                   54119:                     if (!mkdir($newdir, $mode)) {
                   54120:                         $ret = false;
                   54121:                     }
                   54122:                 }
                   54123:             }
                   54124:         } else {
                   54125:             foreach($opts[1] as $dir) {
                   54126:                 if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
                   54127:                     $ret = false;
                   54128:                 }
                   54129:             }
                   54130:         }
                   54131: 
                   54132:         return $ret;
                   54133:     }
                   54134: 
                   54135:     /**
                   54136:      * Concatenate files
                   54137:      *
                   54138:      * Usage:
                   54139:      * 1) $var = System::cat('sample.txt test.txt');
                   54140:      * 2) System::cat('sample.txt test.txt > final.txt');
                   54141:      * 3) System::cat('sample.txt test.txt >> final.txt');
                   54142:      *
                   54143:      * Note: as the class use fopen, urls should work also (test that)
                   54144:      *
                   54145:      * @param    string  $args   the arguments
                   54146:      * @return   boolean true on success
                   54147:      * @static
                   54148:      * @access   public
                   54149:      */
                   54150:     function &cat($args)
                   54151:     {
                   54152:         $ret = null;
                   54153:         $files = array();
                   54154:         if (!is_array($args)) {
                   54155:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   54156:         }
                   54157: 
                   54158:         $count_args = count($args);
                   54159:         for ($i = 0; $i < $count_args; $i++) {
                   54160:             if ($args[$i] == '>') {
                   54161:                 $mode = 'wb';
                   54162:                 $outputfile = $args[$i+1];
                   54163:                 break;
                   54164:             } elseif ($args[$i] == '>>') {
                   54165:                 $mode = 'ab+';
                   54166:                 $outputfile = $args[$i+1];
                   54167:                 break;
                   54168:             } else {
                   54169:                 $files[] = $args[$i];
                   54170:             }
                   54171:         }
                   54172:         $outputfd = false;
                   54173:         if (isset($mode)) {
                   54174:             if (!$outputfd = fopen($outputfile, $mode)) {
                   54175:                 $err = System::raiseError("Could not open $outputfile");
                   54176:                 return $err;
                   54177:             }
                   54178:             $ret = true;
                   54179:         }
                   54180:         foreach ($files as $file) {
                   54181:             if (!$fd = fopen($file, 'r')) {
                   54182:                 System::raiseError("Could not open $file");
                   54183:                 continue;
                   54184:             }
                   54185:             while ($cont = fread($fd, 2048)) {
                   54186:                 if (is_resource($outputfd)) {
                   54187:                     fwrite($outputfd, $cont);
                   54188:                 } else {
                   54189:                     $ret .= $cont;
                   54190:                 }
                   54191:             }
                   54192:             fclose($fd);
                   54193:         }
                   54194:         if (is_resource($outputfd)) {
                   54195:             fclose($outputfd);
                   54196:         }
                   54197:         return $ret;
                   54198:     }
                   54199: 
                   54200:     /**
                   54201:      * Creates temporary files or directories. This function will remove
                   54202:      * the created files when the scripts finish its execution.
                   54203:      *
                   54204:      * Usage:
                   54205:      *   1) $tempfile = System::mktemp("prefix");
                   54206:      *   2) $tempdir  = System::mktemp("-d prefix");
                   54207:      *   3) $tempfile = System::mktemp();
                   54208:      *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
                   54209:      *
                   54210:      * prefix -> The string that will be prepended to the temp name
                   54211:      *           (defaults to "tmp").
                   54212:      * -d     -> A temporary dir will be created instead of a file.
                   54213:      * -t     -> The target dir where the temporary (file|dir) will be created. If
                   54214:      *           this param is missing by default the env vars TMP on Windows or
                   54215:      *           TMPDIR in Unix will be used. If these vars are also missing
                   54216:      *           c:\windows\temp or /tmp will be used.
                   54217:      *
                   54218:      * @param   string  $args  The arguments
                   54219:      * @return  mixed   the full path of the created (file|dir) or false
                   54220:      * @see System::tmpdir()
                   54221:      * @static
                   54222:      * @access  public
                   54223:      */
                   54224:     function mktemp($args = null)
                   54225:     {
                   54226:         static $first_time = true;
                   54227:         $opts = System::_parseArgs($args, 't:d');
                   54228:         if (PEAR::isError($opts)) {
                   54229:             return System::raiseError($opts);
                   54230:         }
                   54231: 
                   54232:         foreach ($opts[0] as $opt) {
                   54233:             if ($opt[0] == 'd') {
                   54234:                 $tmp_is_dir = true;
                   54235:             } elseif ($opt[0] == 't') {
                   54236:                 $tmpdir = $opt[1];
                   54237:             }
                   54238:         }
                   54239: 
                   54240:         $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
                   54241:         if (!isset($tmpdir)) {
                   54242:             $tmpdir = System::tmpdir();
                   54243:         }
                   54244: 
                   54245:         if (!System::mkDir(array('-p', $tmpdir))) {
                   54246:             return false;
                   54247:         }
                   54248: 
                   54249:         $tmp = tempnam($tmpdir, $prefix);
                   54250:         if (isset($tmp_is_dir)) {
                   54251:             unlink($tmp); // be careful possible race condition here
                   54252:             if (!mkdir($tmp, 0700)) {
                   54253:                 return System::raiseError("Unable to create temporary directory $tmpdir");
                   54254:             }
                   54255:         }
                   54256: 
                   54257:         $GLOBALS['_System_temp_files'][] = $tmp;
                   54258:         if (isset($tmp_is_dir)) {
                   54259:             //$GLOBALS['_System_temp_files'][] = dirname($tmp);
                   54260:         }
                   54261: 
                   54262:         if ($first_time) {
                   54263:             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
                   54264:             $first_time = false;
                   54265:         }
                   54266: 
                   54267:         return $tmp;
                   54268:     }
                   54269: 
                   54270:     /**
                   54271:      * Remove temporary files created my mkTemp. This function is executed
                   54272:      * at script shutdown time
                   54273:      *
                   54274:      * @static
                   54275:      * @access private
                   54276:      */
                   54277:     function _removeTmpFiles()
                   54278:     {
                   54279:         if (count($GLOBALS['_System_temp_files'])) {
                   54280:             $delete = $GLOBALS['_System_temp_files'];
                   54281:             array_unshift($delete, '-r');
                   54282:             System::rm($delete);
                   54283:             $GLOBALS['_System_temp_files'] = array();
                   54284:         }
                   54285:     }
                   54286: 
                   54287:     /**
                   54288:      * Get the path of the temporal directory set in the system
                   54289:      * by looking in its environments variables.
                   54290:      * Note: php.ini-recommended removes the "E" from the variables_order setting,
                   54291:      * making unavaible the $_ENV array, that s why we do tests with _ENV
                   54292:      *
                   54293:      * @static
                   54294:      * @return string The temporary directory on the system
                   54295:      */
                   54296:     function tmpdir()
                   54297:     {
                   54298:         if (OS_WINDOWS) {
                   54299:             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                   54300:                 return $var;
                   54301:             }
                   54302:             if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                   54303:                 return $var;
                   54304:             }
                   54305:             if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
                   54306:                 return $var;
                   54307:             }
                   54308:             if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                   54309:                 return $var;
                   54310:             }
                   54311:             return getenv('SystemRoot') . '\temp';
                   54312:         }
                   54313:         if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
                   54314:             return $var;
                   54315:         }
                   54316:         return realpath('/tmp');
                   54317:     }
                   54318: 
                   54319:     /**
                   54320:      * The "which" command (show the full path of a command)
                   54321:      *
                   54322:      * @param string $program The command to search for
                   54323:      * @param mixed  $fallback Value to return if $program is not found
                   54324:      *
                   54325:      * @return mixed A string with the full path or false if not found
                   54326:      * @static
                   54327:      * @author Stig Bakken <ssb@php.net>
                   54328:      */
                   54329:     function which($program, $fallback = false)
                   54330:     {
                   54331:         // enforce API
                   54332:         if (!is_string($program) || '' == $program) {
                   54333:             return $fallback;
                   54334:         }
                   54335: 
                   54336:         // full path given
                   54337:         if (basename($program) != $program) {
                   54338:             $path_elements[] = dirname($program);
                   54339:             $program = basename($program);
                   54340:         } else {
                   54341:             // Honor safe mode
                   54342:             if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
                   54343:                 $path = getenv('PATH');
                   54344:                 if (!$path) {
                   54345:                     $path = getenv('Path'); // some OSes are just stupid enough to do this
                   54346:                 }
                   54347:             }
                   54348:             $path_elements = explode(PATH_SEPARATOR, $path);
                   54349:         }
                   54350: 
                   54351:         if (OS_WINDOWS) {
                   54352:             $exe_suffixes = getenv('PATHEXT')
                   54353:                                 ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
                   54354:                                 : array('.exe','.bat','.cmd','.com');
                   54355:             // allow passing a command.exe param
                   54356:             if (strpos($program, '.') !== false) {
                   54357:                 array_unshift($exe_suffixes, '');
                   54358:             }
                   54359:             // is_executable() is not available on windows for PHP4
                   54360:             $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
                   54361:         } else {
                   54362:             $exe_suffixes = array('');
                   54363:             $pear_is_executable = 'is_executable';
                   54364:         }
                   54365: 
                   54366:         foreach ($exe_suffixes as $suff) {
                   54367:             foreach ($path_elements as $dir) {
                   54368:                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
                   54369:                 if (@$pear_is_executable($file)) {
                   54370:                     return $file;
                   54371:                 }
                   54372:             }
                   54373:         }
                   54374:         return $fallback;
                   54375:     }
                   54376: 
                   54377:     /**
                   54378:      * The "find" command
                   54379:      *
                   54380:      * Usage:
                   54381:      *
                   54382:      * System::find($dir);
                   54383:      * System::find("$dir -type d");
                   54384:      * System::find("$dir -type f");
                   54385:      * System::find("$dir -name *.php");
                   54386:      * System::find("$dir -name *.php -name *.htm*");
                   54387:      * System::find("$dir -maxdepth 1");
                   54388:      *
                   54389:      * Params implmented:
                   54390:      * $dir            -> Start the search at this directory
                   54391:      * -type d         -> return only directories
                   54392:      * -type f         -> return only files
                   54393:      * -maxdepth <n>   -> max depth of recursion
                   54394:      * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
                   54395:      *
                   54396:      * @param  mixed Either array or string with the command line
                   54397:      * @return array Array of found files
                   54398:      * @static
                   54399:      *
                   54400:      */
                   54401:     function find($args)
                   54402:     {
                   54403:         if (!is_array($args)) {
                   54404:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   54405:         }
                   54406:         $dir = realpath(array_shift($args));
                   54407:         if (!$dir) {
                   54408:             return array();
                   54409:         }
                   54410:         $patterns = array();
                   54411:         $depth = 0;
                   54412:         $do_files = $do_dirs = true;
                   54413:         $args_count = count($args);
                   54414:         for ($i = 0; $i < $args_count; $i++) {
                   54415:             switch ($args[$i]) {
                   54416:                 case '-type':
                   54417:                     if (in_array($args[$i+1], array('d', 'f'))) {
                   54418:                         if ($args[$i+1] == 'd') {
                   54419:                             $do_files = false;
                   54420:                         } else {
                   54421:                             $do_dirs = false;
                   54422:                         }
                   54423:                     }
                   54424:                     $i++;
                   54425:                     break;
                   54426:                 case '-name':
                   54427:                     $name = preg_quote($args[$i+1], '#');
                   54428:                     // our magic characters ? and * have just been escaped,
                   54429:                     // so now we change the escaped versions to PCRE operators
                   54430:                     $name = strtr($name, array('\?' => '.', '\*' => '.*'));
                   54431:                     $patterns[] = '('.$name.')';
                   54432:                     $i++;
                   54433:                     break;
                   54434:                 case '-maxdepth':
                   54435:                     $depth = $args[$i+1];
                   54436:                     break;
                   54437:             }
                   54438:         }
                   54439:         $path = System::_dirToStruct($dir, $depth, 0, true);
                   54440:         if ($do_files && $do_dirs) {
                   54441:             $files = array_merge($path['files'], $path['dirs']);
                   54442:         } elseif ($do_dirs) {
                   54443:             $files = $path['dirs'];
                   54444:         } else {
                   54445:             $files = $path['files'];
                   54446:         }
                   54447:         if (count($patterns)) {
                   54448:             $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
                   54449:             $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
                   54450:             $ret = array();
                   54451:             $files_count = count($files);
                   54452:             for ($i = 0; $i < $files_count; $i++) {
                   54453:                 // only search in the part of the file below the current directory
                   54454:                 $filepart = basename($files[$i]);
                   54455:                 if (preg_match($pattern, $filepart)) {
                   54456:                     $ret[] = $files[$i];
                   54457:                 }
                   54458:             }
                   54459:             return $ret;
                   54460:         }
                   54461:         return $files;
                   54462:     }
                   54463: }PEAR-1.9.4/template.spec0000644000076500000240000000372511605156760013734 0ustar  helgistaffSummary: PEAR: @summary@
                   54464: Name: @rpm_package@
                   54465: Version: @version@
                   54466: Release: 1
                   54467: License: @release_license@
                   54468: Group: Development/Libraries
                   54469: Source: http://@master_server@/get/@package@-%{version}.tgz
                   54470: BuildRoot: %{_tmppath}/%{name}-root
                   54471: URL: http://@master_server@/package/@package@
                   54472: Prefix: %{_prefix}
                   54473: BuildArchitectures: @arch@
                   54474: @extra_headers@
                   54475: 
                   54476: %description
                   54477: @description@
                   54478: 
                   54479: %prep
                   54480: rm -rf %{buildroot}/*
                   54481: %setup -c -T
                   54482: # XXX Source files location is missing here in pear cmd
                   54483: pear -v -c %{buildroot}/pearrc \
                   54484:         -d php_dir=%{_libdir}/php/pear \
                   54485:         -d doc_dir=/docs \
                   54486:         -d bin_dir=%{_bindir} \
                   54487:         -d data_dir=%{_libdir}/php/pear/data \
                   54488:         -d test_dir=%{_libdir}/php/pear/tests \
                   54489:         -d ext_dir=%{_libdir} \@extra_config@
                   54490:         -s
                   54491: 
                   54492: %build
                   54493: echo BuildRoot=%{buildroot}
                   54494: 
                   54495: %postun
                   54496: # if refcount = 0 then package has been removed (not upgraded)
                   54497: if [ "$1" -eq "0" ]; then
                   54498:     pear uninstall --nodeps -r @possible_channel@@package@
                   54499:     rm @rpm_xml_dir@/@package@.xml
                   54500: fi
                   54501: 
                   54502: 
                   54503: %post
                   54504: # if refcount = 2 then package has been upgraded
                   54505: if [ "$1" -ge "2" ]; then
                   54506:     pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml
                   54507: else
                   54508:     pear install --nodeps -r @rpm_xml_dir@/@package@.xml
                   54509: fi
                   54510: 
                   54511: %install
                   54512: pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \
                   54513:         $RPM_SOURCE_DIR/@package@-%{version}.tgz
                   54514: rm %{buildroot}/pearrc
                   54515: rm %{buildroot}/%{_libdir}/php/pear/.filemap
                   54516: rm %{buildroot}/%{_libdir}/php/pear/.lock
                   54517: rm -rf %{buildroot}/%{_libdir}/php/pear/.registry
                   54518: if [ "@doc_files@" != "" ]; then
                   54519:      mv %{buildroot}/docs/@package@/* .
                   54520:      rm -rf %{buildroot}/docs
                   54521: fi
                   54522: mkdir -p %{buildroot}@rpm_xml_dir@
                   54523: tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml
                   54524: cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
                   54525: 
                   54526: #rm -rf %{buildroot}/*
                   54527: #pear -q install -R %{buildroot} -n package@package2xml@.xml
                   54528: #mkdir -p %{buildroot}@rpm_xml_dir@
                   54529: #cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
                   54530: 
                   54531: %files
                   54532:     %defattr(-,root,root)
                   54533:     %doc @doc_files@
                   54534:     /
                   54535: package.xml0000644000076500000240000010644711605156760012171 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8" ?>
                   54536: <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
                   54537: <package version="1.0" packagerversion="1.9.4">
                   54538:  <name>PEAR</name>
                   54539:  <summary>PEAR Base System</summary>
                   54540:  <description>The PEAR package contains:
                   54541:  * the PEAR installer, for creating, distributing
                   54542:    and installing packages
                   54543:  * the PEAR_Exception PHP5 error handling mechanism
                   54544:  * the PEAR_ErrorStack advanced error handling mechanism
                   54545:  * the PEAR_Error error handling mechanism
                   54546:  * the OS_Guess class for retrieving info about the OS
                   54547:    where PHP is running on
                   54548:  * the System class for quick handling of common operations
                   54549:    with files and directories
                   54550:  * the PEAR base class
                   54551: 
                   54552:   Features in a nutshell:
                   54553:   * full support for channels
                   54554:   * pre-download dependency validation
                   54555:   * new package.xml 2.0 format allows tremendous flexibility while maintaining BC
                   54556:   * support for optional dependency groups and limited support for sub-packaging
                   54557:   * robust dependency support
                   54558:   * full dependency validation on uninstall
                   54559:   * remote install for hosts with only ftp access - no more problems with
                   54560:     restricted host installation
                   54561:   * full support for mirroring
                   54562:   * support for bundling several packages into a single tarball
                   54563:   * support for static dependencies on a url-based package
                   54564:   * support for custom file roles and installation tasks
                   54565:  </description>
                   54566:  <maintainers>
                   54567:   <maintainer>
                   54568:    <user>cellog</user>
                   54569:    <name>Greg Beaver</name>
                   54570:    <email>cellog@php.net</email>
                   54571:    <role>lead</role>
                   54572:   </maintainer>
                   54573:   <maintainer>
                   54574:    <user>pajoye</user>
                   54575:    <name>Pierre-Alain Joye</name>
                   54576:    <email>pierre@php.net</email>
                   54577:    <role>lead</role>
                   54578:   </maintainer>
                   54579:   <maintainer>
                   54580:    <user>ssb</user>
                   54581:    <name>Stig Bakken</name>
                   54582:    <email>stig@php.net</email>
                   54583:    <role>lead</role>
                   54584:   </maintainer>
                   54585:   <maintainer>
                   54586:    <user>cox</user>
                   54587:    <name>Tomas V.V.Cox</name>
                   54588:    <email>cox@idecnet.com</email>
                   54589:    <role>lead</role>
                   54590:   </maintainer>
                   54591:   <maintainer>
                   54592:    <user>dufuz</user>
                   54593:    <name>Helgi Thormar</name>
                   54594:    <email>dufuz@php.net</email>
                   54595:    <role>lead</role>
                   54596:   </maintainer>
                   54597:   <maintainer>
                   54598:    <user>tias</user>
                   54599:    <name>Tias Guns</name>
                   54600:    <email>tias@php.net</email>
                   54601:    <role>developer</role>
                   54602:   </maintainer>
                   54603:   <maintainer>
                   54604:    <user>timj</user>
                   54605:    <name>Tim Jackson</name>
                   54606:    <email>timj@php.net</email>
                   54607:    <role>helper</role>
                   54608:   </maintainer>
                   54609:   <maintainer>
                   54610:    <user>toggg</user>
                   54611:    <name>Bertrand Gugger</name>
                   54612:    <email>toggg@php.net</email>
                   54613:    <role>helper</role>
                   54614:   </maintainer>
                   54615:   <maintainer>
                   54616:    <user>mj</user>
                   54617:    <name>Martin Jansen</name>
                   54618:    <email>mj@php.net</email>
                   54619:    <role>helper</role>
                   54620:   </maintainer>
                   54621:   </maintainers>
                   54622:  <release>
                   54623:   <version>1.9.4</version>
                   54624:   <date>2011-07-06</date>
                   54625:   <license>New BSD License</license>
                   54626:   <state>stable</state>
                   54627:   <notes>Bug Fixes:
                   54628: * Bug #17350: &quot;pear install --force&quot; doesn&apos;t uninstall files from previous pkg versions [dufuz]
                   54629: * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz]
                   54630: * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz]
                   54631: * Bug #18581: &quot;config-get -c&quot; not returning channel&apos;s configuration when using alias [dufuz]
                   54632: * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz]
                   54633: Features
                   54634: * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes.
                   54635:   Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz]
                   54636:   </notes>
                   54637:   <deps>
                   54638:    <dep type="php" rel="ge" version="4.4.0"/>
                   54639:    <dep type="pkg" rel="ge" version="1.3.3">PEAR</dep>
                   54640:    <dep type="pkg" rel="ge" version="1.3.7">Archive_Tar</dep>
                   54641:    <dep type="pkg" rel="ge" version="1.2">Console_Getopt</dep>
                   54642:    <dep type="pkg" rel="ge" version="1.0.2">Structures_Graph</dep>
                   54643:    <dep type="pkg" rel="ge" version="0.5.0" optional="yes">PEAR_Frontend_Web</dep>
                   54644:    <dep type="pkg" rel="ge" version="0.4.0" optional="yes">PEAR_Frontend_Gtk</dep>
                   54645:    <dep type="ext" rel="has">xml</dep>
                   54646:    <dep type="ext" rel="has">pcre</dep>
                   54647:   </deps>
                   54648:   <provides type="class" name="OS_Guess" />
                   54649:   <provides type="class" name="System" />
                   54650:   <filelist>
                   54651:    <file role="php" name="OS/Guess.php">
                   54652:     <replace from="@package_version@" to="version" type="package-info"/>
                   54653:    </file>
                   54654:    <file role="php" name="PEAR/ChannelFile/Parser.php">
                   54655:     <replace from="@package_version@" to="version" type="package-info"/>
                   54656:    </file>
                   54657:    <file role="php" name="PEAR/Command/Auth.xml"/>
                   54658:    <file role="php" name="PEAR/Command/Auth.php">
                   54659:     <replace from="@package_version@" to="version" type="package-info"/>
                   54660:    </file>
                   54661:    <file role="php" name="PEAR/Command/Build.xml"/>
                   54662:    <file role="php" name="PEAR/Command/Build.php">
                   54663:     <replace from="@package_version@" to="version" type="package-info"/>
                   54664:    </file>
                   54665:    <file role="php" name="PEAR/Command/Channels.xml"/>
                   54666:    <file role="php" name="PEAR/Command/Channels.php">
                   54667:     <replace from="@package_version@" to="version" type="package-info"/>
                   54668:    </file>
                   54669:    <file role="php" name="PEAR/Command/Common.php">
                   54670:     <replace from="@package_version@" to="version" type="package-info"/>
                   54671:    </file>
                   54672:    <file role="php" name="PEAR/Command/Config.xml"/>
                   54673:    <file role="php" name="PEAR/Command/Config.php">
                   54674:     <replace from="@package_version@" to="version" type="package-info"/>
                   54675:    </file>
                   54676:    <file role="php" name="PEAR/Command/Install.xml"/>
                   54677:    <file role="php" name="PEAR/Command/Install.php">
                   54678:     <replace from="@package_version@" to="version" type="package-info"/>
                   54679:    </file>
                   54680:    <file role="php" name="PEAR/Command/Package.xml"/>
                   54681:    <file role="php" name="PEAR/Command/Package.php">
                   54682:     <replace from="@DATA-DIR@" to="data_dir" type="pear-config"/>
                   54683:     <replace from="@package_version@" to="version" type="package-info"/>
                   54684:    </file>
                   54685:    <file role="php" name="PEAR/Command/Pickle.xml"/>
                   54686:    <file role="php" name="PEAR/Command/Pickle.php">
                   54687:     <replace from="@package_version@" to="version" type="package-info"/>
                   54688:    </file>
                   54689:    <file role="php" name="PEAR/Command/Registry.xml"/>
                   54690:    <file role="php" name="PEAR/Command/Registry.php">
                   54691:     <replace from="@package_version@" to="version" type="package-info"/>
                   54692:    </file>
                   54693:    <file role="php" name="PEAR/Command/Remote.xml"/>
                   54694:    <file role="php" name="PEAR/Command/Remote.php">
                   54695:     <replace from="@package_version@" to="version" type="package-info"/>
                   54696:    </file>
                   54697:    <file role="php" name="PEAR/Command/Mirror.xml"/>
                   54698:    <file role="php" name="PEAR/Command/Mirror.php">
                   54699:     <replace from="@package_version@" to="version" type="package-info"/>
                   54700:    </file>
                   54701:    <file role="php" name="PEAR/Command/Test.xml"/>
                   54702:    <file role="php" name="PEAR/Command/Test.php">
                   54703:     <replace from="@package_version@" to="version" type="package-info"/>
                   54704:    </file>
                   54705:    <file role="php" name="PEAR/Downloader/Package.php">
                   54706:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54707:    </file>
                   54708:    <file role="php" name="PEAR/Frontend/CLI.php">
                   54709:     <replace from="@package_version@" to="version" type="package-info"/>
                   54710:    </file>
                   54711:    <file role="php" name="PEAR/Installer/Role/Common.php">
                   54712:     <replace from="@package_version@" to="version" type="package-info"/>
                   54713:    </file>
                   54714:    <file role="php" name="PEAR/Installer/Role/Cfg.xml"/>
                   54715:    <file role="php" name="PEAR/Installer/Role/Cfg.php">
                   54716:     <replace from="@package_version@" to="version" type="package-info"/>
                   54717:    </file>
                   54718:    <file role="php" name="PEAR/Installer/Role/Data.xml"/>
                   54719:    <file role="php" name="PEAR/Installer/Role/Data.php">
                   54720:     <replace from="@package_version@" to="version" type="package-info"/>
                   54721:    </file>
                   54722:    <file role="php" name="PEAR/Installer/Role/Doc.xml"/>
                   54723:    <file role="php" name="PEAR/Installer/Role/Doc.php">
                   54724:     <replace from="@package_version@" to="version" type="package-info"/>
                   54725:    </file>
                   54726:    <file role="php" name="PEAR/Installer/Role/Ext.xml"/>
                   54727:    <file role="php" name="PEAR/Installer/Role/Ext.php">
                   54728:     <replace from="@package_version@" to="version" type="package-info"/>
                   54729:    </file>
                   54730:    <file role="php" name="PEAR/Installer/Role/Php.xml"/>
                   54731:    <file role="php" name="PEAR/Installer/Role/Php.php">
                   54732:     <replace from="@package_version@" to="version" type="package-info"/>
                   54733:    </file>
                   54734:    <file role="php" name="PEAR/Installer/Role/Script.xml"/>
                   54735:    <file role="php" name="PEAR/Installer/Role/Script.php">
                   54736:     <replace from="@package_version@" to="version" type="package-info"/>
                   54737:    </file>
                   54738:    <file role="php" name="PEAR/Installer/Role/Src.xml"/>
                   54739:    <file role="php" name="PEAR/Installer/Role/Src.php">
                   54740:     <replace from="@package_version@" to="version" type="package-info"/>
                   54741:    </file>
                   54742:    <file role="php" name="PEAR/Installer/Role/Test.xml"/>
                   54743:    <file role="php" name="PEAR/Installer/Role/Test.php">
                   54744:     <replace from="@package_version@" to="version" type="package-info"/>
                   54745:    </file>
                   54746:    <file role="php" name="PEAR/Installer/Role/Www.xml"/>
                   54747:    <file role="php" name="PEAR/Installer/Role/Www.php">
                   54748:     <replace from="@package_version@" to="version" type="package-info"/>
                   54749:    </file>
                   54750:    <file role="php" name="PEAR/Installer/Role.php">
                   54751:     <replace from="@package_version@" to="version" type="package-info"/>
                   54752:    </file>
                   54753:    <file role="php" name="PEAR/PackageFile/Generator/v1.php">
                   54754:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54755:    </file>
                   54756:    <file role="php" name="PEAR/PackageFile/Generator/v2.php">
                   54757:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54758:    </file>
                   54759:    <file role="php" name="PEAR/PackageFile/Parser/v1.php">
                   54760:     <replace from="@package_version@" to="version" type="package-info"/>
                   54761:    </file>
                   54762:    <file role="php" name="PEAR/PackageFile/Parser/v2.php">
                   54763:     <replace from="@package_version@" to="version" type="package-info"/>
                   54764:    </file>
                   54765:    <file role="php" name="PEAR/PackageFile/v2/rw.php">
                   54766:     <replace from="@package_version@" to="version" type="package-info"/>
                   54767:    </file>
                   54768:    <file role="php" name="PEAR/PackageFile/v2/Validator.php">
                   54769:     <replace from="@package_version@" to="version" type="package-info"/>
                   54770:    </file>
                   54771:    <file role="php" name="PEAR/PackageFile/v1.php">
                   54772:     <replace from="@package_version@" to="version" type="package-info"/>
                   54773:    </file>
                   54774:    <file role="php" name="PEAR/PackageFile/v2.php">
                   54775:     <replace from="@package_version@" to="version" type="package-info"/>
                   54776:    </file>
                   54777:    <file role="php" name="PEAR/REST/10.php">
                   54778:     <replace from="@package_version@" to="version" type="package-info"/>
                   54779:    </file>
                   54780:    <file role="php" name="PEAR/REST/11.php">
                   54781:     <replace from="@package_version@" to="version" type="package-info"/>
                   54782:    </file>
                   54783:    <file role="php" name="PEAR/REST/13.php">
                   54784:     <replace from="@package_version@" to="version" type="package-info"/>
                   54785:    </file>
                   54786:    <file role="php" name="PEAR/Task/Postinstallscript/rw.php">
                   54787:     <replace from="@package_version@" to="version" type="package-info"/>
                   54788:    </file>
                   54789:    <file role="php" name="PEAR/Task/Replace/rw.php">
                   54790:     <replace from="@package_version@" to="version" type="package-info"/>
                   54791:    </file>
                   54792:    <file role="php" name="PEAR/Task/Unixeol/rw.php">
                   54793:     <replace from="@package_version@" to="version" type="package-info"/>
                   54794:    </file>
                   54795:    <file role="php" name="PEAR/Task/Windowseol/rw.php">
                   54796:     <replace from="@package_version@" to="version" type="package-info"/>
                   54797:    </file>
                   54798:    <file role="php" name="PEAR/Task/Common.php">
                   54799:     <replace from="@package_version@" to="version" type="package-info"/>
                   54800:    </file>
                   54801:    <file role="php" name="PEAR/Task/Postinstallscript.php">
                   54802:     <replace from="@package_version@" to="version" type="package-info"/>
                   54803:    </file>
                   54804:    <file role="php" name="PEAR/Task/Replace.php">
                   54805:     <replace from="@package_version@" to="version" type="package-info"/>
                   54806:    </file>
                   54807:    <file role="php" name="PEAR/Task/Unixeol.php">
                   54808:     <replace from="@package_version@" to="version" type="package-info"/>
                   54809:    </file>
                   54810:    <file role="php" name="PEAR/Task/Windowseol.php">
                   54811:     <replace from="@package_version@" to="version" type="package-info"/>
                   54812:    </file>
                   54813:    <file role="php" name="PEAR/Validator/PECL.php">
                   54814:     <replace from="@package_version@" to="version" type="package-info"/>
                   54815:    </file>
                   54816:    <file role="php" name="PEAR/Autoloader.php">
                   54817:     <replace from="@package_version@" to="version" type="package-info"/>
                   54818:    </file>
                   54819:    <file role="php" name="PEAR/Builder.php">
                   54820:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54821:    </file>
                   54822:    <file role="php" name="PEAR/ChannelFile.php">
                   54823:     <replace from="@package_version@" to="version" type="package-info"/>
                   54824:    </file>
                   54825:    <file role="php" name="PEAR/Command.php">
                   54826:     <replace from="@package_version@" to="version" type="package-info"/>
                   54827:    </file>
                   54828:    <file role="php" name="PEAR/Common.php">
                   54829:     <replace from="@package_version@" to="version" type="package-info"/>
                   54830:    </file>
                   54831:    <file role="php" name="PEAR/Config.php">
                   54832:     <replace from="@package_version@" to="version" type="package-info"/>
                   54833:    </file>
                   54834:    <file role="php" name="PEAR/DependencyDB.php">
                   54835:     <replace from="@package_version@" to="version" type="package-info"/>
                   54836:    </file>
                   54837:    <file role="php" name="PEAR/Dependency2.php">
                   54838:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54839:    </file>
                   54840:    <file role="php" name="PEAR/Downloader.php">
                   54841:     <replace from="@package_version@" to="version" type="package-info"/>
                   54842:    </file>
                   54843:    <file role="php" name="PEAR/ErrorStack.php">
                   54844:     <replace from="@package_version@" to="version" type="package-info"/>
                   54845:    </file>
                   54846:    <file role="php" name="PEAR/Exception.php">
                   54847:     <replace from="@package_version@" to="version" type="package-info"/>
                   54848:    </file>
                   54849:    <file role="php" name="PEAR/FixPHP5PEARWarnings.php"/>
                   54850:    <file role="php" name="PEAR/Frontend.php">
                   54851:     <replace from="@package_version@" to="version" type="package-info"/>
                   54852:    </file>
                   54853:    <file role="php" name="PEAR/Installer.php">
                   54854:     <replace from="@package_version@" to="version" type="package-info"/>
                   54855:    </file>
                   54856:    <file role="php" name="PEAR/Packager.php">
                   54857:     <replace from="@package_version@" to="version" type="package-info"/>
                   54858:    </file>
                   54859:    <file role="php" name="PEAR/PackageFile.php">
                   54860:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54861:    </file>
                   54862:    <file role="php" name="PEAR/Registry.php">
                   54863:     <replace from="@package_version@" to="version" type="package-info"/>
                   54864:    </file>
                   54865:    <file role="php" name="PEAR/REST.php">
                   54866:     <replace from="@package_version@" to="version" type="package-info"/>
                   54867:    </file>
                   54868:    <file role="php" name="PEAR/RunTest.php">
                   54869:     <replace from="@package_version@" to="version" type="package-info"/>
                   54870:    </file>
                   54871:    <file role="php" name="PEAR/Validate.php">
                   54872:     <replace from="@package_version@" to="version" type="package-info"/>
                   54873:    </file>
                   54874:    <file role="php" name="PEAR/XMLParser.php">
                   54875:     <replace from="@package_version@" to="version" type="package-info"/>
                   54876:    </file>
                   54877:    <file role="script" baseinstalldir="/" platform="!windows" install-as="pear" name="scripts/pear.sh">
                   54878:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54879:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   54880:     <replace from="@pear_version@" to="version" type="package-info"/>
                   54881:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54882:    </file>
                   54883:    <file role="script" baseinstalldir="/" platform="!windows" install-as="peardev" name="scripts/peardev.sh">
                   54884:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54885:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   54886:     <replace from="@pear_version@" to="version" type="package-info"/>
                   54887:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54888:    </file>
                   54889:    <file role="script" baseinstalldir="/" platform="!windows" install-as="pecl" name="scripts/pecl.sh">
                   54890:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54891:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   54892:     <replace from="@pear_version@" to="version" type="package-info"/>
                   54893:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54894:    </file>
                   54895:    <file role="script" baseinstalldir="/" platform="windows" install-as="peardev.bat" name="scripts/peardev.bat">
                   54896:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   54897:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54898:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54899:    </file>
                   54900:    <file role="script" baseinstalldir="/" platform="windows" install-as="pear.bat" name="scripts/pear.bat">
                   54901:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   54902:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54903:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54904:    </file>
                   54905:    <file role="script" baseinstalldir="/" platform="windows" install-as="pecl.bat" name="scripts/pecl.bat">
                   54906:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   54907:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54908:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54909:    </file>
                   54910:    <file role="php" baseinstalldir="/" install-as="pearcmd.php" name="scripts/pearcmd.php">
                   54911:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54912:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   54913:     <replace from="@pear_version@" to="version" type="package-info"/>
                   54914:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54915:    </file>
                   54916:    <file role="php" baseinstalldir="/" install-as="peclcmd.php" name="scripts/peclcmd.php">
                   54917:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   54918:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   54919:     <replace from="@pear_version@" to="version" type="package-info"/>
                   54920:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   54921:    </file>
                   54922:    <file role="doc" baseinstalldir="/" name="LICENSE"/>
                   54923:    <file role="doc" baseinstalldir="/" name="INSTALL"/>
                   54924:    <file role="data" baseinstalldir="/" name="package.dtd"/>
                   54925:    <file role="data" baseinstalldir="/" name="template.spec"/>
                   54926:    <file role="php" baseinstalldir="/" name="PEAR.php">
                   54927:     <replace from="@package_version@" to="version" type="package-info"/>
                   54928:    </file>
                   54929:    <file role="php" baseinstalldir="/" name="PEAR5.php"/>
                   54930:    <file role="doc" baseinstalldir="/" name="README"/>
                   54931:    <file role="php" baseinstalldir="/" name="System.php">
                   54932:     <replace from="@package_version@" to="version" type="package-info"/>
                   54933:    </file>
                   54934:   </filelist>
                   54935:  </release>
                   54936:  <changelog>
                   54937:    <release>
                   54938:     <version>1.8.0alpha1</version>
                   54939:     <date>2009-03-09</date>
                   54940:     <license>New BSD License</license>
                   54941:     <state>alpha</state>
                   54942:     <notes>* Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   54943: * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   54944: * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   54945: * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   54946: * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   54947: * Implement Request #12706: pear list -a hard to read [dufuz]
                   54948: * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   54949: * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   54950: * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   54951: * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   54952: * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   54953:   - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   54954:     better what other package managers are doing. upgrade-all will still work as intended.
                   54955: * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   54956:   - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   54957:     channel specific upgrades
                   54958: * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   54959: * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   54960: * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   54961: * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   54962: * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   54963: * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   54964: * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   54965: * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   54966: * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   54967: * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   54968: * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   54969: * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   54970: * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   54971: * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   54972: * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   54973: * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   54974: * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   54975: * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   54976: * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   54977: * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   54978: * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   54979: * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   54980: NOTE!
                   54981: Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   54982: to migrate over to one of the alternatives that have ben provided:
                   54983: * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   54984: * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   54985: * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   54986: * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   54987: * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   54988: * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   54989: * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   54990: * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   54991: * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   54992: * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   54993:   PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   54994: PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   54995: pear upgrade -f PEAR will allow people with lower versions
                   54996: to upgrade to this release but no guarantees will be made that it will work properly.
                   54997: Support for XML RPC channels has been dropped - The only ones that used it
                   54998: (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   54999: SOAP support also removed as it was only proof of concept.
                   55000: Move codebase from the PHP License to New BSD 2 clause license
                   55001:     </notes>
                   55002:    </release>
                   55003:    <release>
                   55004:     <version>1.8.0RC1</version>
                   55005:     <date>2009-03-27</date>
                   55006:     <license>New BSD License</license>
                   55007:     <state>beta</state>
                   55008:     <notes>* Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   55009: * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   55010: * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   55011: * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   55012:     </notes>
                   55013:    </release>
                   55014:    <release>
                   55015:    </release>
                   55016:    <release>
                   55017:     <license>New BSD License</license>
                   55018:     <notes>Changes since RC1:
                   55019:   * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz]
                   55020:   * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz]
                   55021:   * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz]
                   55022: 
                   55023:   Remove custom XML_Util class in favor of using upstream XML_Util package as dependency
                   55024: 
                   55025: RC1 Release Notes:
                   55026:   * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   55027:   * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   55028: 
                   55029:   * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   55030:   * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   55031: 
                   55032: Alpha1 Release Notes:
                   55033:   * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   55034:   * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   55035:   * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   55036:   * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   55037:   * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   55038:   * Implement Request #12706: pear list -a hard to read [dufuz]
                   55039:   * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   55040:   * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   55041:   * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   55042:   * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   55043:   * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   55044:     - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   55045:       better what other package managers are doing. upgrade-all will still work as intended.
                   55046:   * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   55047:     - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   55048:       channel specific upgrades
                   55049:   * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   55050:   * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   55051: 
                   55052:   * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   55053:   * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   55054: 
                   55055:   * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   55056:   * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   55057:   * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   55058:   * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   55059:   * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   55060:   * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   55061:   * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   55062:   * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   55063:   * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   55064:   * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   55065:   * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   55066:   * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   55067:   * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   55068:   * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   55069:   * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   55070:   * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   55071:   * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   55072:   * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   55073: 
                   55074:   NOTE!
                   55075:   Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   55076:   to migrate over to one of the alternatives that have ben provided:
                   55077:   * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   55078:   * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   55079:   * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   55080:   * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   55081:   * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   55082:   * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   55083:   * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   55084:   * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   55085:   * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   55086:   * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   55087:     PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   55088: 
                   55089:   PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   55090:   pear upgrade -f PEAR will allow people with lower versions
                   55091:   to upgrade to this release but no guarantees will be made that it will work properly.
                   55092: 
                   55093:   Support for XML RPC channels has been dropped - The only ones that used it
                   55094:   (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   55095:   SOAP support also removed as it was only proof of concept.
                   55096: 
                   55097:   Move codebase from the PHP License to New BSD 2 clause license
                   55098:     </notes>
                   55099:    </release>
                   55100:    <release>
                   55101:     <version>1.8.1</version>
                   55102:     <date>2009-04-15</date>
                   55103:     <license>New BSD License</license>
                   55104:     <state>stable</state>
                   55105:     <notes>* Fix Bug #16099    PEAR crash on PHP4 (parse error) [dufuz]
                   55106:     </notes>
                   55107:    </release>
                   55108:    <release>
                   55109:     <version>1.9.0RC1</version>
                   55110:     <date>2009-08-18</date>
                   55111:     <license>New BSD License</license>
                   55112:     <state>beta</state>
                   55113:     <notes>* Implement Request #16213: add alias to list-channels output [dufuz]
                   55114: * Implement Request #16378: pear svntag [dufuz]
                   55115: * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj]
                   55116: * Implement Request #16396: package-dependencies should allow package names [dufuz]
                   55117: * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz]
                   55118: * Fix Bug #14493: pear install --offline doesn&apos;t print out errors [dufuz]
                   55119: * Fix Bug #11348: pear package-dependencies isn&apos;t well explained [dufuz]
                   55120: * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz]
                   55121: * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz]
                   55122: * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz]
                   55123: * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz]
                   55124: * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj]
                   55125: * Fix Bug #16444: Setting preferred mirror fails [dufuz]
                   55126: * Fix the shutdown functions where a index might not exist and thus raise a notice [derick]
                   55127:     </notes>
                   55128:    </release>
                   55129:    <release>
                   55130:     <version>1.9.0RC2</version>
                   55131:     <date>2009-08-20</date>
                   55132:     <license>New BSD License</license>
                   55133:     <state>beta</state>
                   55134:     <notes>* REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz]
                   55135:     </notes>
                   55136:    </release>
                   55137:    <release>
                   55138:     <version>1.9.0RC3</version>
                   55139:     <date>2009-08-21</date>
                   55140:     <license>New BSD License</license>
                   55141:     <state>beta</state>
                   55142:     <notes>* Improved svntag support to handle packages like PEAR it self [dufuz]
                   55143:     </notes>
                   55144:    </release>
                   55145:    <release>
                   55146:     <version>1.9.0RC4</version>
                   55147:     <date>2009-08-23</date>
                   55148:     <license>New BSD License</license>
                   55149:     <state>beta</state>
                   55150:     <notes>* Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz]
                   55151: * Make sure channel aliases can&apos;t be made to start with - [dufuz]
                   55152: * Output issues with pear search [dufuz]
                   55153: * Fixed couple of stray notices [dufuz]
                   55154:     </notes>
                   55155:    </release>
                   55156:    <release>
                   55157:     <version>1.9.0</version>
                   55158:     <date>2009-09-03</date>
                   55159:     <license>New BSD License</license>
                   55160:     <state>stable</state>
                   55161:     <notes>* Fix  Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz]
                   55162:     </notes>
                   55163:    </release>
                   55164:    <release>
                   55165:     <version>1.9.1</version>
                   55166:     <date>2010-05-26</date>
                   55167:     <license>New BSD License</license>
                   55168:     <state>stable</state>
                   55169:     <notes>* svntag improvements, tag package files passed into the command and better directory checks [dufuz]
                   55170: * rely on Structures_Graph minimum version instead of recommended version [saltybeagle]
                   55171: * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz]
                   55172: * Fix Bug #14841: Installing pear into directory with space fails [dufuz]
                   55173: * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)]
                   55174: * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)]
                   55175: * Fix Bug #16864: &quot;pear list-upgrades -i&quot; issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)]
                   55176: * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz]
                   55177: * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz]
                   55178: * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian]
                   55179: * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz]
                   55180: * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz]
                   55181:     </notes>
                   55182:    </release>
                   55183:    <release>
                   55184:     <version>1.9.2</version>
                   55185:     <date>2011-02-28</date>
                   55186:     <license>New BSD License</license>
                   55187:     <state>stable</state>
                   55188:     <notes>Important! This is a security fix release. The advisory can be found at
                   55189: http://pear.php.net/advisory-20110228.txt
                   55190: 
                   55191:     Bugs:
                   55192:     * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor]
                   55193:     * Fixed Bug #17641: pecl-list doesn&apos;t sort packages by name [dufuz]
                   55194:     * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz]
                   55195:     * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)]
                   55196:     * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz]
                   55197:     * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz]
                   55198:     * Fixed Bug #17997: Strange output if directories are not writeable [dufuz]
                   55199:     * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz]
                   55200:     * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz]
                   55201:     * Fixed Bug #18218: &quot;pear package&quot; does not allow the use of late static binding [dufuz and Christer Edvartsen]
                   55202:     * Fixed Bug #18238: Wrong return code from &quot;pear help&quot; [till]
                   55203:     * Fixed Bug #18308: Broken error message about missing channel validator [yunosh]
                   55204: 
                   55205:     This feature is implemented as a result of #18056
                   55206:     * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz]
                   55207:     </notes>
                   55208:    </release>
                   55209:    <release>
                   55210:     <version>1.9.3</version>
                   55211:     <date>2011-06-04</date>
                   55212:     <license>New BSD License</license>
                   55213:     <state>stable</state>
                   55214:     <notes>* Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz]
                   55215: * Fixed Bug #18340: raiseErro typo [doconnor]
                   55216: * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz]
                   55217: * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz]
                   55218: * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz]
                   55219: * Fixed Bug #18428: invalid preg_match patterns [glen]
                   55220: * Fixed Bug #18486: REST/10.php does not check error condition [dufuz]
                   55221: * Fixed a problem in RunTest and code coverage. Correctly register the
                   55222:   code coverage shutdown function in case we are inside a namespace. [sebastian]
                   55223: * Fixed a bug with extensions not providing their config.m4 and co in the root directory
                   55224:   of their pecl package but rather in a sub directory, such as xhprof. [dufuz]
                   55225:     </notes>
                   55226:    </release>
                   55227:  </changelog>
                   55228: </package>
                   55229: <?php
                   55230: /**
                   55231:  * PEAR, the PHP Extension and Application Repository
                   55232:  *
                   55233:  * PEAR class and PEAR_Error class
                   55234:  *
                   55235:  * PHP versions 4 and 5
                   55236:  *
                   55237:  * @category   pear
                   55238:  * @package    PEAR
                   55239:  * @author     Sterling Hughes <sterling@php.net>
                   55240:  * @author     Stig Bakken <ssb@php.net>
                   55241:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   55242:  * @author     Greg Beaver <cellog@php.net>
                   55243:  * @copyright  1997-2010 The Authors
                   55244:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   55245:  * @version    CVS: $Id: PEAR.php 299159 2010-05-08 22:32:52Z dufuz $
                   55246:  * @link       http://pear.php.net/package/PEAR
                   55247:  * @since      File available since Release 0.1
                   55248:  */
                   55249: 
                   55250: /**#@+
                   55251:  * ERROR constants
                   55252:  */
                   55253: define('PEAR_ERROR_RETURN',     1);
                   55254: define('PEAR_ERROR_PRINT',      2);
                   55255: define('PEAR_ERROR_TRIGGER',    4);
                   55256: define('PEAR_ERROR_DIE',        8);
                   55257: define('PEAR_ERROR_CALLBACK',  16);
                   55258: /**
                   55259:  * WARNING: obsolete
                   55260:  * @deprecated
                   55261:  */
                   55262: define('PEAR_ERROR_EXCEPTION', 32);
                   55263: /**#@-*/
                   55264: define('PEAR_ZE2', (function_exists('version_compare') &&
                   55265:                     version_compare(zend_version(), "2-dev", "ge")));
                   55266: 
                   55267: if (substr(PHP_OS, 0, 3) == 'WIN') {
                   55268:     define('OS_WINDOWS', true);
                   55269:     define('OS_UNIX',    false);
                   55270:     define('PEAR_OS',    'Windows');
                   55271: } else {
                   55272:     define('OS_WINDOWS', false);
                   55273:     define('OS_UNIX',    true);
                   55274:     define('PEAR_OS',    'Unix'); // blatant assumption
                   55275: }
                   55276: 
                   55277: $GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
                   55278: $GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
                   55279: $GLOBALS['_PEAR_destructor_object_list'] = array();
                   55280: $GLOBALS['_PEAR_shutdown_funcs']         = array();
                   55281: $GLOBALS['_PEAR_error_handler_stack']    = array();
                   55282: 
                   55283: @ini_set('track_errors', true);
                   55284: 
                   55285: /**
                   55286:  * Base class for other PEAR classes.  Provides rudimentary
                   55287:  * emulation of destructors.
                   55288:  *
                   55289:  * If you want a destructor in your class, inherit PEAR and make a
                   55290:  * destructor method called _yourclassname (same name as the
                   55291:  * constructor, but with a "_" prefix).  Also, in your constructor you
                   55292:  * have to call the PEAR constructor: $this->PEAR();.
                   55293:  * The destructor method will be called without parameters.  Note that
                   55294:  * at in some SAPI implementations (such as Apache), any output during
                   55295:  * the request shutdown (in which destructors are called) seems to be
                   55296:  * discarded.  If you need to get any debug information from your
                   55297:  * destructor, use error_log(), syslog() or something similar.
                   55298:  *
                   55299:  * IMPORTANT! To use the emulated destructors you need to create the
                   55300:  * objects by reference: $obj =& new PEAR_child;
                   55301:  *
                   55302:  * @category   pear
                   55303:  * @package    PEAR
                   55304:  * @author     Stig Bakken <ssb@php.net>
                   55305:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   55306:  * @author     Greg Beaver <cellog@php.net>
                   55307:  * @copyright  1997-2006 The PHP Group
                   55308:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   55309:  * @version    Release: 1.10.0beta1
                   55310:  * @link       http://pear.php.net/package/PEAR
                   55311:  * @see        PEAR_Error
                   55312:  * @since      Class available since PHP 4.0.2
                   55313:  * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
                   55314:  */
                   55315: class PEAR
                   55316: {
                   55317:     /**
                   55318:      * Whether to enable internal debug messages.
                   55319:      *
                   55320:      * @var     bool
                   55321:      * @access  private
                   55322:      */
                   55323:     var $_debug = false;
                   55324: 
                   55325:     /**
                   55326:      * Default error mode for this object.
                   55327:      *
                   55328:      * @var     int
                   55329:      * @access  private
                   55330:      */
                   55331:     var $_default_error_mode = null;
                   55332: 
                   55333:     /**
                   55334:      * Default error options used for this object when error mode
                   55335:      * is PEAR_ERROR_TRIGGER.
                   55336:      *
                   55337:      * @var     int
                   55338:      * @access  private
                   55339:      */
                   55340:     var $_default_error_options = null;
                   55341: 
                   55342:     /**
                   55343:      * Default error handler (callback) for this object, if error mode is
                   55344:      * PEAR_ERROR_CALLBACK.
                   55345:      *
                   55346:      * @var     string
                   55347:      * @access  private
                   55348:      */
                   55349:     var $_default_error_handler = '';
                   55350: 
                   55351:     /**
                   55352:      * Which class to use for error objects.
                   55353:      *
                   55354:      * @var     string
                   55355:      * @access  private
                   55356:      */
                   55357:     var $_error_class = 'PEAR_Error';
                   55358: 
                   55359:     /**
                   55360:      * An array of expected errors.
                   55361:      *
                   55362:      * @var     array
                   55363:      * @access  private
                   55364:      */
                   55365:     var $_expected_errors = array();
                   55366: 
                   55367:     /**
                   55368:      * Constructor.  Registers this object in
                   55369:      * $_PEAR_destructor_object_list for destructor emulation if a
                   55370:      * destructor object exists.
                   55371:      *
                   55372:      * @param string $error_class  (optional) which class to use for
                   55373:      *        error objects, defaults to PEAR_Error.
                   55374:      * @access public
                   55375:      * @return void
                   55376:      */
                   55377:     function PEAR($error_class = null)
                   55378:     {
                   55379:         $classname = strtolower(get_class($this));
                   55380:         if ($this->_debug) {
                   55381:             print "PEAR constructor called, class=$classname\n";
                   55382:         }
                   55383: 
                   55384:         if ($error_class !== null) {
                   55385:             $this->_error_class = $error_class;
                   55386:         }
                   55387: 
                   55388:         while ($classname && strcasecmp($classname, "pear")) {
                   55389:             $destructor = "_$classname";
                   55390:             if (method_exists($this, $destructor)) {
                   55391:                 global $_PEAR_destructor_object_list;
                   55392:                 $_PEAR_destructor_object_list[] = &$this;
                   55393:                 if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   55394:                     register_shutdown_function("_PEAR_call_destructors");
                   55395:                     $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   55396:                 }
                   55397:                 break;
                   55398:             } else {
                   55399:                 $classname = get_parent_class($classname);
                   55400:             }
                   55401:         }
                   55402:     }
                   55403: 
                   55404:     /**
                   55405:      * Destructor (the emulated type of...).  Does nothing right now,
                   55406:      * but is included for forward compatibility, so subclass
                   55407:      * destructors should always call it.
                   55408:      *
                   55409:      * See the note in the class desciption about output from
                   55410:      * destructors.
                   55411:      *
                   55412:      * @access public
                   55413:      * @return void
                   55414:      */
                   55415:     function _PEAR() {
                   55416:         if ($this->_debug) {
                   55417:             printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
                   55418:         }
                   55419:     }
                   55420: 
                   55421:     /**
                   55422:     * If you have a class that's mostly/entirely static, and you need static
                   55423:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   55424:     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
                   55425:     * You MUST use a reference, or they will not persist!
                   55426:     *
                   55427:     * @access public
                   55428:     * @param  string $class  The calling classname, to prevent clashes
                   55429:     * @param  string $var    The variable to retrieve.
                   55430:     * @return mixed   A reference to the variable. If not set it will be
                   55431:     *                 auto initialised to NULL.
                   55432:     */
                   55433:     function &getStaticProperty($class, $var)
                   55434:     {
                   55435:         static $properties;
                   55436:         if (!isset($properties[$class])) {
                   55437:             $properties[$class] = array();
                   55438:         }
                   55439: 
                   55440:         if (!array_key_exists($var, $properties[$class])) {
                   55441:             $properties[$class][$var] = null;
                   55442:         }
                   55443: 
                   55444:         return $properties[$class][$var];
                   55445:     }
                   55446: 
                   55447:     /**
                   55448:     * Use this function to register a shutdown method for static
                   55449:     * classes.
                   55450:     *
                   55451:     * @access public
                   55452:     * @param  mixed $func  The function name (or array of class/method) to call
                   55453:     * @param  mixed $args  The arguments to pass to the function
                   55454:     * @return void
                   55455:     */
                   55456:     function registerShutdownFunc($func, $args = array())
                   55457:     {
                   55458:         // if we are called statically, there is a potential
                   55459:         // that no shutdown func is registered.  Bug #6445
                   55460:         if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   55461:             register_shutdown_function("_PEAR_call_destructors");
                   55462:             $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   55463:         }
                   55464:         $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
                   55465:     }
                   55466: 
                   55467:     /**
                   55468:      * Tell whether a value is a PEAR error.
                   55469:      *
                   55470:      * @param   mixed $data   the value to test
                   55471:      * @param   int   $code   if $data is an error object, return true
                   55472:      *                        only if $code is a string and
                   55473:      *                        $obj->getMessage() == $code or
                   55474:      *                        $code is an integer and $obj->getCode() == $code
                   55475:      * @access  public
                   55476:      * @return  bool    true if parameter is an error
                   55477:      */
                   55478:     function isError($data, $code = null)
                   55479:     {
                   55480:         if (!is_a($data, 'PEAR_Error')) {
                   55481:             return false;
                   55482:         }
                   55483: 
                   55484:         if (is_null($code)) {
                   55485:             return true;
                   55486:         } elseif (is_string($code)) {
                   55487:             return $data->getMessage() == $code;
                   55488:         }
                   55489: 
                   55490:         return $data->getCode() == $code;
                   55491:     }
                   55492: 
                   55493:     /**
                   55494:      * Sets how errors generated by this object should be handled.
                   55495:      * Can be invoked both in objects and statically.  If called
                   55496:      * statically, setErrorHandling sets the default behaviour for all
                   55497:      * PEAR objects.  If called in an object, setErrorHandling sets
                   55498:      * the default behaviour for that object.
                   55499:      *
                   55500:      * @param int $mode
                   55501:      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   55502:      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   55503:      *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
                   55504:      *
                   55505:      * @param mixed $options
                   55506:      *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
                   55507:      *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   55508:      *
                   55509:      *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
                   55510:      *        to be the callback function or method.  A callback
                   55511:      *        function is a string with the name of the function, a
                   55512:      *        callback method is an array of two elements: the element
                   55513:      *        at index 0 is the object, and the element at index 1 is
                   55514:      *        the name of the method to call in the object.
                   55515:      *
                   55516:      *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
                   55517:      *        a printf format string used when printing the error
                   55518:      *        message.
                   55519:      *
                   55520:      * @access public
                   55521:      * @return void
                   55522:      * @see PEAR_ERROR_RETURN
                   55523:      * @see PEAR_ERROR_PRINT
                   55524:      * @see PEAR_ERROR_TRIGGER
                   55525:      * @see PEAR_ERROR_DIE
                   55526:      * @see PEAR_ERROR_CALLBACK
                   55527:      * @see PEAR_ERROR_EXCEPTION
                   55528:      *
                   55529:      * @since PHP 4.0.5
                   55530:      */
                   55531:     function setErrorHandling($mode = null, $options = null)
                   55532:     {
                   55533:         if (isset($this) && is_a($this, 'PEAR')) {
                   55534:             $setmode     = &$this->_default_error_mode;
                   55535:             $setoptions  = &$this->_default_error_options;
                   55536:         } else {
                   55537:             $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   55538:             $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   55539:         }
                   55540: 
                   55541:         switch ($mode) {
                   55542:             case PEAR_ERROR_EXCEPTION:
                   55543:             case PEAR_ERROR_RETURN:
                   55544:             case PEAR_ERROR_PRINT:
                   55545:             case PEAR_ERROR_TRIGGER:
                   55546:             case PEAR_ERROR_DIE:
                   55547:             case null:
                   55548:                 $setmode = $mode;
                   55549:                 $setoptions = $options;
                   55550:                 break;
                   55551: 
                   55552:             case PEAR_ERROR_CALLBACK:
                   55553:                 $setmode = $mode;
                   55554:                 // class/object method callback
                   55555:                 if (is_callable($options)) {
                   55556:                     $setoptions = $options;
                   55557:                 } else {
                   55558:                     trigger_error("invalid error callback", E_USER_WARNING);
                   55559:                 }
                   55560:                 break;
                   55561: 
                   55562:             default:
                   55563:                 trigger_error("invalid error mode", E_USER_WARNING);
                   55564:                 break;
                   55565:         }
                   55566:     }
                   55567: 
                   55568:     /**
                   55569:      * This method is used to tell which errors you expect to get.
                   55570:      * Expected errors are always returned with error mode
                   55571:      * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
                   55572:      * and this method pushes a new element onto it.  The list of
                   55573:      * expected errors are in effect until they are popped off the
                   55574:      * stack with the popExpect() method.
                   55575:      *
                   55576:      * Note that this method can not be called statically
                   55577:      *
                   55578:      * @param mixed $code a single error code or an array of error codes to expect
                   55579:      *
                   55580:      * @return int     the new depth of the "expected errors" stack
                   55581:      * @access public
                   55582:      */
                   55583:     function expectError($code = '*')
                   55584:     {
                   55585:         if (is_array($code)) {
                   55586:             array_push($this->_expected_errors, $code);
                   55587:         } else {
                   55588:             array_push($this->_expected_errors, array($code));
                   55589:         }
                   55590:         return count($this->_expected_errors);
                   55591:     }
                   55592: 
                   55593:     /**
                   55594:      * This method pops one element off the expected error codes
                   55595:      * stack.
                   55596:      *
                   55597:      * @return array   the list of error codes that were popped
                   55598:      */
                   55599:     function popExpect()
                   55600:     {
                   55601:         return array_pop($this->_expected_errors);
                   55602:     }
                   55603: 
                   55604:     /**
                   55605:      * This method checks unsets an error code if available
                   55606:      *
                   55607:      * @param mixed error code
                   55608:      * @return bool true if the error code was unset, false otherwise
                   55609:      * @access private
                   55610:      * @since PHP 4.3.0
                   55611:      */
                   55612:     function _checkDelExpect($error_code)
                   55613:     {
                   55614:         $deleted = false;
                   55615:         foreach ($this->_expected_errors as $key => $error_array) {
                   55616:             if (in_array($error_code, $error_array)) {
                   55617:                 unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
                   55618:                 $deleted = true;
                   55619:             }
                   55620: 
                   55621:             // clean up empty arrays
                   55622:             if (0 == count($this->_expected_errors[$key])) {
                   55623:                 unset($this->_expected_errors[$key]);
                   55624:             }
                   55625:         }
                   55626: 
                   55627:         return $deleted;
                   55628:     }
                   55629: 
                   55630:     /**
                   55631:      * This method deletes all occurences of the specified element from
                   55632:      * the expected error codes stack.
                   55633:      *
                   55634:      * @param  mixed $error_code error code that should be deleted
                   55635:      * @return mixed list of error codes that were deleted or error
                   55636:      * @access public
                   55637:      * @since PHP 4.3.0
                   55638:      */
                   55639:     function delExpect($error_code)
                   55640:     {
                   55641:         $deleted = false;
                   55642:         if ((is_array($error_code) && (0 != count($error_code)))) {
                   55643:             // $error_code is a non-empty array here; we walk through it trying
                   55644:             // to unset all values
                   55645:             foreach ($error_code as $key => $error) {
                   55646:                 $deleted =  $this->_checkDelExpect($error) ? true : false;
                   55647:             }
                   55648: 
                   55649:             return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   55650:         } elseif (!empty($error_code)) {
                   55651:             // $error_code comes alone, trying to unset it
                   55652:             if ($this->_checkDelExpect($error_code)) {
                   55653:                 return true;
                   55654:             }
                   55655: 
                   55656:             return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   55657:         }
                   55658: 
                   55659:         // $error_code is empty
                   55660:         return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
                   55661:     }
                   55662: 
                   55663:     /**
                   55664:      * This method is a wrapper that returns an instance of the
                   55665:      * configured error class with this object's default error
                   55666:      * handling applied.  If the $mode and $options parameters are not
                   55667:      * specified, the object's defaults are used.
                   55668:      *
                   55669:      * @param mixed $message a text error message or a PEAR error object
                   55670:      *
                   55671:      * @param int $code      a numeric error code (it is up to your class
                   55672:      *                  to define these if you want to use codes)
                   55673:      *
                   55674:      * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   55675:      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   55676:      *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
                   55677:      *
                   55678:      * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
                   55679:      *                  specifies the PHP-internal error level (one of
                   55680:      *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   55681:      *                  If $mode is PEAR_ERROR_CALLBACK, this
                   55682:      *                  parameter specifies the callback function or
                   55683:      *                  method.  In other error modes this parameter
                   55684:      *                  is ignored.
                   55685:      *
                   55686:      * @param string $userinfo If you need to pass along for example debug
                   55687:      *                  information, this parameter is meant for that.
                   55688:      *
                   55689:      * @param string $error_class The returned error object will be
                   55690:      *                  instantiated from this class, if specified.
                   55691:      *
                   55692:      * @param bool $skipmsg If true, raiseError will only pass error codes,
                   55693:      *                  the error message parameter will be dropped.
                   55694:      *
                   55695:      * @access public
                   55696:      * @return object   a PEAR error object
                   55697:      * @see PEAR::setErrorHandling
                   55698:      * @since PHP 4.0.5
                   55699:      */
                   55700:     function &raiseError($message = null,
                   55701:                          $code = null,
                   55702:                          $mode = null,
                   55703:                          $options = null,
                   55704:                          $userinfo = null,
                   55705:                          $error_class = null,
                   55706:                          $skipmsg = false)
                   55707:     {
                   55708:         // The error is yet a PEAR error object
                   55709:         if (is_object($message)) {
                   55710:             $code        = $message->getCode();
                   55711:             $userinfo    = $message->getUserInfo();
                   55712:             $error_class = $message->getType();
                   55713:             $message->error_message_prefix = '';
                   55714:             $message     = $message->getMessage();
                   55715:         }
                   55716: 
                   55717:         if (
                   55718:             isset($this) &&
                   55719:             isset($this->_expected_errors) &&
                   55720:             count($this->_expected_errors) > 0 &&
                   55721:             count($exp = end($this->_expected_errors))
                   55722:         ) {
                   55723:             if ($exp[0] == "*" ||
                   55724:                 (is_int(reset($exp)) && in_array($code, $exp)) ||
                   55725:                 (is_string(reset($exp)) && in_array($message, $exp))
                   55726:             ) {
                   55727:                 $mode = PEAR_ERROR_RETURN;
                   55728:             }
                   55729:         }
                   55730: 
                   55731:         // No mode given, try global ones
                   55732:         if ($mode === null) {
                   55733:             // Class error handler
                   55734:             if (isset($this) && isset($this->_default_error_mode)) {
                   55735:                 $mode    = $this->_default_error_mode;
                   55736:                 $options = $this->_default_error_options;
                   55737:             // Global error handler
                   55738:             } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
                   55739:                 $mode    = $GLOBALS['_PEAR_default_error_mode'];
                   55740:                 $options = $GLOBALS['_PEAR_default_error_options'];
                   55741:             }
                   55742:         }
                   55743: 
                   55744:         if ($error_class !== null) {
                   55745:             $ec = $error_class;
                   55746:         } elseif (isset($this) && isset($this->_error_class)) {
                   55747:             $ec = $this->_error_class;
                   55748:         } else {
                   55749:             $ec = 'PEAR_Error';
                   55750:         }
                   55751: 
                   55752:         if (intval(PHP_VERSION) < 5) {
                   55753:             // little non-eval hack to fix bug #12147
                   55754:             include 'phar://install-pear-nozlib.phar/' . 'PEAR/FixPHP5PEARWarnings.php';
                   55755:             return $a;
                   55756:         }
                   55757: 
                   55758:         if ($skipmsg) {
                   55759:             $a = new $ec($code, $mode, $options, $userinfo);
                   55760:         } else {
                   55761:             $a = new $ec($message, $code, $mode, $options, $userinfo);
                   55762:         }
                   55763: 
                   55764:         return $a;
                   55765:     }
                   55766: 
                   55767:     /**
                   55768:      * Simpler form of raiseError with fewer options.  In most cases
                   55769:      * message, code and userinfo are enough.
                   55770:      *
                   55771:      * @param mixed $message a text error message or a PEAR error object
                   55772:      *
                   55773:      * @param int $code      a numeric error code (it is up to your class
                   55774:      *                  to define these if you want to use codes)
                   55775:      *
                   55776:      * @param string $userinfo If you need to pass along for example debug
                   55777:      *                  information, this parameter is meant for that.
                   55778:      *
                   55779:      * @access public
                   55780:      * @return object   a PEAR error object
                   55781:      * @see PEAR::raiseError
                   55782:      */
                   55783:     function &throwError($message = null, $code = null, $userinfo = null)
                   55784:     {
                   55785:         if (isset($this) && is_a($this, 'PEAR')) {
                   55786:             $a = &$this->raiseError($message, $code, null, null, $userinfo);
                   55787:             return $a;
                   55788:         }
                   55789: 
                   55790:         $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
                   55791:         return $a;
                   55792:     }
                   55793: 
                   55794:     function staticPushErrorHandling($mode, $options = null)
                   55795:     {
                   55796:         $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
                   55797:         $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   55798:         $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   55799:         $stack[] = array($def_mode, $def_options);
                   55800:         switch ($mode) {
                   55801:             case PEAR_ERROR_EXCEPTION:
                   55802:             case PEAR_ERROR_RETURN:
                   55803:             case PEAR_ERROR_PRINT:
                   55804:             case PEAR_ERROR_TRIGGER:
                   55805:             case PEAR_ERROR_DIE:
                   55806:             case null:
                   55807:                 $def_mode = $mode;
                   55808:                 $def_options = $options;
                   55809:                 break;
                   55810: 
                   55811:             case PEAR_ERROR_CALLBACK:
                   55812:                 $def_mode = $mode;
                   55813:                 // class/object method callback
                   55814:                 if (is_callable($options)) {
                   55815:                     $def_options = $options;
                   55816:                 } else {
                   55817:                     trigger_error("invalid error callback", E_USER_WARNING);
                   55818:                 }
                   55819:                 break;
                   55820: 
                   55821:             default:
                   55822:                 trigger_error("invalid error mode", E_USER_WARNING);
                   55823:                 break;
                   55824:         }
                   55825:         $stack[] = array($mode, $options);
                   55826:         return true;
                   55827:     }
                   55828: 
                   55829:     function staticPopErrorHandling()
                   55830:     {
                   55831:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   55832:         $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   55833:         $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   55834:         array_pop($stack);
                   55835:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   55836:         array_pop($stack);
                   55837:         switch ($mode) {
                   55838:             case PEAR_ERROR_EXCEPTION:
                   55839:             case PEAR_ERROR_RETURN:
                   55840:             case PEAR_ERROR_PRINT:
                   55841:             case PEAR_ERROR_TRIGGER:
                   55842:             case PEAR_ERROR_DIE:
                   55843:             case null:
                   55844:                 $setmode = $mode;
                   55845:                 $setoptions = $options;
                   55846:                 break;
                   55847: 
                   55848:             case PEAR_ERROR_CALLBACK:
                   55849:                 $setmode = $mode;
                   55850:                 // class/object method callback
                   55851:                 if (is_callable($options)) {
                   55852:                     $setoptions = $options;
                   55853:                 } else {
                   55854:                     trigger_error("invalid error callback", E_USER_WARNING);
                   55855:                 }
                   55856:                 break;
                   55857: 
                   55858:             default:
                   55859:                 trigger_error("invalid error mode", E_USER_WARNING);
                   55860:                 break;
                   55861:         }
                   55862:         return true;
                   55863:     }
                   55864: 
                   55865:     /**
                   55866:      * Push a new error handler on top of the error handler options stack. With this
                   55867:      * you can easily override the actual error handler for some code and restore
                   55868:      * it later with popErrorHandling.
                   55869:      *
                   55870:      * @param mixed $mode (same as setErrorHandling)
                   55871:      * @param mixed $options (same as setErrorHandling)
                   55872:      *
                   55873:      * @return bool Always true
                   55874:      *
                   55875:      * @see PEAR::setErrorHandling
                   55876:      */
                   55877:     function pushErrorHandling($mode, $options = null)
                   55878:     {
                   55879:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   55880:         if (isset($this) && is_a($this, 'PEAR')) {
                   55881:             $def_mode    = &$this->_default_error_mode;
                   55882:             $def_options = &$this->_default_error_options;
                   55883:         } else {
                   55884:             $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   55885:             $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   55886:         }
                   55887:         $stack[] = array($def_mode, $def_options);
                   55888: 
                   55889:         if (isset($this) && is_a($this, 'PEAR')) {
                   55890:             $this->setErrorHandling($mode, $options);
                   55891:         } else {
                   55892:             PEAR::setErrorHandling($mode, $options);
                   55893:         }
                   55894:         $stack[] = array($mode, $options);
                   55895:         return true;
                   55896:     }
                   55897: 
                   55898:     /**
                   55899:     * Pop the last error handler used
                   55900:     *
                   55901:     * @return bool Always true
                   55902:     *
                   55903:     * @see PEAR::pushErrorHandling
                   55904:     */
                   55905:     function popErrorHandling()
                   55906:     {
                   55907:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   55908:         array_pop($stack);
                   55909:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   55910:         array_pop($stack);
                   55911:         if (isset($this) && is_a($this, 'PEAR')) {
                   55912:             $this->setErrorHandling($mode, $options);
                   55913:         } else {
                   55914:             PEAR::setErrorHandling($mode, $options);
                   55915:         }
                   55916:         return true;
                   55917:     }
                   55918: 
                   55919:     /**
                   55920:     * OS independant PHP extension load. Remember to take care
                   55921:     * on the correct extension name for case sensitive OSes.
                   55922:     *
                   55923:     * @param string $ext The extension name
                   55924:     * @return bool Success or not on the dl() call
                   55925:     */
                   55926:     function loadExtension($ext)
                   55927:     {
                   55928:         if (extension_loaded($ext)) {
                   55929:             return true;
                   55930:         }
                   55931: 
                   55932:         // if either returns true dl() will produce a FATAL error, stop that
                   55933:         if (
                   55934:             function_exists('dl') === false ||
                   55935:             ini_get('enable_dl') != 1 ||
                   55936:             ini_get('safe_mode') == 1
                   55937:         ) {
                   55938:             return false;
                   55939:         }
                   55940: 
                   55941:         if (OS_WINDOWS) {
                   55942:             $suffix = '.dll';
                   55943:         } elseif (PHP_OS == 'HP-UX') {
                   55944:             $suffix = '.sl';
                   55945:         } elseif (PHP_OS == 'AIX') {
                   55946:             $suffix = '.a';
                   55947:         } elseif (PHP_OS == 'OSX') {
                   55948:             $suffix = '.bundle';
                   55949:         } else {
                   55950:             $suffix = '.so';
                   55951:         }
                   55952: 
                   55953:         return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
                   55954:     }
                   55955: }
                   55956: 
                   55957: if (PEAR_ZE2) {
                   55958:     include_once 'phar://install-pear-nozlib.phar/' . 'PEAR5.php';
                   55959: }
                   55960: 
                   55961: function _PEAR_call_destructors()
                   55962: {
                   55963:     global $_PEAR_destructor_object_list;
                   55964:     if (is_array($_PEAR_destructor_object_list) &&
                   55965:         sizeof($_PEAR_destructor_object_list))
                   55966:     {
                   55967:         reset($_PEAR_destructor_object_list);
                   55968:         if (PEAR_ZE2) {
                   55969:             $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
                   55970:         } else {
                   55971:             $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
                   55972:         }
                   55973: 
                   55974:         if ($destructLifoExists) {
                   55975:             $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
                   55976:         }
                   55977: 
                   55978:         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
                   55979:             $classname = get_class($objref);
                   55980:             while ($classname) {
                   55981:                 $destructor = "_$classname";
                   55982:                 if (method_exists($objref, $destructor)) {
                   55983:                     $objref->$destructor();
                   55984:                     break;
                   55985:                 } else {
                   55986:                     $classname = get_parent_class($classname);
                   55987:                 }
                   55988:             }
                   55989:         }
                   55990:         // Empty the object list to ensure that destructors are
                   55991:         // not called more than once.
                   55992:         $_PEAR_destructor_object_list = array();
                   55993:     }
                   55994: 
                   55995:     // Now call the shutdown functions
                   55996:     if (
                   55997:         isset($GLOBALS['_PEAR_shutdown_funcs']) &&
                   55998:         is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
                   55999:         !empty($GLOBALS['_PEAR_shutdown_funcs'])
                   56000:     ) {
                   56001:         foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
                   56002:             call_user_func_array($value[0], $value[1]);
                   56003:         }
                   56004:     }
                   56005: }
                   56006: 
                   56007: /**
                   56008:  * Standard PEAR error class for PHP 4
                   56009:  *
                   56010:  * This class is supserseded by {@link PEAR_Exception} in PHP 5
                   56011:  *
                   56012:  * @category   pear
                   56013:  * @package    PEAR
                   56014:  * @author     Stig Bakken <ssb@php.net>
                   56015:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   56016:  * @author     Gregory Beaver <cellog@php.net>
                   56017:  * @copyright  1997-2006 The PHP Group
                   56018:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   56019:  * @version    Release: 1.10.0beta1
                   56020:  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
                   56021:  * @see        PEAR::raiseError(), PEAR::throwError()
                   56022:  * @since      Class available since PHP 4.0.2
                   56023:  */
                   56024: class PEAR_Error
                   56025: {
                   56026:     var $error_message_prefix = '';
                   56027:     var $mode                 = PEAR_ERROR_RETURN;
                   56028:     var $level                = E_USER_NOTICE;
                   56029:     var $code                 = -1;
                   56030:     var $message              = '';
                   56031:     var $userinfo             = '';
                   56032:     var $backtrace            = null;
                   56033: 
                   56034:     /**
                   56035:      * PEAR_Error constructor
                   56036:      *
                   56037:      * @param string $message  message
                   56038:      *
                   56039:      * @param int $code     (optional) error code
                   56040:      *
                   56041:      * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
                   56042:      * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
                   56043:      * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
                   56044:      *
                   56045:      * @param mixed $options   (optional) error level, _OR_ in the case of
                   56046:      * PEAR_ERROR_CALLBACK, the callback function or object/method
                   56047:      * tuple.
                   56048:      *
                   56049:      * @param string $userinfo (optional) additional user/debug info
                   56050:      *
                   56051:      * @access public
                   56052:      *
                   56053:      */
                   56054:     function PEAR_Error($message = 'unknown error', $code = null,
                   56055:                         $mode = null, $options = null, $userinfo = null)
                   56056:     {
                   56057:         if ($mode === null) {
                   56058:             $mode = PEAR_ERROR_RETURN;
                   56059:         }
                   56060:         $this->message   = $message;
                   56061:         $this->code      = $code;
                   56062:         $this->mode      = $mode;
                   56063:         $this->userinfo  = $userinfo;
                   56064: 
                   56065:         if (PEAR_ZE2) {
                   56066:             $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
                   56067:         } else {
                   56068:             $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
                   56069:         }
                   56070: 
                   56071:         if (!$skiptrace) {
                   56072:             $this->backtrace = debug_backtrace();
                   56073:             if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
                   56074:                 unset($this->backtrace[0]['object']);
                   56075:             }
                   56076:         }
                   56077: 
                   56078:         if ($mode & PEAR_ERROR_CALLBACK) {
                   56079:             $this->level = E_USER_NOTICE;
                   56080:             $this->callback = $options;
                   56081:         } else {
                   56082:             if ($options === null) {
                   56083:                 $options = E_USER_NOTICE;
                   56084:             }
                   56085: 
                   56086:             $this->level = $options;
                   56087:             $this->callback = null;
                   56088:         }
                   56089: 
                   56090:         if ($this->mode & PEAR_ERROR_PRINT) {
                   56091:             if (is_null($options) || is_int($options)) {
                   56092:                 $format = "%s";
                   56093:             } else {
                   56094:                 $format = $options;
                   56095:             }
                   56096: 
                   56097:             printf($format, $this->getMessage());
                   56098:         }
                   56099: 
                   56100:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   56101:             trigger_error($this->getMessage(), $this->level);
                   56102:         }
                   56103: 
                   56104:         if ($this->mode & PEAR_ERROR_DIE) {
                   56105:             $msg = $this->getMessage();
                   56106:             if (is_null($options) || is_int($options)) {
                   56107:                 $format = "%s";
                   56108:                 if (substr($msg, -1) != "\n") {
                   56109:                     $msg .= "\n";
                   56110:                 }
                   56111:             } else {
                   56112:                 $format = $options;
                   56113:             }
                   56114:             die(sprintf($format, $msg));
                   56115:         }
                   56116: 
                   56117:         if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
                   56118:             call_user_func($this->callback, $this);
                   56119:         }
                   56120: 
                   56121:         if ($this->mode & PEAR_ERROR_EXCEPTION) {
                   56122:             trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
                   56123:             eval('$e = new Exception($this->message, $this->code);throw($e);');
                   56124:         }
                   56125:     }
                   56126: 
                   56127:     /**
                   56128:      * Get the error mode from an error object.
                   56129:      *
                   56130:      * @return int error mode
                   56131:      * @access public
                   56132:      */
                   56133:     function getMode()
                   56134:     {
                   56135:         return $this->mode;
                   56136:     }
                   56137: 
                   56138:     /**
                   56139:      * Get the callback function/method from an error object.
                   56140:      *
                   56141:      * @return mixed callback function or object/method array
                   56142:      * @access public
                   56143:      */
                   56144:     function getCallback()
                   56145:     {
                   56146:         return $this->callback;
                   56147:     }
                   56148: 
                   56149:     /**
                   56150:      * Get the error message from an error object.
                   56151:      *
                   56152:      * @return  string  full error message
                   56153:      * @access public
                   56154:      */
                   56155:     function getMessage()
                   56156:     {
                   56157:         return ($this->error_message_prefix . $this->message);
                   56158:     }
                   56159: 
                   56160:     /**
                   56161:      * Get error code from an error object
                   56162:      *
                   56163:      * @return int error code
                   56164:      * @access public
                   56165:      */
                   56166:      function getCode()
                   56167:      {
                   56168:         return $this->code;
                   56169:      }
                   56170: 
                   56171:     /**
                   56172:      * Get the name of this error/exception.
                   56173:      *
                   56174:      * @return string error/exception name (type)
                   56175:      * @access public
                   56176:      */
                   56177:     function getType()
                   56178:     {
                   56179:         return get_class($this);
                   56180:     }
                   56181: 
                   56182:     /**
                   56183:      * Get additional user-supplied information.
                   56184:      *
                   56185:      * @return string user-supplied information
                   56186:      * @access public
                   56187:      */
                   56188:     function getUserInfo()
                   56189:     {
                   56190:         return $this->userinfo;
                   56191:     }
                   56192: 
                   56193:     /**
                   56194:      * Get additional debug information supplied by the application.
                   56195:      *
                   56196:      * @return string debug information
                   56197:      * @access public
                   56198:      */
                   56199:     function getDebugInfo()
                   56200:     {
                   56201:         return $this->getUserInfo();
                   56202:     }
                   56203: 
                   56204:     /**
                   56205:      * Get the call backtrace from where the error was generated.
                   56206:      * Supported with PHP 4.3.0 or newer.
                   56207:      *
                   56208:      * @param int $frame (optional) what frame to fetch
                   56209:      * @return array Backtrace, or NULL if not available.
                   56210:      * @access public
                   56211:      */
                   56212:     function getBacktrace($frame = null)
                   56213:     {
                   56214:         if (defined('PEAR_IGNORE_BACKTRACE')) {
                   56215:             return null;
                   56216:         }
                   56217:         if ($frame === null) {
                   56218:             return $this->backtrace;
                   56219:         }
                   56220:         return $this->backtrace[$frame];
                   56221:     }
                   56222: 
                   56223:     function addUserInfo($info)
                   56224:     {
                   56225:         if (empty($this->userinfo)) {
                   56226:             $this->userinfo = $info;
                   56227:         } else {
                   56228:             $this->userinfo .= " ** $info";
                   56229:         }
                   56230:     }
                   56231: 
                   56232:     function __toString()
                   56233:     {
                   56234:         return $this->getMessage();
                   56235:     }
                   56236: 
                   56237:     /**
                   56238:      * Make a string representation of this object.
                   56239:      *
                   56240:      * @return string a string with an object summary
                   56241:      * @access public
                   56242:      */
                   56243:     function toString()
                   56244:     {
                   56245:         $modes = array();
                   56246:         $levels = array(E_USER_NOTICE  => 'notice',
                   56247:                         E_USER_WARNING => 'warning',
                   56248:                         E_USER_ERROR   => 'error');
                   56249:         if ($this->mode & PEAR_ERROR_CALLBACK) {
                   56250:             if (is_array($this->callback)) {
                   56251:                 $callback = (is_object($this->callback[0]) ?
                   56252:                     strtolower(get_class($this->callback[0])) :
                   56253:                     $this->callback[0]) . '::' .
                   56254:                     $this->callback[1];
                   56255:             } else {
                   56256:                 $callback = $this->callback;
                   56257:             }
                   56258:             return sprintf('[%s: message="%s" code=%d mode=callback '.
                   56259:                            'callback=%s prefix="%s" info="%s"]',
                   56260:                            strtolower(get_class($this)), $this->message, $this->code,
                   56261:                            $callback, $this->error_message_prefix,
                   56262:                            $this->userinfo);
                   56263:         }
                   56264:         if ($this->mode & PEAR_ERROR_PRINT) {
                   56265:             $modes[] = 'print';
                   56266:         }
                   56267:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   56268:             $modes[] = 'trigger';
                   56269:         }
                   56270:         if ($this->mode & PEAR_ERROR_DIE) {
                   56271:             $modes[] = 'die';
                   56272:         }
                   56273:         if ($this->mode & PEAR_ERROR_RETURN) {
                   56274:             $modes[] = 'return';
                   56275:         }
                   56276:         return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
                   56277:                        'prefix="%s" info="%s"]',
                   56278:                        strtolower(get_class($this)), $this->message, $this->code,
                   56279:                        implode("|", $modes), $levels[$this->level],
                   56280:                        $this->error_message_prefix,
                   56281:                        $this->userinfo);
                   56282:     }
                   56283: }
                   56284: 
                   56285: /*
                   56286:  * Local Variables:
                   56287:  * mode: php
                   56288:  * tab-width: 4
                   56289:  * c-basic-offset: 4
                   56290:  * End:
                   56291:  */
                   56292: <?php
                   56293: /**
                   56294:  * PEAR_ChannelFile, the channel handling class
                   56295:  *
                   56296:  * PHP versions 4 and 5
                   56297:  *
                   56298:  * @category   pear
                   56299:  * @package    PEAR
                   56300:  * @author     Greg Beaver <cellog@php.net>
                   56301:  * @copyright  1997-2009 The Authors
                   56302:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   56303:  * @version    CVS: $Id: ChannelFile.php 286951 2009-08-09 14:41:22Z dufuz $
                   56304:  * @link       http://pear.php.net/package/PEAR
                   56305:  * @since      File available since Release 1.4.0a1
                   56306:  */
                   56307: 
                   56308: /**
                   56309:  * Needed for error handling
                   56310:  */
                   56311: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
                   56312: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   56313: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   56314: 
                   56315: /**
                   56316:  * Error code if the channel.xml <channel> tag does not contain a valid version
                   56317:  */
                   56318: define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
                   56319: /**
                   56320:  * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
                   56321:  * currently
                   56322:  */
                   56323: define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
                   56324: 
                   56325: /**
                   56326:  * Error code if parsing is attempted with no xml extension
                   56327:  */
                   56328: define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
                   56329: 
                   56330: /**
                   56331:  * Error code if creating the xml parser resource fails
                   56332:  */
                   56333: define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
                   56334: 
                   56335: /**
                   56336:  * Error code used for all sax xml parsing errors
                   56337:  */
                   56338: define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
                   56339: 
                   56340: /**#@+
                   56341:  * Validation errors
                   56342:  */
                   56343: /**
                   56344:  * Error code when channel name is missing
                   56345:  */
                   56346: define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
                   56347: /**
                   56348:  * Error code when channel name is invalid
                   56349:  */
                   56350: define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
                   56351: /**
                   56352:  * Error code when channel summary is missing
                   56353:  */
                   56354: define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
                   56355: /**
                   56356:  * Error code when channel summary is multi-line
                   56357:  */
                   56358: define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
                   56359: /**
                   56360:  * Error code when channel server is missing for protocol
                   56361:  */
                   56362: define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
                   56363: /**
                   56364:  * Error code when channel server is invalid for protocol
                   56365:  */
                   56366: define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
                   56367: /**
                   56368:  * Error code when a mirror name is invalid
                   56369:  */
                   56370: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
                   56371: /**
                   56372:  * Error code when a mirror type is invalid
                   56373:  */
                   56374: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
                   56375: /**
                   56376:  * Error code when an attempt is made to generate xml, but the parsed content is invalid
                   56377:  */
                   56378: define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
                   56379: /**
                   56380:  * Error code when an empty package name validate regex is passed in
                   56381:  */
                   56382: define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
                   56383: /**
                   56384:  * Error code when a <function> tag has no version
                   56385:  */
                   56386: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
                   56387: /**
                   56388:  * Error code when a <function> tag has no name
                   56389:  */
                   56390: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
                   56391: /**
                   56392:  * Error code when a <validatepackage> tag has no name
                   56393:  */
                   56394: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
                   56395: /**
                   56396:  * Error code when a <validatepackage> tag has no version attribute
                   56397:  */
                   56398: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
                   56399: /**
                   56400:  * Error code when a mirror does not exist but is called for in one of the set*
                   56401:  * methods.
                   56402:  */
                   56403: define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
                   56404: /**
                   56405:  * Error code when a server port is not numeric
                   56406:  */
                   56407: define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
                   56408: /**
                   56409:  * Error code when <static> contains no version attribute
                   56410:  */
                   56411: define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
                   56412: /**
                   56413:  * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
                   56414:  */
                   56415: define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
                   56416: /**
                   56417:  * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
                   56418:  */
                   56419: define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
                   56420: /**
                   56421:  * Error code when ssl attribute is present and is not "yes"
                   56422:  */
                   56423: define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
                   56424: /**#@-*/
                   56425: 
                   56426: /**
                   56427:  * Mirror types allowed.  Currently only internet servers are recognized.
                   56428:  */
                   56429: $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
                   56430: 
                   56431: 
                   56432: /**
                   56433:  * The Channel handling class
                   56434:  *
                   56435:  * @category   pear
                   56436:  * @package    PEAR
                   56437:  * @author     Greg Beaver <cellog@php.net>
                   56438:  * @copyright  1997-2009 The Authors
                   56439:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   56440:  * @version    Release: 1.10.0beta1
                   56441:  * @link       http://pear.php.net/package/PEAR
                   56442:  * @since      Class available since Release 1.4.0a1
                   56443:  */
                   56444: class PEAR_ChannelFile
                   56445: {
                   56446:     /**
                   56447:      * @access private
                   56448:      * @var PEAR_ErrorStack
                   56449:      * @access private
                   56450:      */
                   56451:     var $_stack;
                   56452: 
                   56453:     /**
                   56454:      * Supported channel.xml versions, for parsing
                   56455:      * @var array
                   56456:      * @access private
                   56457:      */
                   56458:     var $_supportedVersions = array('1.0');
                   56459: 
                   56460:     /**
                   56461:      * Parsed channel information
                   56462:      * @var array
                   56463:      * @access private
                   56464:      */
                   56465:     var $_channelInfo;
                   56466: 
                   56467:     /**
                   56468:      * index into the subchannels array, used for parsing xml
                   56469:      * @var int
                   56470:      * @access private
                   56471:      */
                   56472:     var $_subchannelIndex;
                   56473: 
                   56474:     /**
                   56475:      * index into the mirrors array, used for parsing xml
                   56476:      * @var int
                   56477:      * @access private
                   56478:      */
                   56479:     var $_mirrorIndex;
                   56480: 
                   56481:     /**
                   56482:      * Flag used to determine the validity of parsed content
                   56483:      * @var boolean
                   56484:      * @access private
                   56485:      */
                   56486:     var $_isValid = false;
                   56487: 
                   56488:     function PEAR_ChannelFile()
                   56489:     {
                   56490:         $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
                   56491:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   56492:         $this->_isValid = false;
                   56493:     }
                   56494: 
                   56495:     /**
                   56496:      * @return array
                   56497:      * @access protected
                   56498:      */
                   56499:     function _getErrorMessage()
                   56500:     {
                   56501:         return
                   56502:             array(
                   56503:                 PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
                   56504:                     'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
                   56505:                 PEAR_CHANNELFILE_ERROR_NO_VERSION =>
                   56506:                     'No version number found in <channel> tag',
                   56507:                 PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
                   56508:                     '%error%',
                   56509:                 PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
                   56510:                     'Unable to create XML parser',
                   56511:                 PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
                   56512:                     '%error%',
                   56513:                 PEAR_CHANNELFILE_ERROR_NO_NAME =>
                   56514:                     'Missing channel name',
                   56515:                 PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
                   56516:                     'Invalid channel %tag% "%name%"',
                   56517:                 PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
                   56518:                     'Missing channel summary',
                   56519:                 PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
                   56520:                     'Channel summary should be on one line, but is multi-line',
                   56521:                 PEAR_CHANNELFILE_ERROR_NO_HOST =>
                   56522:                     'Missing channel server for %type% server',
                   56523:                 PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
                   56524:                     'Server name "%server%" is invalid for %type% server',
                   56525:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
                   56526:                     'Invalid mirror name "%name%", mirror type %type%',
                   56527:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
                   56528:                     'Invalid mirror type "%type%"',
                   56529:                 PEAR_CHANNELFILE_ERROR_INVALID =>
                   56530:                     'Cannot generate xml, contents are invalid',
                   56531:                 PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
                   56532:                     'packagenameregex cannot be empty',
                   56533:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
                   56534:                     '%parent% %protocol% function has no version',
                   56535:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
                   56536:                     '%parent% %protocol% function has no name',
                   56537:                 PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
                   56538:                     '%parent% rest baseurl has no type',
                   56539:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
                   56540:                     'Validation package has no name in <validatepackage> tag',
                   56541:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
                   56542:                     'Validation package "%package%" has no version',
                   56543:                 PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
                   56544:                     'Mirror "%mirror%" does not exist',
                   56545:                 PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
                   56546:                     'Port "%port%" must be numeric',
                   56547:                 PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
                   56548:                     '<static> tag must contain version attribute',
                   56549:                 PEAR_CHANNELFILE_URI_CANT_MIRROR =>
                   56550:                     'The __uri pseudo-channel cannot have mirrors',
                   56551:                 PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
                   56552:                     '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
                   56553:             );
                   56554:     }
                   56555: 
                   56556:     /**
                   56557:      * @param string contents of package.xml file
                   56558:      * @return bool success of parsing
                   56559:      */
                   56560:     function fromXmlString($data)
                   56561:     {
                   56562:         if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
                   56563:             if (!in_array($channelversion[1], $this->_supportedVersions)) {
                   56564:                 $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
                   56565:                     array('version' => $channelversion[1]));
                   56566:                 return false;
                   56567:             }
                   56568:             $parser = new PEAR_XMLParser;
                   56569:             $result = $parser->parse($data);
                   56570:             if ($result !== true) {
                   56571:                 if ($result->getCode() == 1) {
                   56572:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
                   56573:                         array('error' => $result->getMessage()));
                   56574:                 } else {
                   56575:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
                   56576:                 }
                   56577:                 return false;
                   56578:             }
                   56579:             $this->_channelInfo = $parser->getData();
                   56580:             return true;
                   56581:         } else {
                   56582:             $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
                   56583:             return false;
                   56584:         }
                   56585:     }
                   56586: 
                   56587:     /**
                   56588:      * @return array
                   56589:      */
                   56590:     function toArray()
                   56591:     {
                   56592:         if (!$this->_isValid && !$this->validate()) {
                   56593:             return false;
                   56594:         }
                   56595:         return $this->_channelInfo;
                   56596:     }
                   56597: 
                   56598:     /**
                   56599:      * @param array
                   56600:      * @static
                   56601:      * @return PEAR_ChannelFile|false false if invalid
                   56602:      */
                   56603:     function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
                   56604:     {
                   56605:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   56606:         $a->_fromArray($data);
                   56607:         if (!$a->validate()) {
                   56608:             $a = false;
                   56609:             return $a;
                   56610:         }
                   56611:         return $a;
                   56612:     }
                   56613: 
                   56614:     /**
                   56615:      * Unlike {@link fromArray()} this does not do any validation
                   56616:      * @param array
                   56617:      * @static
                   56618:      * @return PEAR_ChannelFile
                   56619:      */
                   56620:     function &fromArrayWithErrors($data, $compatibility = false,
                   56621:                                   $stackClass = 'PEAR_ErrorStack')
                   56622:     {
                   56623:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   56624:         $a->_fromArray($data);
                   56625:         return $a;
                   56626:     }
                   56627: 
                   56628:     /**
                   56629:      * @param array
                   56630:      * @access private
                   56631:      */
                   56632:     function _fromArray($data)
                   56633:     {
                   56634:         $this->_channelInfo = $data;
                   56635:     }
                   56636: 
                   56637:     /**
                   56638:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   56639:      * @param boolean determines whether to purge the error stack after retrieving
                   56640:      * @return array
                   56641:      */
                   56642:     function getErrors($purge = false)
                   56643:     {
                   56644:         return $this->_stack->getErrors($purge);
                   56645:     }
                   56646: 
                   56647:     /**
                   56648:      * Unindent given string (?)
                   56649:      *
                   56650:      * @param string $str The string that has to be unindented.
                   56651:      * @return string
                   56652:      * @access private
                   56653:      */
                   56654:     function _unIndent($str)
                   56655:     {
                   56656:         // remove leading newlines
                   56657:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   56658:         // find whitespace at the beginning of the first line
                   56659:         $indent_len = strspn($str, " \t");
                   56660:         $indent = substr($str, 0, $indent_len);
                   56661:         $data = '';
                   56662:         // remove the same amount of whitespace from following lines
                   56663:         foreach (explode("\n", $str) as $line) {
                   56664:             if (substr($line, 0, $indent_len) == $indent) {
                   56665:                 $data .= substr($line, $indent_len) . "\n";
                   56666:             }
                   56667:         }
                   56668:         return $data;
                   56669:     }
                   56670: 
                   56671:     /**
                   56672:      * Parse a channel.xml file.  Expects the name of
                   56673:      * a channel xml file as input.
                   56674:      *
                   56675:      * @param string  $descfile  name of channel xml file
                   56676:      * @return bool success of parsing
                   56677:      */
                   56678:     function fromXmlFile($descfile)
                   56679:     {
                   56680:         if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
                   56681:              (!$fp = fopen($descfile, 'r'))) {
                   56682:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   56683:             return PEAR::raiseError("Unable to open $descfile");
                   56684:         }
                   56685: 
                   56686:         // read the whole thing so we only get one cdata callback
                   56687:         // for each block of cdata
                   56688:         fclose($fp);
                   56689:         $data = file_get_contents($descfile);
                   56690:         return $this->fromXmlString($data);
                   56691:     }
                   56692: 
                   56693:     /**
                   56694:      * Parse channel information from different sources
                   56695:      *
                   56696:      * This method is able to extract information about a channel
                   56697:      * from an .xml file or a string
                   56698:      *
                   56699:      * @access public
                   56700:      * @param  string Filename of the source or the source itself
                   56701:      * @return bool
                   56702:      */
                   56703:     function fromAny($info)
                   56704:     {
                   56705:         if (is_string($info) && file_exists($info) && strlen($info) < 255) {
                   56706:             $tmp = substr($info, -4);
                   56707:             if ($tmp == '.xml') {
                   56708:                 $info = $this->fromXmlFile($info);
                   56709:             } else {
                   56710:                 $fp = fopen($info, "r");
                   56711:                 $test = fread($fp, 5);
                   56712:                 fclose($fp);
                   56713:                 if ($test == "<?xml") {
                   56714:                     $info = $this->fromXmlFile($info);
                   56715:                 }
                   56716:             }
                   56717:             if (PEAR::isError($info)) {
                   56718:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   56719:                 return PEAR::raiseError($info);
                   56720:             }
                   56721:         }
                   56722:         if (is_string($info)) {
                   56723:             $info = $this->fromXmlString($info);
                   56724:         }
                   56725:         return $info;
                   56726:     }
                   56727: 
                   56728:     /**
                   56729:      * Return an XML document based on previous parsing and modifications
                   56730:      *
                   56731:      * @return string XML data
                   56732:      *
                   56733:      * @access public
                   56734:      */
                   56735:     function toXml()
                   56736:     {
                   56737:         if (!$this->_isValid && !$this->validate()) {
                   56738:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
                   56739:             return false;
                   56740:         }
                   56741:         if (!isset($this->_channelInfo['attribs']['version'])) {
                   56742:             $this->_channelInfo['attribs']['version'] = '1.0';
                   56743:         }
                   56744:         $channelInfo = $this->_channelInfo;
                   56745:         $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
                   56746:         $ret .= "<channel version=\"" .
                   56747:             $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
                   56748:   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
                   56749:   xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
                   56750:             . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
                   56751:             $channelInfo['attribs']['version'] . ".xsd\">
                   56752:  <name>$channelInfo[name]</name>
                   56753:  <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
                   56754: ";
                   56755:         if (isset($channelInfo['suggestedalias'])) {
                   56756:             $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
                   56757:         }
                   56758:         if (isset($channelInfo['validatepackage'])) {
                   56759:             $ret .= ' <validatepackage version="' .
                   56760:                 $channelInfo['validatepackage']['attribs']['version']. '">' .
                   56761:                 htmlspecialchars($channelInfo['validatepackage']['_content']) .
                   56762:                 "</validatepackage>\n";
                   56763:         }
                   56764:         $ret .= " <servers>\n";
                   56765:         $ret .= '  <primary';
                   56766:         if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
                   56767:             $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
                   56768:         }
                   56769:         if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
                   56770:             $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
                   56771:         }
                   56772:         $ret .= ">\n";
                   56773:         if (isset($channelInfo['servers']['primary']['rest'])) {
                   56774:             $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
                   56775:         }
                   56776:         $ret .= "  </primary>\n";
                   56777:         if (isset($channelInfo['servers']['mirror'])) {
                   56778:             $ret .= $this->_makeMirrorsXml($channelInfo);
                   56779:         }
                   56780:         $ret .= " </servers>\n";
                   56781:         $ret .= "</channel>";
                   56782:         return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
                   56783:     }
                   56784: 
                   56785:     /**
                   56786:      * Generate the <rest> tag
                   56787:      * @access private
                   56788:      */
                   56789:     function _makeRestXml($info, $indent)
                   56790:     {
                   56791:         $ret = $indent . "<rest>\n";
                   56792:         if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
                   56793:             $info['baseurl'] = array($info['baseurl']);
                   56794:         }
                   56795: 
                   56796:         if (isset($info['baseurl'])) {
                   56797:             foreach ($info['baseurl'] as $url) {
                   56798:                 $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
                   56799:                 $ret .= ">" . $url['_content'] . "</baseurl>\n";
                   56800:             }
                   56801:         }
                   56802:         $ret .= $indent . "</rest>\n";
                   56803:         return $ret;
                   56804:     }
                   56805: 
                   56806:     /**
                   56807:      * Generate the <mirrors> tag
                   56808:      * @access private
                   56809:      */
                   56810:     function _makeMirrorsXml($channelInfo)
                   56811:     {
                   56812:         $ret = "";
                   56813:         if (!isset($channelInfo['servers']['mirror'][0])) {
                   56814:             $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
                   56815:         }
                   56816:         foreach ($channelInfo['servers']['mirror'] as $mirror) {
                   56817:             $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
                   56818:             if (isset($mirror['attribs']['port'])) {
                   56819:                 $ret .= ' port="' . $mirror['attribs']['port'] . '"';
                   56820:             }
                   56821:             if (isset($mirror['attribs']['ssl'])) {
                   56822:                 $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
                   56823:             }
                   56824:             $ret .= ">\n";
                   56825:             if (isset($mirror['rest'])) {
                   56826:                 if (isset($mirror['rest'])) {
                   56827:                     $ret .= $this->_makeRestXml($mirror['rest'], '   ');
                   56828:                 }
                   56829:                 $ret .= "  </mirror>\n";
                   56830:             } else {
                   56831:                 $ret .= "/>\n";
                   56832:             }
                   56833:         }
                   56834:         return $ret;
                   56835:     }
                   56836: 
                   56837:     /**
                   56838:      * Generate the <functions> tag
                   56839:      * @access private
                   56840:      */
                   56841:     function _makeFunctionsXml($functions, $indent, $rest = false)
                   56842:     {
                   56843:         $ret = '';
                   56844:         if (!isset($functions[0])) {
                   56845:             $functions = array($functions);
                   56846:         }
                   56847:         foreach ($functions as $function) {
                   56848:             $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
                   56849:             if ($rest) {
                   56850:                 $ret .= ' uri="' . $function['attribs']['uri'] . '"';
                   56851:             }
                   56852:             $ret .= ">" . $function['_content'] . "</function>\n";
                   56853:         }
                   56854:         return $ret;
                   56855:     }
                   56856: 
                   56857:     /**
                   56858:      * Validation error.  Also marks the object contents as invalid
                   56859:      * @param error code
                   56860:      * @param array error information
                   56861:      * @access private
                   56862:      */
                   56863:     function _validateError($code, $params = array())
                   56864:     {
                   56865:         $this->_stack->push($code, 'error', $params);
                   56866:         $this->_isValid = false;
                   56867:     }
                   56868: 
                   56869:     /**
                   56870:      * Validation warning.  Does not mark the object contents invalid.
                   56871:      * @param error code
                   56872:      * @param array error information
                   56873:      * @access private
                   56874:      */
                   56875:     function _validateWarning($code, $params = array())
                   56876:     {
                   56877:         $this->_stack->push($code, 'warning', $params);
                   56878:     }
                   56879: 
                   56880:     /**
                   56881:      * Validate parsed file.
                   56882:      *
                   56883:      * @access public
                   56884:      * @return boolean
                   56885:      */
                   56886:     function validate()
                   56887:     {
                   56888:         $this->_isValid = true;
                   56889:         $info = $this->_channelInfo;
                   56890:         if (empty($info['name'])) {
                   56891:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
                   56892:         } elseif (!$this->validChannelServer($info['name'])) {
                   56893:             if ($info['name'] != '__uri') {
                   56894:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
                   56895:                     'name' => $info['name']));
                   56896:             }
                   56897:         }
                   56898:         if (empty($info['summary'])) {
                   56899:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   56900:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   56901:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   56902:                 array('summary' => $info['summary']));
                   56903:         }
                   56904:         if (isset($info['suggestedalias'])) {
                   56905:             if (!$this->validChannelServer($info['suggestedalias'])) {
                   56906:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   56907:                     array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
                   56908:             }
                   56909:         }
                   56910:         if (isset($info['localalias'])) {
                   56911:             if (!$this->validChannelServer($info['localalias'])) {
                   56912:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   56913:                     array('tag' => 'localalias', 'name' =>$info['localalias']));
                   56914:             }
                   56915:         }
                   56916:         if (isset($info['validatepackage'])) {
                   56917:             if (!isset($info['validatepackage']['_content'])) {
                   56918:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
                   56919:             }
                   56920:             if (!isset($info['validatepackage']['attribs']['version'])) {
                   56921:                 $content = isset($info['validatepackage']['_content']) ?
                   56922:                     $info['validatepackage']['_content'] :
                   56923:                     null;
                   56924:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
                   56925:                     array('package' => $content));
                   56926:             }
                   56927:         }
                   56928: 
                   56929:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
                   56930:               !is_numeric($info['servers']['primary']['attribs']['port'])) {
                   56931:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
                   56932:                 array('port' => $info['servers']['primary']['attribs']['port']));
                   56933:         }
                   56934: 
                   56935:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
                   56936:               $info['servers']['primary']['attribs']['ssl'] != 'yes') {
                   56937:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   56938:                 array('ssl' => $info['servers']['primary']['attribs']['ssl'],
                   56939:                     'server' => $info['name']));
                   56940:         }
                   56941: 
                   56942:         if (isset($info['servers']['primary']['rest']) &&
                   56943:               isset($info['servers']['primary']['rest']['baseurl'])) {
                   56944:             $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
                   56945:         }
                   56946:         if (isset($info['servers']['mirror'])) {
                   56947:             if ($this->_channelInfo['name'] == '__uri') {
                   56948:                 $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
                   56949:             }
                   56950:             if (!isset($info['servers']['mirror'][0])) {
                   56951:                 $info['servers']['mirror'] = array($info['servers']['mirror']);
                   56952:             }
                   56953:             foreach ($info['servers']['mirror'] as $mirror) {
                   56954:                 if (!isset($mirror['attribs']['host'])) {
                   56955:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
                   56956:                       array('type' => 'mirror'));
                   56957:                 } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
                   56958:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
                   56959:                         array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
                   56960:                 }
                   56961:                 if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
                   56962:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   56963:                         array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
                   56964:                 }
                   56965:                 if (isset($mirror['rest'])) {
                   56966:                     $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
                   56967:                         $mirror['attribs']['host']);
                   56968:                 }
                   56969:             }
                   56970:         }
                   56971:         return $this->_isValid;
                   56972:     }
                   56973: 
                   56974:     /**
                   56975:      * @param string  rest - protocol name this function applies to
                   56976:      * @param array the functions
                   56977:      * @param string the name of the parent element (mirror name, for instance)
                   56978:      */
                   56979:     function _validateFunctions($protocol, $functions, $parent = '')
                   56980:     {
                   56981:         if (!isset($functions[0])) {
                   56982:             $functions = array($functions);
                   56983:         }
                   56984: 
                   56985:         foreach ($functions as $function) {
                   56986:             if (!isset($function['_content']) || empty($function['_content'])) {
                   56987:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
                   56988:                     array('parent' => $parent, 'protocol' => $protocol));
                   56989:             }
                   56990: 
                   56991:             if ($protocol == 'rest') {
                   56992:                 if (!isset($function['attribs']['type']) ||
                   56993:                       empty($function['attribs']['type'])) {
                   56994:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
                   56995:                         array('parent' => $parent, 'protocol' => $protocol));
                   56996:                 }
                   56997:             } else {
                   56998:                 if (!isset($function['attribs']['version']) ||
                   56999:                       empty($function['attribs']['version'])) {
                   57000:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
                   57001:                         array('parent' => $parent, 'protocol' => $protocol));
                   57002:                 }
                   57003:             }
                   57004:         }
                   57005:     }
                   57006: 
                   57007:     /**
                   57008:      * Test whether a string contains a valid channel server.
                   57009:      * @param string $ver the package version to test
                   57010:      * @return bool
                   57011:      */
                   57012:     function validChannelServer($server)
                   57013:     {
                   57014:         if ($server == '__uri') {
                   57015:             return true;
                   57016:         }
                   57017:         return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
                   57018:     }
                   57019: 
                   57020:     /**
                   57021:      * @return string|false
                   57022:      */
                   57023:     function getName()
                   57024:     {
                   57025:         if (isset($this->_channelInfo['name'])) {
                   57026:             return $this->_channelInfo['name'];
                   57027:         }
                   57028: 
                   57029:         return false;
                   57030:     }
                   57031: 
                   57032:     /**
                   57033:      * @return string|false
                   57034:      */
                   57035:     function getServer()
                   57036:     {
                   57037:         if (isset($this->_channelInfo['name'])) {
                   57038:             return $this->_channelInfo['name'];
                   57039:         }
                   57040: 
                   57041:         return false;
                   57042:     }
                   57043: 
                   57044:     /**
                   57045:      * @return int|80 port number to connect to
                   57046:      */
                   57047:     function getPort($mirror = false)
                   57048:     {
                   57049:         if ($mirror) {
                   57050:             if ($mir = $this->getMirror($mirror)) {
                   57051:                 if (isset($mir['attribs']['port'])) {
                   57052:                     return $mir['attribs']['port'];
                   57053:                 }
                   57054: 
                   57055:                 if ($this->getSSL($mirror)) {
                   57056:                     return 443;
                   57057:                 }
                   57058: 
                   57059:                 return 80;
                   57060:             }
                   57061: 
                   57062:             return false;
                   57063:         }
                   57064: 
                   57065:         if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
                   57066:             return $this->_channelInfo['servers']['primary']['attribs']['port'];
                   57067:         }
                   57068: 
                   57069:         if ($this->getSSL()) {
                   57070:             return 443;
                   57071:         }
                   57072: 
                   57073:         return 80;
                   57074:     }
                   57075: 
                   57076:     /**
                   57077:      * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
                   57078:      */
                   57079:     function getSSL($mirror = false)
                   57080:     {
                   57081:         if ($mirror) {
                   57082:             if ($mir = $this->getMirror($mirror)) {
                   57083:                 if (isset($mir['attribs']['ssl'])) {
                   57084:                     return true;
                   57085:                 }
                   57086: 
                   57087:                 return false;
                   57088:             }
                   57089: 
                   57090:             return false;
                   57091:         }
                   57092: 
                   57093:         if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   57094:             return true;
                   57095:         }
                   57096: 
                   57097:         return false;
                   57098:     }
                   57099: 
                   57100:     /**
                   57101:      * @return string|false
                   57102:      */
                   57103:     function getSummary()
                   57104:     {
                   57105:         if (isset($this->_channelInfo['summary'])) {
                   57106:             return $this->_channelInfo['summary'];
                   57107:         }
                   57108: 
                   57109:         return false;
                   57110:     }
                   57111: 
                   57112:     /**
                   57113:      * @param string protocol type
                   57114:      * @param string Mirror name
                   57115:      * @return array|false
                   57116:      */
                   57117:     function getFunctions($protocol, $mirror = false)
                   57118:     {
                   57119:         if ($this->getName() == '__uri') {
                   57120:             return false;
                   57121:         }
                   57122: 
                   57123:         $function = $protocol == 'rest' ? 'baseurl' : 'function';
                   57124:         if ($mirror) {
                   57125:             if ($mir = $this->getMirror($mirror)) {
                   57126:                 if (isset($mir[$protocol][$function])) {
                   57127:                     return $mir[$protocol][$function];
                   57128:                 }
                   57129:             }
                   57130: 
                   57131:             return false;
                   57132:         }
                   57133: 
                   57134:         if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
                   57135:             return $this->_channelInfo['servers']['primary'][$protocol][$function];
                   57136:         }
                   57137: 
                   57138:         return false;
                   57139:     }
                   57140: 
                   57141:     /**
                   57142:      * @param string Protocol type
                   57143:      * @param string Function name (null to return the
                   57144:      *               first protocol of the type requested)
                   57145:      * @param string Mirror name, if any
                   57146:      * @return array
                   57147:      */
                   57148:      function getFunction($type, $name = null, $mirror = false)
                   57149:      {
                   57150:         $protocols = $this->getFunctions($type, $mirror);
                   57151:         if (!$protocols) {
                   57152:             return false;
                   57153:         }
                   57154: 
                   57155:         foreach ($protocols as $protocol) {
                   57156:             if ($name === null) {
                   57157:                 return $protocol;
                   57158:             }
                   57159: 
                   57160:             if ($protocol['_content'] != $name) {
                   57161:                 continue;
                   57162:             }
                   57163: 
                   57164:             return $protocol;
                   57165:         }
                   57166: 
                   57167:         return false;
                   57168:      }
                   57169: 
                   57170:     /**
                   57171:      * @param string protocol type
                   57172:      * @param string protocol name
                   57173:      * @param string version
                   57174:      * @param string mirror name
                   57175:      * @return boolean
                   57176:      */
                   57177:     function supports($type, $name = null, $mirror = false, $version = '1.0')
                   57178:     {
                   57179:         $protocols = $this->getFunctions($type, $mirror);
                   57180:         if (!$protocols) {
                   57181:             return false;
                   57182:         }
                   57183: 
                   57184:         foreach ($protocols as $protocol) {
                   57185:             if ($protocol['attribs']['version'] != $version) {
                   57186:                 continue;
                   57187:             }
                   57188: 
                   57189:             if ($name === null) {
                   57190:                 return true;
                   57191:             }
                   57192: 
                   57193:             if ($protocol['_content'] != $name) {
                   57194:                 continue;
                   57195:             }
                   57196: 
                   57197:             return true;
                   57198:         }
                   57199: 
                   57200:         return false;
                   57201:     }
                   57202: 
                   57203:     /**
                   57204:      * Determines whether a channel supports Representational State Transfer (REST) protocols
                   57205:      * for retrieving channel information
                   57206:      * @param string
                   57207:      * @return bool
                   57208:      */
                   57209:     function supportsREST($mirror = false)
                   57210:     {
                   57211:         if ($mirror == $this->_channelInfo['name']) {
                   57212:             $mirror = false;
                   57213:         }
                   57214: 
                   57215:         if ($mirror) {
                   57216:             if ($mir = $this->getMirror($mirror)) {
                   57217:                 return isset($mir['rest']);
                   57218:             }
                   57219: 
                   57220:             return false;
                   57221:         }
                   57222: 
                   57223:         return isset($this->_channelInfo['servers']['primary']['rest']);
                   57224:     }
                   57225: 
                   57226:     /**
                   57227:      * Get the URL to access a base resource.
                   57228:      *
                   57229:      * Hyperlinks in the returned xml will be used to retrieve the proper information
                   57230:      * needed.  This allows extreme extensibility and flexibility in implementation
                   57231:      * @param string Resource Type to retrieve
                   57232:      */
                   57233:     function getBaseURL($resourceType, $mirror = false)
                   57234:     {
                   57235:         if ($mirror == $this->_channelInfo['name']) {
                   57236:             $mirror = false;
                   57237:         }
                   57238: 
                   57239:         if ($mirror) {
                   57240:             $mir = $this->getMirror($mirror);
                   57241:             if (!$mir) {
                   57242:                 return false;
                   57243:             }
                   57244: 
                   57245:             $rest = $mir['rest'];
                   57246:         } else {
                   57247:             $rest = $this->_channelInfo['servers']['primary']['rest'];
                   57248:         }
                   57249: 
                   57250:         if (!isset($rest['baseurl'][0])) {
                   57251:             $rest['baseurl'] = array($rest['baseurl']);
                   57252:         }
                   57253: 
                   57254:         foreach ($rest['baseurl'] as $baseurl) {
                   57255:             if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
                   57256:                 return $baseurl['_content'];
                   57257:             }
                   57258:         }
                   57259: 
                   57260:         return false;
                   57261:     }
                   57262: 
                   57263:     /**
                   57264:      * Since REST does not implement RPC, provide this as a logical wrapper around
                   57265:      * resetFunctions for REST
                   57266:      * @param string|false mirror name, if any
                   57267:      */
                   57268:     function resetREST($mirror = false)
                   57269:     {
                   57270:         return $this->resetFunctions('rest', $mirror);
                   57271:     }
                   57272: 
                   57273:     /**
                   57274:      * Empty all protocol definitions
                   57275:      * @param string protocol type
                   57276:      * @param string|false mirror name, if any
                   57277:      */
                   57278:     function resetFunctions($type, $mirror = false)
                   57279:     {
                   57280:         if ($mirror) {
                   57281:             if (isset($this->_channelInfo['servers']['mirror'])) {
                   57282:                 $mirrors = $this->_channelInfo['servers']['mirror'];
                   57283:                 if (!isset($mirrors[0])) {
                   57284:                     $mirrors = array($mirrors);
                   57285:                 }
                   57286: 
                   57287:                 foreach ($mirrors as $i => $mir) {
                   57288:                     if ($mir['attribs']['host'] == $mirror) {
                   57289:                         if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
                   57290:                             unset($this->_channelInfo['servers']['mirror'][$i][$type]);
                   57291:                         }
                   57292: 
                   57293:                         return true;
                   57294:                     }
                   57295:                 }
                   57296: 
                   57297:                 return false;
                   57298:             }
                   57299: 
                   57300:             return false;
                   57301:         }
                   57302: 
                   57303:         if (isset($this->_channelInfo['servers']['primary'][$type])) {
                   57304:             unset($this->_channelInfo['servers']['primary'][$type]);
                   57305:         }
                   57306: 
                   57307:         return true;
                   57308:     }
                   57309: 
                   57310:     /**
                   57311:      * Set a channel's protocols to the protocols supported by pearweb
                   57312:      */
                   57313:     function setDefaultPEARProtocols($version = '1.0', $mirror = false)
                   57314:     {
                   57315:         switch ($version) {
                   57316:             case '1.0' :
                   57317:                 $this->resetREST($mirror);
                   57318: 
                   57319:                 if (!isset($this->_channelInfo['servers'])) {
                   57320:                     $this->_channelInfo['servers'] = array('primary' =>
                   57321:                         array('rest' => array()));
                   57322:                 } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   57323:                     $this->_channelInfo['servers']['primary'] = array('rest' => array());
                   57324:                 }
                   57325: 
                   57326:                 return true;
                   57327:             break;
                   57328:             default :
                   57329:                 return false;
                   57330:             break;
                   57331:         }
                   57332:     }
                   57333: 
                   57334:     /**
                   57335:      * @return array
                   57336:      */
                   57337:     function getMirrors()
                   57338:     {
                   57339:         if (isset($this->_channelInfo['servers']['mirror'])) {
                   57340:             $mirrors = $this->_channelInfo['servers']['mirror'];
                   57341:             if (!isset($mirrors[0])) {
                   57342:                 $mirrors = array($mirrors);
                   57343:             }
                   57344: 
                   57345:             return $mirrors;
                   57346:         }
                   57347: 
                   57348:         return array();
                   57349:     }
                   57350: 
                   57351:     /**
                   57352:      * Get the unserialized XML representing a mirror
                   57353:      * @return array|false
                   57354:      */
                   57355:     function getMirror($server)
                   57356:     {
                   57357:         foreach ($this->getMirrors() as $mirror) {
                   57358:             if ($mirror['attribs']['host'] == $server) {
                   57359:                 return $mirror;
                   57360:             }
                   57361:         }
                   57362: 
                   57363:         return false;
                   57364:     }
                   57365: 
                   57366:     /**
                   57367:      * @param string
                   57368:      * @return string|false
                   57369:      * @error PEAR_CHANNELFILE_ERROR_NO_NAME
                   57370:      * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
                   57371:      */
                   57372:     function setName($name)
                   57373:     {
                   57374:         return $this->setServer($name);
                   57375:     }
                   57376: 
                   57377:     /**
                   57378:      * Set the socket number (port) that is used to connect to this channel
                   57379:      * @param integer
                   57380:      * @param string|false name of the mirror server, or false for the primary
                   57381:      */
                   57382:     function setPort($port, $mirror = false)
                   57383:     {
                   57384:         if ($mirror) {
                   57385:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   57386:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57387:                     array('mirror' => $mirror));
                   57388:                 return false;
                   57389:             }
                   57390: 
                   57391:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   57392:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   57393:                     if ($mirror == $mir['attribs']['host']) {
                   57394:                         $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
                   57395:                         return true;
                   57396:                     }
                   57397:                 }
                   57398: 
                   57399:                 return false;
                   57400:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   57401:                 $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
                   57402:                 $this->_isValid = false;
                   57403:                 return true;
                   57404:             }
                   57405:         }
                   57406: 
                   57407:         $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
                   57408:         $this->_isValid = false;
                   57409:         return true;
                   57410:     }
                   57411: 
                   57412:     /**
                   57413:      * Set the socket number (port) that is used to connect to this channel
                   57414:      * @param bool Determines whether to turn on SSL support or turn it off
                   57415:      * @param string|false name of the mirror server, or false for the primary
                   57416:      */
                   57417:     function setSSL($ssl = true, $mirror = false)
                   57418:     {
                   57419:         if ($mirror) {
                   57420:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   57421:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57422:                     array('mirror' => $mirror));
                   57423:                 return false;
                   57424:             }
                   57425: 
                   57426:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   57427:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   57428:                     if ($mirror == $mir['attribs']['host']) {
                   57429:                         if (!$ssl) {
                   57430:                             if (isset($this->_channelInfo['servers']['mirror'][$i]
                   57431:                                   ['attribs']['ssl'])) {
                   57432:                                 unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
                   57433:                             }
                   57434:                         } else {
                   57435:                             $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
                   57436:                         }
                   57437: 
                   57438:                         return true;
                   57439:                     }
                   57440:                 }
                   57441: 
                   57442:                 return false;
                   57443:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   57444:                 if (!$ssl) {
                   57445:                     if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
                   57446:                         unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
                   57447:                     }
                   57448:                 } else {
                   57449:                     $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
                   57450:                 }
                   57451: 
                   57452:                 $this->_isValid = false;
                   57453:                 return true;
                   57454:             }
                   57455:         }
                   57456: 
                   57457:         if ($ssl) {
                   57458:             $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
                   57459:         } else {
                   57460:             if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   57461:                 unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
                   57462:             }
                   57463:         }
                   57464: 
                   57465:         $this->_isValid = false;
                   57466:         return true;
                   57467:     }
                   57468: 
                   57469:     /**
                   57470:      * @param string
                   57471:      * @return string|false
                   57472:      * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
                   57473:      * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
                   57474:      */
                   57475:     function setServer($server, $mirror = false)
                   57476:     {
                   57477:         if (empty($server)) {
                   57478:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
                   57479:             return false;
                   57480:         } elseif (!$this->validChannelServer($server)) {
                   57481:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   57482:                 array('tag' => 'name', 'name' => $server));
                   57483:             return false;
                   57484:         }
                   57485: 
                   57486:         if ($mirror) {
                   57487:             $found = false;
                   57488:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   57489:                 if ($mirror == $mir['attribs']['host']) {
                   57490:                     $found = true;
                   57491:                     break;
                   57492:                 }
                   57493:             }
                   57494: 
                   57495:             if (!$found) {
                   57496:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57497:                     array('mirror' => $mirror));
                   57498:                 return false;
                   57499:             }
                   57500: 
                   57501:             $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
                   57502:             return true;
                   57503:         }
                   57504: 
                   57505:         $this->_channelInfo['name'] = $server;
                   57506:         return true;
                   57507:     }
                   57508: 
                   57509:     /**
                   57510:      * @param string
                   57511:      * @return boolean success
                   57512:      * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
                   57513:      * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
                   57514:      */
                   57515:     function setSummary($summary)
                   57516:     {
                   57517:         if (empty($summary)) {
                   57518:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   57519:             return false;
                   57520:         } elseif (strpos(trim($summary), "\n") !== false) {
                   57521:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   57522:                 array('summary' => $summary));
                   57523:         }
                   57524: 
                   57525:         $this->_channelInfo['summary'] = $summary;
                   57526:         return true;
                   57527:     }
                   57528: 
                   57529:     /**
                   57530:      * @param string
                   57531:      * @param boolean determines whether the alias is in channel.xml or local
                   57532:      * @return boolean success
                   57533:      */
                   57534:     function setAlias($alias, $local = false)
                   57535:     {
                   57536:         if (!$this->validChannelServer($alias)) {
                   57537:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   57538:                 array('tag' => 'suggestedalias', 'name' => $alias));
                   57539:             return false;
                   57540:         }
                   57541: 
                   57542:         if ($local) {
                   57543:             $this->_channelInfo['localalias'] = $alias;
                   57544:         } else {
                   57545:             $this->_channelInfo['suggestedalias'] = $alias;
                   57546:         }
                   57547: 
                   57548:         return true;
                   57549:     }
                   57550: 
                   57551:     /**
                   57552:      * @return string
                   57553:      */
                   57554:     function getAlias()
                   57555:     {
                   57556:         if (isset($this->_channelInfo['localalias'])) {
                   57557:             return $this->_channelInfo['localalias'];
                   57558:         }
                   57559:         if (isset($this->_channelInfo['suggestedalias'])) {
                   57560:             return $this->_channelInfo['suggestedalias'];
                   57561:         }
                   57562:         if (isset($this->_channelInfo['name'])) {
                   57563:             return $this->_channelInfo['name'];
                   57564:         }
                   57565:         return '';
                   57566:     }
                   57567: 
                   57568:     /**
                   57569:      * Set the package validation object if it differs from PEAR's default
                   57570:      * The class must be includeable via changing _ in the classname to path separator,
                   57571:      * but no checking of this is made.
                   57572:      * @param string|false pass in false to reset to the default packagename regex
                   57573:      * @return boolean success
                   57574:      */
                   57575:     function setValidationPackage($validateclass, $version)
                   57576:     {
                   57577:         if (empty($validateclass)) {
                   57578:             unset($this->_channelInfo['validatepackage']);
                   57579:         }
                   57580:         $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
                   57581:         $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
                   57582:     }
                   57583: 
                   57584:     /**
                   57585:      * Add a protocol to the provides section
                   57586:      * @param string protocol type
                   57587:      * @param string protocol version
                   57588:      * @param string protocol name, if any
                   57589:      * @param string mirror name, if this is a mirror's protocol
                   57590:      * @return bool
                   57591:      */
                   57592:     function addFunction($type, $version, $name = '', $mirror = false)
                   57593:     {
                   57594:         if ($mirror) {
                   57595:             return $this->addMirrorFunction($mirror, $type, $version, $name);
                   57596:         }
                   57597: 
                   57598:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   57599:         if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
                   57600:             if (!isset($this->_channelInfo['servers'])) {
                   57601:                 $this->_channelInfo['servers'] = array('primary' =>
                   57602:                     array($type => array()));
                   57603:             } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   57604:                 $this->_channelInfo['servers']['primary'] = array($type => array());
                   57605:             }
                   57606: 
                   57607:             $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
                   57608:             $this->_isValid = false;
                   57609:             return true;
                   57610:         } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
                   57611:             $this->_channelInfo['servers']['primary'][$type]['function'] = array(
                   57612:                 $this->_channelInfo['servers']['primary'][$type]['function']);
                   57613:         }
                   57614: 
                   57615:         $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
                   57616:         return true;
                   57617:     }
                   57618:     /**
                   57619:      * Add a protocol to a mirror's provides section
                   57620:      * @param string mirror name (server)
                   57621:      * @param string protocol type
                   57622:      * @param string protocol version
                   57623:      * @param string protocol name, if any
                   57624:      */
                   57625:     function addMirrorFunction($mirror, $type, $version, $name = '')
                   57626:     {
                   57627:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   57628:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57629:                 array('mirror' => $mirror));
                   57630:             return false;
                   57631:         }
                   57632: 
                   57633:         $setmirror = false;
                   57634:         if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   57635:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   57636:                 if ($mirror == $mir['attribs']['host']) {
                   57637:                     $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   57638:                     break;
                   57639:                 }
                   57640:             }
                   57641:         } else {
                   57642:             if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   57643:                 $setmirror = &$this->_channelInfo['servers']['mirror'];
                   57644:             }
                   57645:         }
                   57646: 
                   57647:         if (!$setmirror) {
                   57648:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57649:                 array('mirror' => $mirror));
                   57650:             return false;
                   57651:         }
                   57652: 
                   57653:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   57654:         if (!isset($setmirror[$type]['function'])) {
                   57655:             $setmirror[$type]['function'] = $set;
                   57656:             $this->_isValid = false;
                   57657:             return true;
                   57658:         } elseif (!isset($setmirror[$type]['function'][0])) {
                   57659:             $setmirror[$type]['function'] = array($setmirror[$type]['function']);
                   57660:         }
                   57661: 
                   57662:         $setmirror[$type]['function'][] = $set;
                   57663:         $this->_isValid = false;
                   57664:         return true;
                   57665:     }
                   57666: 
                   57667:     /**
                   57668:      * @param string Resource Type this url links to
                   57669:      * @param string URL
                   57670:      * @param string|false mirror name, if this is not a primary server REST base URL
                   57671:      */
                   57672:     function setBaseURL($resourceType, $url, $mirror = false)
                   57673:     {
                   57674:         if ($mirror) {
                   57675:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   57676:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   57677:                     array('mirror' => $mirror));
                   57678:                 return false;
                   57679:             }
                   57680: 
                   57681:             $setmirror = false;
                   57682:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   57683:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   57684:                     if ($mirror == $mir['attribs']['host']) {
                   57685:                         $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   57686:                         break;
                   57687:                     }
                   57688:                 }
                   57689:             } else {
                   57690:                 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   57691:                     $setmirror = &$this->_channelInfo['servers']['mirror'];
                   57692:                 }
                   57693:             }
                   57694:         } else {
                   57695:             $setmirror = &$this->_channelInfo['servers']['primary'];
                   57696:         }
                   57697: 
                   57698:         $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
                   57699:         if (!isset($setmirror['rest'])) {
                   57700:             $setmirror['rest'] = array();
                   57701:         }
                   57702: 
                   57703:         if (!isset($setmirror['rest']['baseurl'])) {
                   57704:             $setmirror['rest']['baseurl'] = $set;
                   57705:             $this->_isValid = false;
                   57706:             return true;
                   57707:         } elseif (!isset($setmirror['rest']['baseurl'][0])) {
                   57708:             $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
                   57709:         }
                   57710: 
                   57711:         foreach ($setmirror['rest']['baseurl'] as $i => $url) {
                   57712:             if ($url['attribs']['type'] == $resourceType) {
                   57713:                 $this->_isValid = false;
                   57714:                 $setmirror['rest']['baseurl'][$i] = $set;
                   57715:                 return true;
                   57716:             }
                   57717:         }
                   57718: 
                   57719:         $setmirror['rest']['baseurl'][] = $set;
                   57720:         $this->_isValid = false;
                   57721:         return true;
                   57722:     }
                   57723: 
                   57724:     /**
                   57725:      * @param string mirror server
                   57726:      * @param int mirror http port
                   57727:      * @return boolean
                   57728:      */
                   57729:     function addMirror($server, $port = null)
                   57730:     {
                   57731:         if ($this->_channelInfo['name'] == '__uri') {
                   57732:             return false; // the __uri channel cannot have mirrors by definition
                   57733:         }
                   57734: 
                   57735:         $set = array('attribs' => array('host' => $server));
                   57736:         if (is_numeric($port)) {
                   57737:             $set['attribs']['port'] = $port;
                   57738:         }
                   57739: 
                   57740:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   57741:             $this->_channelInfo['servers']['mirror'] = $set;
                   57742:             return true;
                   57743:         }
                   57744: 
                   57745:         if (!isset($this->_channelInfo['servers']['mirror'][0])) {
                   57746:             $this->_channelInfo['servers']['mirror'] =
                   57747:                 array($this->_channelInfo['servers']['mirror']);
                   57748:         }
                   57749: 
                   57750:         $this->_channelInfo['servers']['mirror'][] = $set;
                   57751:         return true;
                   57752:     }
                   57753: 
                   57754:     /**
                   57755:      * Retrieve the name of the validation package for this channel
                   57756:      * @return string|false
                   57757:      */
                   57758:     function getValidationPackage()
                   57759:     {
                   57760:         if (!$this->_isValid && !$this->validate()) {
                   57761:             return false;
                   57762:         }
                   57763: 
                   57764:         if (!isset($this->_channelInfo['validatepackage'])) {
                   57765:             return array('attribs' => array('version' => 'default'),
                   57766:                 '_content' => 'PEAR_Validate');
                   57767:         }
                   57768: 
                   57769:         return $this->_channelInfo['validatepackage'];
                   57770:     }
                   57771: 
                   57772:     /**
                   57773:      * Retrieve the object that can be used for custom validation
                   57774:      * @param string|false the name of the package to validate.  If the package is
                   57775:      *                     the channel validation package, PEAR_Validate is returned
                   57776:      * @return PEAR_Validate|false false is returned if the validation package
                   57777:      *         cannot be located
                   57778:      */
                   57779:     function &getValidationObject($package = false)
                   57780:     {
                   57781:         if (!class_exists('PEAR_Validate')) {
                   57782:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   57783:         }
                   57784: 
                   57785:         if (!$this->_isValid) {
                   57786:             if (!$this->validate()) {
                   57787:                 $a = false;
                   57788:                 return $a;
                   57789:             }
                   57790:         }
                   57791: 
                   57792:         if (isset($this->_channelInfo['validatepackage'])) {
                   57793:             if ($package == $this->_channelInfo['validatepackage']) {
                   57794:                 // channel validation packages are always validated by PEAR_Validate
                   57795:                 $val = &new PEAR_Validate;
                   57796:                 return $val;
                   57797:             }
                   57798: 
                   57799:             if (!class_exists(str_replace('.', '_',
                   57800:                   $this->_channelInfo['validatepackage']['_content']))) {
                   57801:                 if ($this->isIncludeable(str_replace('_', '/',
                   57802:                       $this->_channelInfo['validatepackage']['_content']) . '.php')) {
                   57803:                     include_once 'phar://install-pear-nozlib.phar/' . str_replace('_', '/',
                   57804:                         $this->_channelInfo['validatepackage']['_content']) . '.php';
                   57805:                     $vclass = str_replace('.', '_',
                   57806:                         $this->_channelInfo['validatepackage']['_content']);
                   57807:                     $val = &new $vclass;
                   57808:                 } else {
                   57809:                     $a = false;
                   57810:                     return $a;
                   57811:                 }
                   57812:             } else {
                   57813:                 $vclass = str_replace('.', '_',
                   57814:                     $this->_channelInfo['validatepackage']['_content']);
                   57815:                 $val = &new $vclass;
                   57816:             }
                   57817:         } else {
                   57818:             $val = &new PEAR_Validate;
                   57819:         }
                   57820: 
                   57821:         return $val;
                   57822:     }
                   57823: 
                   57824:     function isIncludeable($path)
                   57825:     {
                   57826:         $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
                   57827:         foreach ($possibilities as $dir) {
                   57828:             if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
                   57829:                   && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
                   57830:                 return true;
                   57831:             }
                   57832:         }
                   57833: 
                   57834:         return false;
                   57835:     }
                   57836: 
                   57837:     /**
                   57838:      * This function is used by the channel updater and retrieves a value set by
                   57839:      * the registry, or the current time if it has not been set
                   57840:      * @return string
                   57841:      */
                   57842:     function lastModified()
                   57843:     {
                   57844:         if (isset($this->_channelInfo['_lastmodified'])) {
                   57845:             return $this->_channelInfo['_lastmodified'];
                   57846:         }
                   57847: 
                   57848:         return time();
                   57849:     }
                   57850: }<?php
                   57851: /**
                   57852:  * PEAR_ChannelFile_Parser for parsing channel.xml
                   57853:  *
                   57854:  * PHP versions 4 and 5
                   57855:  *
                   57856:  * @category   pear
                   57857:  * @package    PEAR
                   57858:  * @author     Greg Beaver <cellog@php.net>
                   57859:  * @copyright  1997-2009 The Authors
                   57860:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   57861:  * @version    CVS: $Id: Parser.php 276383 2009-02-24 23:39:37Z dufuz $
                   57862:  * @link       http://pear.php.net/package/PEAR
                   57863:  * @since      File available since Release 1.4.0a1
                   57864:  */
                   57865: 
                   57866: /**
                   57867:  * base xml parser class
                   57868:  */
                   57869: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   57870: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   57871: /**
                   57872:  * Parser for channel.xml
                   57873:  * @category   pear
                   57874:  * @package    PEAR
                   57875:  * @author     Greg Beaver <cellog@php.net>
                   57876:  * @copyright  1997-2009 The Authors
                   57877:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   57878:  * @version    Release: 1.10.0beta1
                   57879:  * @link       http://pear.php.net/package/PEAR
                   57880:  * @since      Class available since Release 1.4.0a1
                   57881:  */
                   57882: class PEAR_ChannelFile_Parser extends PEAR_XMLParser
                   57883: {
                   57884:     var $_config;
                   57885:     var $_logger;
                   57886:     var $_registry;
                   57887: 
                   57888:     function setConfig(&$c)
                   57889:     {
                   57890:         $this->_config = &$c;
                   57891:         $this->_registry = &$c->getRegistry();
                   57892:     }
                   57893: 
                   57894:     function setLogger(&$l)
                   57895:     {
                   57896:         $this->_logger = &$l;
                   57897:     }
                   57898: 
                   57899:     function parse($data, $file)
                   57900:     {
                   57901:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   57902:             return $err;
                   57903:         }
                   57904: 
                   57905:         $ret = new PEAR_ChannelFile;
                   57906:         $ret->setConfig($this->_config);
                   57907:         if (isset($this->_logger)) {
                   57908:             $ret->setLogger($this->_logger);
                   57909:         }
                   57910: 
                   57911:         $ret->fromArray($this->_unserializedData);
                   57912:         // make sure the filelist is in the easy to read format needed
                   57913:         $ret->flattenFilelist();
                   57914:         $ret->setPackagefile($file, $archive);
                   57915:         return $ret;
                   57916:     }
                   57917: }<?php
                   57918: /**
                   57919:  * PEAR_Command, command pattern class
                   57920:  *
                   57921:  * PHP versions 4 and 5
                   57922:  *
                   57923:  * @category   pear
                   57924:  * @package    PEAR
                   57925:  * @author     Stig Bakken <ssb@php.net>
                   57926:  * @author     Greg Beaver <cellog@php.net>
                   57927:  * @copyright  1997-2009 The Authors
                   57928:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   57929:  * @version    CVS: $Id: Command.php 286494 2009-07-29 06:57:11Z dufuz $
                   57930:  * @link       http://pear.php.net/package/PEAR
                   57931:  * @since      File available since Release 0.1
                   57932:  */
                   57933: 
                   57934: /**
                   57935:  * Needed for error handling
                   57936:  */
                   57937: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   57938: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
                   57939: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   57940: 
                   57941: /**
                   57942:  * List of commands and what classes they are implemented in.
                   57943:  * @var array command => implementing class
                   57944:  */
                   57945: $GLOBALS['_PEAR_Command_commandlist'] = array();
                   57946: 
                   57947: /**
                   57948:  * List of commands and their descriptions
                   57949:  * @var array command => description
                   57950:  */
                   57951: $GLOBALS['_PEAR_Command_commanddesc'] = array();
                   57952: 
                   57953: /**
                   57954:  * List of shortcuts to common commands.
                   57955:  * @var array shortcut => command
                   57956:  */
                   57957: $GLOBALS['_PEAR_Command_shortcuts'] = array();
                   57958: 
                   57959: /**
                   57960:  * Array of command objects
                   57961:  * @var array class => object
                   57962:  */
                   57963: $GLOBALS['_PEAR_Command_objects'] = array();
                   57964: 
                   57965: /**
                   57966:  * PEAR command class, a simple factory class for administrative
                   57967:  * commands.
                   57968:  *
                   57969:  * How to implement command classes:
                   57970:  *
                   57971:  * - The class must be called PEAR_Command_Nnn, installed in the
                   57972:  *   "PEAR/Common" subdir, with a method called getCommands() that
                   57973:  *   returns an array of the commands implemented by the class (see
                   57974:  *   PEAR/Command/Install.php for an example).
                   57975:  *
                   57976:  * - The class must implement a run() function that is called with three
                   57977:  *   params:
                   57978:  *
                   57979:  *    (string) command name
                   57980:  *    (array)  assoc array with options, freely defined by each
                   57981:  *             command, for example:
                   57982:  *             array('force' => true)
                   57983:  *    (array)  list of the other parameters
                   57984:  *
                   57985:  *   The run() function returns a PEAR_CommandResponse object.  Use
                   57986:  *   these methods to get information:
                   57987:  *
                   57988:  *    int getStatus()   Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
                   57989:  *                      *_PARTIAL means that you need to issue at least
                   57990:  *                      one more command to complete the operation
                   57991:  *                      (used for example for validation steps).
                   57992:  *
                   57993:  *    string getMessage()  Returns a message for the user.  Remember,
                   57994:  *                         no HTML or other interface-specific markup.
                   57995:  *
                   57996:  *   If something unexpected happens, run() returns a PEAR error.
                   57997:  *
                   57998:  * - DON'T OUTPUT ANYTHING! Return text for output instead.
                   57999:  *
                   58000:  * - DON'T USE HTML! The text you return will be used from both Gtk,
                   58001:  *   web and command-line interfaces, so for now, keep everything to
                   58002:  *   plain text.
                   58003:  *
                   58004:  * - DON'T USE EXIT OR DIE! Always use pear errors.  From static
                   58005:  *   classes do PEAR::raiseError(), from other classes do
                   58006:  *   $this->raiseError().
                   58007:  * @category   pear
                   58008:  * @package    PEAR
                   58009:  * @author     Stig Bakken <ssb@php.net>
                   58010:  * @author     Greg Beaver <cellog@php.net>
                   58011:  * @copyright  1997-2009 The Authors
                   58012:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   58013:  * @version    Release: 1.10.0beta1
                   58014:  * @link       http://pear.php.net/package/PEAR
                   58015:  * @since      Class available since Release 0.1
                   58016:  */
                   58017: class PEAR_Command
                   58018: {
                   58019:     // {{{ factory()
                   58020: 
                   58021:     /**
                   58022:      * Get the right object for executing a command.
                   58023:      *
                   58024:      * @param string $command The name of the command
                   58025:      * @param object $config  Instance of PEAR_Config object
                   58026:      *
                   58027:      * @return object the command object or a PEAR error
                   58028:      *
                   58029:      * @access public
                   58030:      * @static
                   58031:      */
                   58032:     function &factory($command, &$config)
                   58033:     {
                   58034:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   58035:             PEAR_Command::registerCommands();
                   58036:         }
                   58037:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   58038:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   58039:         }
                   58040:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   58041:             $a = PEAR::raiseError("unknown command `$command'");
                   58042:             return $a;
                   58043:         }
                   58044:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   58045:         if (!class_exists($class)) {
                   58046:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   58047:         }
                   58048:         if (!class_exists($class)) {
                   58049:             $a = PEAR::raiseError("unknown command `$command'");
                   58050:             return $a;
                   58051:         }
                   58052:         $ui =& PEAR_Command::getFrontendObject();
                   58053:         $obj = &new $class($ui, $config);
                   58054:         return $obj;
                   58055:     }
                   58056: 
                   58057:     // }}}
                   58058:     // {{{ & getObject()
                   58059:     function &getObject($command)
                   58060:     {
                   58061:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   58062:         if (!class_exists($class)) {
                   58063:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   58064:         }
                   58065:         if (!class_exists($class)) {
                   58066:             return PEAR::raiseError("unknown command `$command'");
                   58067:         }
                   58068:         $ui =& PEAR_Command::getFrontendObject();
                   58069:         $config = &PEAR_Config::singleton();
                   58070:         $obj = &new $class($ui, $config);
                   58071:         return $obj;
                   58072:     }
                   58073: 
                   58074:     // }}}
                   58075:     // {{{ & getFrontendObject()
                   58076: 
                   58077:     /**
                   58078:      * Get instance of frontend object.
                   58079:      *
                   58080:      * @return object|PEAR_Error
                   58081:      * @static
                   58082:      */
                   58083:     function &getFrontendObject()
                   58084:     {
                   58085:         $a = &PEAR_Frontend::singleton();
                   58086:         return $a;
                   58087:     }
                   58088: 
                   58089:     // }}}
                   58090:     // {{{ & setFrontendClass()
                   58091: 
                   58092:     /**
                   58093:      * Load current frontend class.
                   58094:      *
                   58095:      * @param string $uiclass Name of class implementing the frontend
                   58096:      *
                   58097:      * @return object the frontend object, or a PEAR error
                   58098:      * @static
                   58099:      */
                   58100:     function &setFrontendClass($uiclass)
                   58101:     {
                   58102:         $a = &PEAR_Frontend::setFrontendClass($uiclass);
                   58103:         return $a;
                   58104:     }
                   58105: 
                   58106:     // }}}
                   58107:     // {{{ setFrontendType()
                   58108: 
                   58109:     /**
                   58110:      * Set current frontend.
                   58111:      *
                   58112:      * @param string $uitype Name of the frontend type (for example "CLI")
                   58113:      *
                   58114:      * @return object the frontend object, or a PEAR error
                   58115:      * @static
                   58116:      */
                   58117:     function setFrontendType($uitype)
                   58118:     {
                   58119:         $uiclass = 'PEAR_Frontend_' . $uitype;
                   58120:         return PEAR_Command::setFrontendClass($uiclass);
                   58121:     }
                   58122: 
                   58123:     // }}}
                   58124:     // {{{ registerCommands()
                   58125: 
                   58126:     /**
                   58127:      * Scan through the Command directory looking for classes
                   58128:      * and see what commands they implement.
                   58129:      *
                   58130:      * @param bool   (optional) if FALSE (default), the new list of
                   58131:      *               commands should replace the current one.  If TRUE,
                   58132:      *               new entries will be merged with old.
                   58133:      *
                   58134:      * @param string (optional) where (what directory) to look for
                   58135:      *               classes, defaults to the Command subdirectory of
                   58136:      *               the directory from where this file (__FILE__) is
                   58137:      *               included.
                   58138:      *
                   58139:      * @return bool TRUE on success, a PEAR error on failure
                   58140:      *
                   58141:      * @access public
                   58142:      * @static
                   58143:      */
                   58144:     function registerCommands($merge = false, $dir = null)
                   58145:     {
                   58146:         $parser = new PEAR_XMLParser;
                   58147:         if ($dir === null) {
                   58148:             $dir = dirname(__FILE__) . '/Command';
                   58149:         }
                   58150:         if (!is_dir($dir)) {
                   58151:             return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
                   58152:         }
                   58153:         $dp = @opendir($dir);
                   58154:         if (empty($dp)) {
                   58155:             return PEAR::raiseError("registerCommands: opendir($dir) failed");
                   58156:         }
                   58157:         if (!$merge) {
                   58158:             $GLOBALS['_PEAR_Command_commandlist'] = array();
                   58159:         }
                   58160: 
                   58161:         while ($file = readdir($dp)) {
                   58162:             if ($file{0} == '.' || substr($file, -4) != '.xml') {
                   58163:                 continue;
                   58164:             }
                   58165: 
                   58166:             $f = substr($file, 0, -4);
                   58167:             $class = "PEAR_Command_" . $f;
                   58168:             // List of commands
                   58169:             if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
                   58170:                 $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
                   58171:             }
                   58172: 
                   58173:             $parser->parse(file_get_contents("$dir/$file"));
                   58174:             $implements = $parser->getData();
                   58175:             foreach ($implements as $command => $desc) {
                   58176:                 if ($command == 'attribs') {
                   58177:                     continue;
                   58178:                 }
                   58179: 
                   58180:                 if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   58181:                     return PEAR::raiseError('Command "' . $command . '" already registered in ' .
                   58182:                         'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   58183:                 }
                   58184: 
                   58185:                 $GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
                   58186:                 $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
                   58187:                 if (isset($desc['shortcut'])) {
                   58188:                     $shortcut = $desc['shortcut'];
                   58189:                     if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
                   58190:                         return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
                   58191:                             'registered to command "' . $command . '" in class "' .
                   58192:                             $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   58193:                     }
                   58194:                     $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
                   58195:                 }
                   58196: 
                   58197:                 if (isset($desc['options']) && $desc['options']) {
                   58198:                     foreach ($desc['options'] as $oname => $option) {
                   58199:                         if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
                   58200:                             return PEAR::raiseError('Option "' . $oname . '" short option "' .
                   58201:                                 $option['shortopt'] . '" must be ' .
                   58202:                                 'only 1 character in Command "' . $command . '" in class "' .
                   58203:                                 $class . '"');
                   58204:                         }
                   58205:                     }
                   58206:                 }
                   58207:             }
                   58208:         }
                   58209: 
                   58210:         ksort($GLOBALS['_PEAR_Command_shortcuts']);
                   58211:         ksort($GLOBALS['_PEAR_Command_commandlist']);
                   58212:         @closedir($dp);
                   58213:         return true;
                   58214:     }
                   58215: 
                   58216:     // }}}
                   58217:     // {{{ getCommands()
                   58218: 
                   58219:     /**
                   58220:      * Get the list of currently supported commands, and what
                   58221:      * classes implement them.
                   58222:      *
                   58223:      * @return array command => implementing class
                   58224:      *
                   58225:      * @access public
                   58226:      * @static
                   58227:      */
                   58228:     function getCommands()
                   58229:     {
                   58230:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   58231:             PEAR_Command::registerCommands();
                   58232:         }
                   58233:         return $GLOBALS['_PEAR_Command_commandlist'];
                   58234:     }
                   58235: 
                   58236:     // }}}
                   58237:     // {{{ getShortcuts()
                   58238: 
                   58239:     /**
                   58240:      * Get the list of command shortcuts.
                   58241:      *
                   58242:      * @return array shortcut => command
                   58243:      *
                   58244:      * @access public
                   58245:      * @static
                   58246:      */
                   58247:     function getShortcuts()
                   58248:     {
                   58249:         if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
                   58250:             PEAR_Command::registerCommands();
                   58251:         }
                   58252:         return $GLOBALS['_PEAR_Command_shortcuts'];
                   58253:     }
                   58254: 
                   58255:     // }}}
                   58256:     // {{{ getGetoptArgs()
                   58257: 
                   58258:     /**
                   58259:      * Compiles arguments for getopt.
                   58260:      *
                   58261:      * @param string $command     command to get optstring for
                   58262:      * @param string $short_args  (reference) short getopt format
                   58263:      * @param array  $long_args   (reference) long getopt format
                   58264:      *
                   58265:      * @return void
                   58266:      *
                   58267:      * @access public
                   58268:      * @static
                   58269:      */
                   58270:     function getGetoptArgs($command, &$short_args, &$long_args)
                   58271:     {
                   58272:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   58273:             PEAR_Command::registerCommands();
                   58274:         }
                   58275:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   58276:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   58277:         }
                   58278:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   58279:             return null;
                   58280:         }
                   58281:         $obj = &PEAR_Command::getObject($command);
                   58282:         return $obj->getGetoptArgs($command, $short_args, $long_args);
                   58283:     }
                   58284: 
                   58285:     // }}}
                   58286:     // {{{ getDescription()
                   58287: 
                   58288:     /**
                   58289:      * Get description for a command.
                   58290:      *
                   58291:      * @param  string $command Name of the command
                   58292:      *
                   58293:      * @return string command description
                   58294:      *
                   58295:      * @access public
                   58296:      * @static
                   58297:      */
                   58298:     function getDescription($command)
                   58299:     {
                   58300:         if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
                   58301:             return null;
                   58302:         }
                   58303:         return $GLOBALS['_PEAR_Command_commanddesc'][$command];
                   58304:     }
                   58305: 
                   58306:     // }}}
                   58307:     // {{{ getHelp()
                   58308: 
                   58309:     /**
                   58310:      * Get help for command.
                   58311:      *
                   58312:      * @param string $command Name of the command to return help for
                   58313:      *
                   58314:      * @access public
                   58315:      * @static
                   58316:      */
                   58317:     function getHelp($command)
                   58318:     {
                   58319:         $cmds = PEAR_Command::getCommands();
                   58320:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   58321:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   58322:         }
                   58323:         if (isset($cmds[$command])) {
                   58324:             $obj = &PEAR_Command::getObject($command);
                   58325:             return $obj->getHelp($command);
                   58326:         }
                   58327:         return false;
                   58328:     }
                   58329:     // }}}
                   58330: }<?php
                   58331: /**
                   58332:  * PEAR_Command_Common base class
                   58333:  *
                   58334:  * PHP versions 4 and 5
                   58335:  *
                   58336:  * @category   pear
                   58337:  * @package    PEAR
                   58338:  * @author     Stig Bakken <ssb@php.net>
                   58339:  * @author     Greg Beaver <cellog@php.net>
                   58340:  * @copyright  1997-2009 The Authors
                   58341:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   58342:  * @version    CVS: $Id: Common.php 276383 2009-02-24 23:39:37Z dufuz $
                   58343:  * @link       http://pear.php.net/package/PEAR
                   58344:  * @since      File available since Release 0.1
                   58345:  */
                   58346: 
                   58347: /**
                   58348:  * base class
                   58349:  */
                   58350: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   58351: 
                   58352: /**
                   58353:  * PEAR commands base class
                   58354:  *
                   58355:  * @category   pear
                   58356:  * @package    PEAR
                   58357:  * @author     Stig Bakken <ssb@php.net>
                   58358:  * @author     Greg Beaver <cellog@php.net>
                   58359:  * @copyright  1997-2009 The Authors
                   58360:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   58361:  * @version    Release: 1.10.0beta1
                   58362:  * @link       http://pear.php.net/package/PEAR
                   58363:  * @since      Class available since Release 0.1
                   58364:  */
                   58365: class PEAR_Command_Common extends PEAR
                   58366: {
                   58367:     /**
                   58368:      * PEAR_Config object used to pass user system and configuration
                   58369:      * on when executing commands
                   58370:      *
                   58371:      * @var PEAR_Config
                   58372:      */
                   58373:     var $config;
                   58374:     /**
                   58375:      * @var PEAR_Registry
                   58376:      * @access protected
                   58377:      */
                   58378:     var $_registry;
                   58379: 
                   58380:     /**
                   58381:      * User Interface object, for all interaction with the user.
                   58382:      * @var object
                   58383:      */
                   58384:     var $ui;
                   58385: 
                   58386:     var $_deps_rel_trans = array(
                   58387:                                  'lt' => '<',
                   58388:                                  'le' => '<=',
                   58389:                                  'eq' => '=',
                   58390:                                  'ne' => '!=',
                   58391:                                  'gt' => '>',
                   58392:                                  'ge' => '>=',
                   58393:                                  'has' => '=='
                   58394:                                  );
                   58395: 
                   58396:     var $_deps_type_trans = array(
                   58397:                                   'pkg' => 'package',
                   58398:                                   'ext' => 'extension',
                   58399:                                   'php' => 'PHP',
                   58400:                                   'prog' => 'external program',
                   58401:                                   'ldlib' => 'external library for linking',
                   58402:                                   'rtlib' => 'external runtime library',
                   58403:                                   'os' => 'operating system',
                   58404:                                   'websrv' => 'web server',
                   58405:                                   'sapi' => 'SAPI backend'
                   58406:                                   );
                   58407: 
                   58408:     /**
                   58409:      * PEAR_Command_Common constructor.
                   58410:      *
                   58411:      * @access public
                   58412:      */
                   58413:     function PEAR_Command_Common(&$ui, &$config)
                   58414:     {
                   58415:         parent::PEAR();
                   58416:         $this->config = &$config;
                   58417:         $this->ui = &$ui;
                   58418:     }
                   58419: 
                   58420:     /**
                   58421:      * Return a list of all the commands defined by this class.
                   58422:      * @return array list of commands
                   58423:      * @access public
                   58424:      */
                   58425:     function getCommands()
                   58426:     {
                   58427:         $ret = array();
                   58428:         foreach (array_keys($this->commands) as $command) {
                   58429:             $ret[$command] = $this->commands[$command]['summary'];
                   58430:         }
                   58431: 
                   58432:         return $ret;
                   58433:     }
                   58434: 
                   58435:     /**
                   58436:      * Return a list of all the command shortcuts defined by this class.
                   58437:      * @return array shortcut => command
                   58438:      * @access public
                   58439:      */
                   58440:     function getShortcuts()
                   58441:     {
                   58442:         $ret = array();
                   58443:         foreach (array_keys($this->commands) as $command) {
                   58444:             if (isset($this->commands[$command]['shortcut'])) {
                   58445:                 $ret[$this->commands[$command]['shortcut']] = $command;
                   58446:             }
                   58447:         }
                   58448: 
                   58449:         return $ret;
                   58450:     }
                   58451: 
                   58452:     function getOptions($command)
                   58453:     {
                   58454:         $shortcuts = $this->getShortcuts();
                   58455:         if (isset($shortcuts[$command])) {
                   58456:             $command = $shortcuts[$command];
                   58457:         }
                   58458: 
                   58459:         if (isset($this->commands[$command]) &&
                   58460:               isset($this->commands[$command]['options'])) {
                   58461:             return $this->commands[$command]['options'];
                   58462:         }
                   58463: 
                   58464:         return null;
                   58465:     }
                   58466: 
                   58467:     function getGetoptArgs($command, &$short_args, &$long_args)
                   58468:     {
                   58469:         $short_args = '';
                   58470:         $long_args = array();
                   58471:         if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
                   58472:             return;
                   58473:         }
                   58474: 
                   58475:         reset($this->commands[$command]['options']);
                   58476:         while (list($option, $info) = each($this->commands[$command]['options'])) {
                   58477:             $larg = $sarg = '';
                   58478:             if (isset($info['arg'])) {
                   58479:                 if ($info['arg']{0} == '(') {
                   58480:                     $larg = '==';
                   58481:                     $sarg = '::';
                   58482:                     $arg = substr($info['arg'], 1, -1);
                   58483:                 } else {
                   58484:                     $larg = '=';
                   58485:                     $sarg = ':';
                   58486:                     $arg = $info['arg'];
                   58487:                 }
                   58488:             }
                   58489: 
                   58490:             if (isset($info['shortopt'])) {
                   58491:                 $short_args .= $info['shortopt'] . $sarg;
                   58492:             }
                   58493: 
                   58494:             $long_args[] = $option . $larg;
                   58495:         }
                   58496:     }
                   58497: 
                   58498:     /**
                   58499:     * Returns the help message for the given command
                   58500:     *
                   58501:     * @param string $command The command
                   58502:     * @return mixed A fail string if the command does not have help or
                   58503:     *               a two elements array containing [0]=>help string,
                   58504:     *               [1]=> help string for the accepted cmd args
                   58505:     */
                   58506:     function getHelp($command)
                   58507:     {
                   58508:         $config = &PEAR_Config::singleton();
                   58509:         if (!isset($this->commands[$command])) {
                   58510:             return "No such command \"$command\"";
                   58511:         }
                   58512: 
                   58513:         $help = null;
                   58514:         if (isset($this->commands[$command]['doc'])) {
                   58515:             $help = $this->commands[$command]['doc'];
                   58516:         }
                   58517: 
                   58518:         if (empty($help)) {
                   58519:             // XXX (cox) Fallback to summary if there is no doc (show both?)
                   58520:             if (!isset($this->commands[$command]['summary'])) {
                   58521:                 return "No help for command \"$command\"";
                   58522:             }
                   58523:             $help = $this->commands[$command]['summary'];
                   58524:         }
                   58525: 
                   58526:         if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
                   58527:             foreach($matches[0] as $k => $v) {
                   58528:                 $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
                   58529:             }
                   58530:         }
                   58531: 
                   58532:         return array($help, $this->getHelpArgs($command));
                   58533:     }
                   58534: 
                   58535:     /**
                   58536:      * Returns the help for the accepted arguments of a command
                   58537:      *
                   58538:      * @param  string $command
                   58539:      * @return string The help string
                   58540:      */
                   58541:     function getHelpArgs($command)
                   58542:     {
                   58543:         if (isset($this->commands[$command]['options']) &&
                   58544:             count($this->commands[$command]['options']))
                   58545:         {
                   58546:             $help = "Options:\n";
                   58547:             foreach ($this->commands[$command]['options'] as $k => $v) {
                   58548:                 if (isset($v['arg'])) {
                   58549:                     if ($v['arg'][0] == '(') {
                   58550:                         $arg = substr($v['arg'], 1, -1);
                   58551:                         $sapp = " [$arg]";
                   58552:                         $lapp = "[=$arg]";
                   58553:                     } else {
                   58554:                         $sapp = " $v[arg]";
                   58555:                         $lapp = "=$v[arg]";
                   58556:                     }
                   58557:                 } else {
                   58558:                     $sapp = $lapp = "";
                   58559:                 }
                   58560: 
                   58561:                 if (isset($v['shortopt'])) {
                   58562:                     $s = $v['shortopt'];
                   58563:                     $help .= "  -$s$sapp, --$k$lapp\n";
                   58564:                 } else {
                   58565:                     $help .= "  --$k$lapp\n";
                   58566:                 }
                   58567: 
                   58568:                 $p = "        ";
                   58569:                 $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
                   58570:                 $help .= "        $doc\n";
                   58571:             }
                   58572: 
                   58573:             return $help;
                   58574:         }
                   58575: 
                   58576:         return null;
                   58577:     }
                   58578: 
                   58579:     function run($command, $options, $params)
                   58580:     {
                   58581:         if (empty($this->commands[$command]['function'])) {
                   58582:             // look for shortcuts
                   58583:             foreach (array_keys($this->commands) as $cmd) {
                   58584:                 if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
                   58585:                     if (empty($this->commands[$cmd]['function'])) {
                   58586:                         return $this->raiseError("unknown command `$command'");
                   58587:                     } else {
                   58588:                         $func = $this->commands[$cmd]['function'];
                   58589:                     }
                   58590:                     $command = $cmd;
                   58591: 
                   58592:                     //$command = $this->commands[$cmd]['function'];
                   58593:                     break;
                   58594:                 }
                   58595:             }
                   58596:         } else {
                   58597:             $func = $this->commands[$command]['function'];
                   58598:         }
                   58599: 
                   58600:         return $this->$func($command, $options, $params);
                   58601:     }
                   58602: }<?php
                   58603: /**
                   58604:  * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
                   58605:  *
                   58606:  * PHP versions 4 and 5
                   58607:  *
                   58608:  * @category   pear
                   58609:  * @package    PEAR
                   58610:  * @author     Stig Bakken <ssb@php.net>
                   58611:  * @author     Greg Beaver <cellog@php.net>
                   58612:  * @copyright  1997-2009 The Authors
                   58613:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   58614:  * @version    CVS: $Id: Install.php 311686 2011-06-01 02:35:01Z dufuz $
                   58615:  * @link       http://pear.php.net/package/PEAR
                   58616:  * @since      File available since Release 0.1
                   58617:  */
                   58618: 
                   58619: /**
                   58620:  * base class
                   58621:  */
                   58622: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
                   58623: 
                   58624: /**
                   58625:  * PEAR commands for installation or deinstallation/upgrading of
                   58626:  * packages.
                   58627:  *
                   58628:  * @category   pear
                   58629:  * @package    PEAR
                   58630:  * @author     Stig Bakken <ssb@php.net>
                   58631:  * @author     Greg Beaver <cellog@php.net>
                   58632:  * @copyright  1997-2009 The Authors
                   58633:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   58634:  * @version    Release: 1.10.0beta1
                   58635:  * @link       http://pear.php.net/package/PEAR
                   58636:  * @since      Class available since Release 0.1
                   58637:  */
                   58638: class PEAR_Command_Install extends PEAR_Command_Common
                   58639: {
                   58640:     // {{{ properties
                   58641: 
                   58642:     var $commands = array(
                   58643:         'install' => array(
                   58644:             'summary' => 'Install Package',
                   58645:             'function' => 'doInstall',
                   58646:             'shortcut' => 'i',
                   58647:             'options' => array(
                   58648:                 'force' => array(
                   58649:                     'shortopt' => 'f',
                   58650:                     'doc' => 'will overwrite newer installed packages',
                   58651:                     ),
                   58652:                 'loose' => array(
                   58653:                     'shortopt' => 'l',
                   58654:                     'doc' => 'do not check for recommended dependency version',
                   58655:                     ),
                   58656:                 'nodeps' => array(
                   58657:                     'shortopt' => 'n',
                   58658:                     'doc' => 'ignore dependencies, install anyway',
                   58659:                     ),
                   58660:                 'register-only' => array(
                   58661:                     'shortopt' => 'r',
                   58662:                     'doc' => 'do not install files, only register the package as installed',
                   58663:                     ),
                   58664:                 'soft' => array(
                   58665:                     'shortopt' => 's',
                   58666:                     'doc' => 'soft install, fail silently, or upgrade if already installed',
                   58667:                     ),
                   58668:                 'nobuild' => array(
                   58669:                     'shortopt' => 'B',
                   58670:                     'doc' => 'don\'t build C extensions',
                   58671:                     ),
                   58672:                 'nocompress' => array(
                   58673:                     'shortopt' => 'Z',
                   58674:                     'doc' => 'request uncompressed files when downloading',
                   58675:                     ),
                   58676:                 'installroot' => array(
                   58677:                     'shortopt' => 'R',
                   58678:                     'arg' => 'DIR',
                   58679:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   58680:                     ),
                   58681:                 'packagingroot' => array(
                   58682:                     'shortopt' => 'P',
                   58683:                     'arg' => 'DIR',
                   58684:                     'doc' => 'root directory used when packaging files, like RPM packaging',
                   58685:                     ),
                   58686:                 'ignore-errors' => array(
                   58687:                     'doc' => 'force install even if there were errors',
                   58688:                     ),
                   58689:                 'alldeps' => array(
                   58690:                     'shortopt' => 'a',
                   58691:                     'doc' => 'install all required and optional dependencies',
                   58692:                     ),
                   58693:                 'onlyreqdeps' => array(
                   58694:                     'shortopt' => 'o',
                   58695:                     'doc' => 'install all required dependencies',
                   58696:                     ),
                   58697:                 'offline' => array(
                   58698:                     'shortopt' => 'O',
                   58699:                     'doc' => 'do not attempt to download any urls or contact channels',
                   58700:                     ),
                   58701:                 'pretend' => array(
                   58702:                     'shortopt' => 'p',
                   58703:                     'doc' => 'Only list the packages that would be downloaded',
                   58704:                     ),
                   58705:                 ),
                   58706:             'doc' => '[channel/]<package> ...
                   58707: Installs one or more PEAR packages.  You can specify a package to
                   58708: install in four ways:
                   58709: 
                   58710: "Package-1.0.tgz" : installs from a local file
                   58711: 
                   58712: "http://example.com/Package-1.0.tgz" : installs from
                   58713: anywhere on the net.
                   58714: 
                   58715: "package.xml" : installs the package described in
                   58716: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   58717: another package manager such as RPM.
                   58718: 
                   58719: "Package[-version/state][.tar]" : queries your default channel\'s server
                   58720: ({config master_server}) and downloads the newest package with
                   58721: the preferred quality/state ({config preferred_state}).
                   58722: 
                   58723: To retrieve Package version 1.1, use "Package-1.1," to retrieve
                   58724: Package state beta, use "Package-beta."  To retrieve an uncompressed
                   58725: file, append .tar (make sure there is no file by the same name first)
                   58726: 
                   58727: To download a package from another channel, prefix with the channel name like
                   58728: "channel/Package"
                   58729: 
                   58730: More than one package may be specified at once.  It is ok to mix these
                   58731: four ways of specifying packages.
                   58732: '),
                   58733:         'upgrade' => array(
                   58734:             'summary' => 'Upgrade Package',
                   58735:             'function' => 'doInstall',
                   58736:             'shortcut' => 'up',
                   58737:             'options' => array(
                   58738:                 'channel' => array(
                   58739:                     'shortopt' => 'c',
                   58740:                     'doc' => 'upgrade packages from a specific channel',
                   58741:                     'arg' => 'CHAN',
                   58742:                     ),
                   58743:                 'force' => array(
                   58744:                     'shortopt' => 'f',
                   58745:                     'doc' => 'overwrite newer installed packages',
                   58746:                     ),
                   58747:                 'loose' => array(
                   58748:                     'shortopt' => 'l',
                   58749:                     'doc' => 'do not check for recommended dependency version',
                   58750:                     ),
                   58751:                 'nodeps' => array(
                   58752:                     'shortopt' => 'n',
                   58753:                     'doc' => 'ignore dependencies, upgrade anyway',
                   58754:                     ),
                   58755:                 'register-only' => array(
                   58756:                     'shortopt' => 'r',
                   58757:                     'doc' => 'do not install files, only register the package as upgraded',
                   58758:                     ),
                   58759:                 'nobuild' => array(
                   58760:                     'shortopt' => 'B',
                   58761:                     'doc' => 'don\'t build C extensions',
                   58762:                     ),
                   58763:                 'nocompress' => array(
                   58764:                     'shortopt' => 'Z',
                   58765:                     'doc' => 'request uncompressed files when downloading',
                   58766:                     ),
                   58767:                 'installroot' => array(
                   58768:                     'shortopt' => 'R',
                   58769:                     'arg' => 'DIR',
                   58770:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   58771:                     ),
                   58772:                 'ignore-errors' => array(
                   58773:                     'doc' => 'force install even if there were errors',
                   58774:                     ),
                   58775:                 'alldeps' => array(
                   58776:                     'shortopt' => 'a',
                   58777:                     'doc' => 'install all required and optional dependencies',
                   58778:                     ),
                   58779:                 'onlyreqdeps' => array(
                   58780:                     'shortopt' => 'o',
                   58781:                     'doc' => 'install all required dependencies',
                   58782:                     ),
                   58783:                 'offline' => array(
                   58784:                     'shortopt' => 'O',
                   58785:                     'doc' => 'do not attempt to download any urls or contact channels',
                   58786:                     ),
                   58787:                 'pretend' => array(
                   58788:                     'shortopt' => 'p',
                   58789:                     'doc' => 'Only list the packages that would be downloaded',
                   58790:                     ),
                   58791:                 ),
                   58792:             'doc' => '<package> ...
                   58793: Upgrades one or more PEAR packages.  See documentation for the
                   58794: "install" command for ways to specify a package.
                   58795: 
                   58796: When upgrading, your package will be updated if the provided new
                   58797: package has a higher version number (use the -f option if you need to
                   58798: upgrade anyway).
                   58799: 
                   58800: More than one package may be specified at once.
                   58801: '),
                   58802:         'upgrade-all' => array(
                   58803:             'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
                   58804:             'function' => 'doUpgradeAll',
                   58805:             'shortcut' => 'ua',
                   58806:             'options' => array(
                   58807:                 'channel' => array(
                   58808:                     'shortopt' => 'c',
                   58809:                     'doc' => 'upgrade packages from a specific channel',
                   58810:                     'arg' => 'CHAN',
                   58811:                     ),
                   58812:                 'nodeps' => array(
                   58813:                     'shortopt' => 'n',
                   58814:                     'doc' => 'ignore dependencies, upgrade anyway',
                   58815:                     ),
                   58816:                 'register-only' => array(
                   58817:                     'shortopt' => 'r',
                   58818:                     'doc' => 'do not install files, only register the package as upgraded',
                   58819:                     ),
                   58820:                 'nobuild' => array(
                   58821:                     'shortopt' => 'B',
                   58822:                     'doc' => 'don\'t build C extensions',
                   58823:                     ),
                   58824:                 'nocompress' => array(
                   58825:                     'shortopt' => 'Z',
                   58826:                     'doc' => 'request uncompressed files when downloading',
                   58827:                     ),
                   58828:                 'installroot' => array(
                   58829:                     'shortopt' => 'R',
                   58830:                     'arg' => 'DIR',
                   58831:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   58832:                     ),
                   58833:                 'ignore-errors' => array(
                   58834:                     'doc' => 'force install even if there were errors',
                   58835:                     ),
                   58836:                 'loose' => array(
                   58837:                     'doc' => 'do not check for recommended dependency version',
                   58838:                     ),
                   58839:                 ),
                   58840:             'doc' => '
                   58841: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   58842: 
                   58843: Upgrades all packages that have a newer release available.  Upgrades are
                   58844: done only if there is a release available of the state specified in
                   58845: "preferred_state" (currently {config preferred_state}), or a state considered
                   58846: more stable.
                   58847: '),
                   58848:         'uninstall' => array(
                   58849:             'summary' => 'Un-install Package',
                   58850:             'function' => 'doUninstall',
                   58851:             'shortcut' => 'un',
                   58852:             'options' => array(
                   58853:                 'nodeps' => array(
                   58854:                     'shortopt' => 'n',
                   58855:                     'doc' => 'ignore dependencies, uninstall anyway',
                   58856:                     ),
                   58857:                 'register-only' => array(
                   58858:                     'shortopt' => 'r',
                   58859:                     'doc' => 'do not remove files, only register the packages as not installed',
                   58860:                     ),
                   58861:                 'installroot' => array(
                   58862:                     'shortopt' => 'R',
                   58863:                     'arg' => 'DIR',
                   58864:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   58865:                     ),
                   58866:                 'ignore-errors' => array(
                   58867:                     'doc' => 'force install even if there were errors',
                   58868:                     ),
                   58869:                 'offline' => array(
                   58870:                     'shortopt' => 'O',
                   58871:                     'doc' => 'do not attempt to uninstall remotely',
                   58872:                     ),
                   58873:                 ),
                   58874:             'doc' => '[channel/]<package> ...
                   58875: Uninstalls one or more PEAR packages.  More than one package may be
                   58876: specified at once.  Prefix with channel name to uninstall from a
                   58877: channel not in your default channel ({config default_channel})
                   58878: '),
                   58879:         'bundle' => array(
                   58880:             'summary' => 'Unpacks a Pecl Package',
                   58881:             'function' => 'doBundle',
                   58882:             'shortcut' => 'bun',
                   58883:             'options' => array(
                   58884:                 'destination' => array(
                   58885:                    'shortopt' => 'd',
                   58886:                     'arg' => 'DIR',
                   58887:                     'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
                   58888:                     ),
                   58889:                 'force' => array(
                   58890:                     'shortopt' => 'f',
                   58891:                     'doc' => 'Force the unpacking even if there were errors in the package',
                   58892:                 ),
                   58893:             ),
                   58894:             'doc' => '<package>
                   58895: Unpacks a Pecl Package into the selected location. It will download the
                   58896: package if needed.
                   58897: '),
                   58898:         'run-scripts' => array(
                   58899:             'summary' => 'Run Post-Install Scripts bundled with a package',
                   58900:             'function' => 'doRunScripts',
                   58901:             'shortcut' => 'rs',
                   58902:             'options' => array(
                   58903:             ),
                   58904:             'doc' => '<package>
                   58905: Run post-installation scripts in package <package>, if any exist.
                   58906: '),
                   58907:     );
                   58908: 
                   58909:     // }}}
                   58910:     // {{{ constructor
                   58911: 
                   58912:     /**
                   58913:      * PEAR_Command_Install constructor.
                   58914:      *
                   58915:      * @access public
                   58916:      */
                   58917:     function PEAR_Command_Install(&$ui, &$config)
                   58918:     {
                   58919:         parent::PEAR_Command_Common($ui, $config);
                   58920:     }
                   58921: 
                   58922:     // }}}
                   58923: 
                   58924:     /**
                   58925:      * For unit testing purposes
                   58926:      */
                   58927:     function &getDownloader(&$ui, $options, &$config)
                   58928:     {
                   58929:         if (!class_exists('PEAR_Downloader')) {
                   58930:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
                   58931:         }
                   58932:         $a = &new PEAR_Downloader($ui, $options, $config);
                   58933:         return $a;
                   58934:     }
                   58935: 
                   58936:     /**
                   58937:      * For unit testing purposes
                   58938:      */
                   58939:     function &getInstaller(&$ui)
                   58940:     {
                   58941:         if (!class_exists('PEAR_Installer')) {
                   58942:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer.php';
                   58943:         }
                   58944:         $a = &new PEAR_Installer($ui);
                   58945:         return $a;
                   58946:     }
                   58947: 
                   58948:     function enableExtension($binaries, $type)
                   58949:     {
                   58950:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   58951:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   58952:         }
                   58953:         $ini = $this->_parseIni($phpini);
                   58954:         if (PEAR::isError($ini)) {
                   58955:             return $ini;
                   58956:         }
                   58957:         $line = 0;
                   58958:         if ($type == 'extsrc' || $type == 'extbin') {
                   58959:             $search = 'extensions';
                   58960:             $enable = 'extension';
                   58961:         } else {
                   58962:             $search = 'zend_extensions';
                   58963:             ob_start();
                   58964:             phpinfo(INFO_GENERAL);
                   58965:             $info = ob_get_contents();
                   58966:             ob_end_clean();
                   58967:             $debug = function_exists('leak') ? '_debug' : '';
                   58968:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   58969:             $enable = 'zend_extension' . $debug . $ts;
                   58970:         }
                   58971:         foreach ($ini[$search] as $line => $extension) {
                   58972:             if (in_array($extension, $binaries, true) || in_array(
                   58973:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   58974:                 // already enabled - assume if one is, all are
                   58975:                 return true;
                   58976:             }
                   58977:         }
                   58978:         if ($line) {
                   58979:             $newini = array_slice($ini['all'], 0, $line);
                   58980:         } else {
                   58981:             $newini = array();
                   58982:         }
                   58983:         foreach ($binaries as $binary) {
                   58984:             if ($ini['extension_dir']) {
                   58985:                 $binary = basename($binary);
                   58986:             }
                   58987:             $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
                   58988:         }
                   58989:         $newini = array_merge($newini, array_slice($ini['all'], $line));
                   58990:         $fp = @fopen($phpini, 'wb');
                   58991:         if (!$fp) {
                   58992:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   58993:         }
                   58994:         foreach ($newini as $line) {
                   58995:             fwrite($fp, $line);
                   58996:         }
                   58997:         fclose($fp);
                   58998:         return true;
                   58999:     }
                   59000: 
                   59001:     function disableExtension($binaries, $type)
                   59002:     {
                   59003:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   59004:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   59005:         }
                   59006:         $ini = $this->_parseIni($phpini);
                   59007:         if (PEAR::isError($ini)) {
                   59008:             return $ini;
                   59009:         }
                   59010:         $line = 0;
                   59011:         if ($type == 'extsrc' || $type == 'extbin') {
                   59012:             $search = 'extensions';
                   59013:             $enable = 'extension';
                   59014:         } else {
                   59015:             $search = 'zend_extensions';
                   59016:             ob_start();
                   59017:             phpinfo(INFO_GENERAL);
                   59018:             $info = ob_get_contents();
                   59019:             ob_end_clean();
                   59020:             $debug = function_exists('leak') ? '_debug' : '';
                   59021:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   59022:             $enable = 'zend_extension' . $debug . $ts;
                   59023:         }
                   59024:         $found = false;
                   59025:         foreach ($ini[$search] as $line => $extension) {
                   59026:             if (in_array($extension, $binaries, true) || in_array(
                   59027:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   59028:                 $found = true;
                   59029:                 break;
                   59030:             }
                   59031:         }
                   59032:         if (!$found) {
                   59033:             // not enabled
                   59034:             return true;
                   59035:         }
                   59036:         $fp = @fopen($phpini, 'wb');
                   59037:         if (!$fp) {
                   59038:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   59039:         }
                   59040:         if ($line) {
                   59041:             $newini = array_slice($ini['all'], 0, $line);
                   59042:             // delete the enable line
                   59043:             $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
                   59044:         } else {
                   59045:             $newini = array_slice($ini['all'], 1);
                   59046:         }
                   59047:         foreach ($newini as $line) {
                   59048:             fwrite($fp, $line);
                   59049:         }
                   59050:         fclose($fp);
                   59051:         return true;
                   59052:     }
                   59053: 
                   59054:     function _parseIni($filename)
                   59055:     {
                   59056:         if (!file_exists($filename)) {
                   59057:             return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
                   59058:         }
                   59059: 
                   59060:         if (filesize($filename) > 300000) {
                   59061:             return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
                   59062:         }
                   59063: 
                   59064:         ob_start();
                   59065:         phpinfo(INFO_GENERAL);
                   59066:         $info = ob_get_contents();
                   59067:         ob_end_clean();
                   59068:         $debug = function_exists('leak') ? '_debug' : '';
                   59069:         $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   59070:         $zend_extension_line = 'zend_extension' . $debug . $ts;
                   59071:         $all = @file($filename);
                   59072:         if (!$all) {
                   59073:             return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
                   59074:         }
                   59075:         $zend_extensions = $extensions = array();
                   59076:         // assume this is right, but pull from the php.ini if it is found
                   59077:         $extension_dir = ini_get('extension_dir');
                   59078:         foreach ($all as $linenum => $line) {
                   59079:             $line = trim($line);
                   59080:             if (!$line) {
                   59081:                 continue;
                   59082:             }
                   59083:             if ($line[0] == ';') {
                   59084:                 continue;
                   59085:             }
                   59086:             if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
                   59087:                 $line = trim(substr($line, 13));
                   59088:                 if ($line[0] == '=') {
                   59089:                     $x = trim(substr($line, 1));
                   59090:                     $x = explode(';', $x);
                   59091:                     $extension_dir = str_replace('"', '', array_shift($x));
                   59092:                     continue;
                   59093:                 }
                   59094:             }
                   59095:             if (strtolower(substr($line, 0, 9)) == 'extension') {
                   59096:                 $line = trim(substr($line, 9));
                   59097:                 if ($line[0] == '=') {
                   59098:                     $x = trim(substr($line, 1));
                   59099:                     $x = explode(';', $x);
                   59100:                     $extensions[$linenum] = str_replace('"', '', array_shift($x));
                   59101:                     continue;
                   59102:                 }
                   59103:             }
                   59104:             if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
                   59105:                   $zend_extension_line) {
                   59106:                 $line = trim(substr($line, strlen($zend_extension_line)));
                   59107:                 if ($line[0] == '=') {
                   59108:                     $x = trim(substr($line, 1));
                   59109:                     $x = explode(';', $x);
                   59110:                     $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
                   59111:                     continue;
                   59112:                 }
                   59113:             }
                   59114:         }
                   59115:         return array(
                   59116:             'extensions' => $extensions,
                   59117:             'zend_extensions' => $zend_extensions,
                   59118:             'extension_dir' => $extension_dir,
                   59119:             'all' => $all,
                   59120:         );
                   59121:     }
                   59122: 
                   59123:     // {{{ doInstall()
                   59124: 
                   59125:     function doInstall($command, $options, $params)
                   59126:     {
                   59127:         if (!class_exists('PEAR_PackageFile')) {
                   59128:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
                   59129:         }
                   59130: 
                   59131:         if (isset($options['installroot']) && isset($options['packagingroot'])) {
                   59132:             return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
                   59133:         }
                   59134: 
                   59135:         $reg = &$this->config->getRegistry();
                   59136:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   59137:         if (!$reg->channelExists($channel)) {
                   59138:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   59139:         }
                   59140: 
                   59141:         if (empty($this->installer)) {
                   59142:             $this->installer = &$this->getInstaller($this->ui);
                   59143:         }
                   59144: 
                   59145:         if ($command == 'upgrade' || $command == 'upgrade-all') {
                   59146:             // If people run the upgrade command but pass nothing, emulate a upgrade-all
                   59147:             if ($command == 'upgrade' && empty($params)) {
                   59148:                 return $this->doUpgradeAll($command, $options, $params);
                   59149:             }
                   59150:             $options['upgrade'] = true;
                   59151:         } else {
                   59152:             $packages = $params;
                   59153:         }
                   59154: 
                   59155:         $instreg = &$reg; // instreg used to check if package is installed
                   59156:         if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
                   59157:             $packrootphp_dir = $this->installer->_prependPath(
                   59158:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   59159:                 $options['packagingroot']);
                   59160:             $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
                   59161: 
                   59162:             if ($this->config->get('verbose') > 2) {
                   59163:                 $this->ui->outputData('using package root: ' . $options['packagingroot']);
                   59164:             }
                   59165:         }
                   59166: 
                   59167:         $abstractpackages = $otherpackages = array();
                   59168:         // parse params
                   59169:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59170: 
                   59171:         foreach ($params as $param) {
                   59172:             if (strpos($param, 'http://') === 0) {
                   59173:                 $otherpackages[] = $param;
                   59174:                 continue;
                   59175:             }
                   59176: 
                   59177:             if (strpos($param, 'channel://') === false && @file_exists($param)) {
                   59178:                 if (isset($options['force'])) {
                   59179:                     $otherpackages[] = $param;
                   59180:                     continue;
                   59181:                 }
                   59182: 
                   59183:                 $pkg = new PEAR_PackageFile($this->config);
                   59184:                 $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
                   59185:                 if (PEAR::isError($pf)) {
                   59186:                     $otherpackages[] = $param;
                   59187:                     continue;
                   59188:                 }
                   59189: 
                   59190:                 $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
                   59191:                 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
                   59192:                 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
                   59193:                 if ($exists && $version_compare) {
                   59194:                     if ($this->config->get('verbose')) {
                   59195:                         $this->ui->outputData('Ignoring installed package ' .
                   59196:                             $reg->parsedPackageNameToString(
                   59197:                             array('package' => $pf->getPackage(),
                   59198:                                   'channel' => $pf->getChannel()), true));
                   59199:                     }
                   59200:                     continue;
                   59201:                 }
                   59202:                 $otherpackages[] = $param;
                   59203:                 continue;
                   59204:             }
                   59205: 
                   59206:             $e = $reg->parsePackageName($param, $channel);
                   59207:             if (PEAR::isError($e)) {
                   59208:                 $otherpackages[] = $param;
                   59209:             } else {
                   59210:                 $abstractpackages[] = $e;
                   59211:             }
                   59212:         }
                   59213:         PEAR::staticPopErrorHandling();
                   59214: 
                   59215:         // if there are any local package .tgz or remote static url, we can't
                   59216:         // filter.  The filter only works for abstract packages
                   59217:         if (count($abstractpackages) && !isset($options['force'])) {
                   59218:             // when not being forced, only do necessary upgrades/installs
                   59219:             if (isset($options['upgrade'])) {
                   59220:                 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
                   59221:             } else {
                   59222:                 $count = count($abstractpackages);
                   59223:                 foreach ($abstractpackages as $i => $package) {
                   59224:                     if (isset($package['group'])) {
                   59225:                         // do not filter out install groups
                   59226:                         continue;
                   59227:                     }
                   59228: 
                   59229:                     if ($instreg->packageExists($package['package'], $package['channel'])) {
                   59230:                         if ($count > 1) {
                   59231:                             if ($this->config->get('verbose')) {
                   59232:                                 $this->ui->outputData('Ignoring installed package ' .
                   59233:                                     $reg->parsedPackageNameToString($package, true));
                   59234:                             }
                   59235:                             unset($abstractpackages[$i]);
                   59236:                         } elseif ($count === 1) {
                   59237:                             // Lets try to upgrade it since it's already installed
                   59238:                             $options['upgrade'] = true;
                   59239:                         }
                   59240:                     }
                   59241:                 }
                   59242:             }
                   59243:             $abstractpackages =
                   59244:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   59245:         } elseif (count($abstractpackages)) {
                   59246:             $abstractpackages =
                   59247:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   59248:         }
                   59249: 
                   59250:         $packages = array_merge($abstractpackages, $otherpackages);
                   59251:         if (!count($packages)) {
                   59252:             $c = '';
                   59253:             if (isset($options['channel'])){
                   59254:                 $c .= ' in channel "' . $options['channel'] . '"';
                   59255:             }
                   59256:             $this->ui->outputData('Nothing to ' . $command . $c);
                   59257:             return true;
                   59258:         }
                   59259: 
                   59260:         $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
                   59261:         $errors = $downloaded = $binaries = array();
                   59262:         $downloaded = &$this->downloader->download($packages);
                   59263:         if (PEAR::isError($downloaded)) {
                   59264:             return $this->raiseError($downloaded);
                   59265:         }
                   59266: 
                   59267:         $errors = $this->downloader->getErrorMsgs();
                   59268:         if (count($errors)) {
                   59269:             $err = array();
                   59270:             $err['data'] = array();
                   59271:             foreach ($errors as $error) {
                   59272:                 if ($error !== null) {
                   59273:                     $err['data'][] = array($error);
                   59274:                 }
                   59275:             }
                   59276: 
                   59277:             if (!empty($err['data'])) {
                   59278:                 $err['headline'] = 'Install Errors';
                   59279:                 $this->ui->outputData($err);
                   59280:             }
                   59281: 
                   59282:             if (!count($downloaded)) {
                   59283:                 return $this->raiseError("$command failed");
                   59284:             }
                   59285:         }
                   59286: 
                   59287:         $data = array(
                   59288:             'headline' => 'Packages that would be Installed'
                   59289:         );
                   59290: 
                   59291:         if (isset($options['pretend'])) {
                   59292:             foreach ($downloaded as $package) {
                   59293:                 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
                   59294:             }
                   59295:             $this->ui->outputData($data, 'pretend');
                   59296:             return true;
                   59297:         }
                   59298: 
                   59299:         $this->installer->setOptions($options);
                   59300:         $this->installer->sortPackagesForInstall($downloaded);
                   59301:         if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
                   59302:             $this->raiseError($err->getMessage());
                   59303:             return true;
                   59304:         }
                   59305: 
                   59306:         $binaries = $extrainfo = array();
                   59307:         foreach ($downloaded as $param) {
                   59308:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59309:             $info = $this->installer->install($param, $options);
                   59310:             PEAR::staticPopErrorHandling();
                   59311:             if (PEAR::isError($info)) {
                   59312:                 $oldinfo = $info;
                   59313:                 $pkg = &$param->getPackageFile();
                   59314:                 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
                   59315:                     if (!($info = $pkg->installBinary($this->installer))) {
                   59316:                         $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
                   59317:                         continue;
                   59318:                     }
                   59319: 
                   59320:                     // we just installed a different package than requested,
                   59321:                     // let's change the param and info so that the rest of this works
                   59322:                     $param = $info[0];
                   59323:                     $info  = $info[1];
                   59324:                 }
                   59325:             }
                   59326: 
                   59327:             if (!is_array($info)) {
                   59328:                 return $this->raiseError("$command failed");
                   59329:             }
                   59330: 
                   59331:             if ($param->getPackageType() == 'extsrc' ||
                   59332:                   $param->getPackageType() == 'extbin' ||
                   59333:                   $param->getPackageType() == 'zendextsrc' ||
                   59334:                   $param->getPackageType() == 'zendextbin'
                   59335:             ) {
                   59336:                 $pkg = &$param->getPackageFile();
                   59337:                 if ($instbin = $pkg->getInstalledBinary()) {
                   59338:                     $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
                   59339:                 } else {
                   59340:                     $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
                   59341:                 }
                   59342: 
                   59343:                 foreach ($instpkg->getFilelist() as $name => $atts) {
                   59344:                     $pinfo = pathinfo($atts['installed_as']);
                   59345:                     if (!isset($pinfo['extension']) ||
                   59346:                           in_array($pinfo['extension'], array('c', 'h'))
                   59347:                     ) {
                   59348:                         continue; // make sure we don't match php_blah.h
                   59349:                     }
                   59350: 
                   59351:                     if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   59352:                           $pinfo['extension'] == 'dll') ||
                   59353:                           // most unices
                   59354:                           $pinfo['extension'] == 'so' ||
                   59355:                           // hp-ux
                   59356:                           $pinfo['extension'] == 'sl') {
                   59357:                         $binaries[] = array($atts['installed_as'], $pinfo);
                   59358:                         break;
                   59359:                     }
                   59360:                 }
                   59361: 
                   59362:                 if (count($binaries)) {
                   59363:                     foreach ($binaries as $pinfo) {
                   59364:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59365:                         $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
                   59366:                         PEAR::staticPopErrorHandling();
                   59367:                         if (PEAR::isError($ret)) {
                   59368:                             $extrainfo[] = $ret->getMessage();
                   59369:                             if ($param->getPackageType() == 'extsrc' ||
                   59370:                                   $param->getPackageType() == 'extbin') {
                   59371:                                 $exttype = 'extension';
                   59372:                             } else {
                   59373:                                 ob_start();
                   59374:                                 phpinfo(INFO_GENERAL);
                   59375:                                 $info = ob_get_contents();
                   59376:                                 ob_end_clean();
                   59377:                                 $debug = function_exists('leak') ? '_debug' : '';
                   59378:                                 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   59379:                                 $exttype = 'zend_extension' . $debug . $ts;
                   59380:                             }
                   59381:                             $extrainfo[] = 'You should add "' . $exttype . '=' .
                   59382:                                 $pinfo[1]['basename'] . '" to php.ini';
                   59383:                         } else {
                   59384:                             $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
                   59385:                                 ' enabled in php.ini';
                   59386:                         }
                   59387:                     }
                   59388:                 }
                   59389:             }
                   59390: 
                   59391:             if ($this->config->get('verbose') > 0) {
                   59392:                 $chan = $param->getChannel();
                   59393:                 $label = $reg->parsedPackageNameToString(
                   59394:                     array(
                   59395:                         'channel' => $chan,
                   59396:                         'package' => $param->getPackage(),
                   59397:                         'version' => $param->getVersion(),
                   59398:                     ));
                   59399:                 $out = array('data' => "$command ok: $label");
                   59400:                 if (isset($info['release_warnings'])) {
                   59401:                     $out['release_warnings'] = $info['release_warnings'];
                   59402:                 }
                   59403:                 $this->ui->outputData($out, $command);
                   59404: 
                   59405:                 if (!isset($options['register-only']) && !isset($options['offline'])) {
                   59406:                     if ($this->config->isDefinedLayer('ftp')) {
                   59407:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59408:                         $info = $this->installer->ftpInstall($param);
                   59409:                         PEAR::staticPopErrorHandling();
                   59410:                         if (PEAR::isError($info)) {
                   59411:                             $this->ui->outputData($info->getMessage());
                   59412:                             $this->ui->outputData("remote install failed: $label");
                   59413:                         } else {
                   59414:                             $this->ui->outputData("remote install ok: $label");
                   59415:                         }
                   59416:                     }
                   59417:                 }
                   59418:             }
                   59419: 
                   59420:             $deps = $param->getDeps();
                   59421:             if ($deps) {
                   59422:                 if (isset($deps['group'])) {
                   59423:                     $groups = $deps['group'];
                   59424:                     if (!isset($groups[0])) {
                   59425:                         $groups = array($groups);
                   59426:                     }
                   59427: 
                   59428:                     foreach ($groups as $group) {
                   59429:                         if ($group['attribs']['name'] == 'default') {
                   59430:                             // default group is always installed, unless the user
                   59431:                             // explicitly chooses to install another group
                   59432:                             continue;
                   59433:                         }
                   59434:                         $extrainfo[] = $param->getPackage() . ': Optional feature ' .
                   59435:                             $group['attribs']['name'] . ' available (' .
                   59436:                             $group['attribs']['hint'] . ')';
                   59437:                     }
                   59438: 
                   59439:                     $extrainfo[] = $param->getPackage() .
                   59440:                         ': To install optional features use "pear install ' .
                   59441:                         $reg->parsedPackageNameToString(
                   59442:                             array('package' => $param->getPackage(),
                   59443:                                   'channel' => $param->getChannel()), true) .
                   59444:                               '#featurename"';
                   59445:                 }
                   59446:             }
                   59447: 
                   59448:             $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
                   59449:             // $pkg may be NULL if install is a 'fake' install via --packagingroot
                   59450:             if (is_object($pkg)) {
                   59451:                 $pkg->setConfig($this->config);
                   59452:                 if ($list = $pkg->listPostinstallScripts()) {
                   59453:                     $pn = $reg->parsedPackageNameToString(array('channel' =>
                   59454:                        $param->getChannel(), 'package' => $param->getPackage()), true);
                   59455:                     $extrainfo[] = $pn . ' has post-install scripts:';
                   59456:                     foreach ($list as $file) {
                   59457:                         $extrainfo[] = $file;
                   59458:                     }
                   59459:                     $extrainfo[] = $param->getPackage() .
                   59460:                         ': Use "pear run-scripts ' . $pn . '" to finish setup.';
                   59461:                     $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
                   59462:                 }
                   59463:             }
                   59464:         }
                   59465: 
                   59466:         if (count($extrainfo)) {
                   59467:             foreach ($extrainfo as $info) {
                   59468:                 $this->ui->outputData($info);
                   59469:             }
                   59470:         }
                   59471: 
                   59472:         return true;
                   59473:     }
                   59474: 
                   59475:     // }}}
                   59476:     // {{{ doUpgradeAll()
                   59477: 
                   59478:     function doUpgradeAll($command, $options, $params)
                   59479:     {
                   59480:         $reg = &$this->config->getRegistry();
                   59481:         $upgrade = array();
                   59482: 
                   59483:         if (isset($options['channel'])) {
                   59484:             $channels = array($options['channel']);
                   59485:         } else {
                   59486:             $channels = $reg->listChannels();
                   59487:         }
                   59488: 
                   59489:         foreach ($channels as $channel) {
                   59490:             if ($channel == '__uri') {
                   59491:                 continue;
                   59492:             }
                   59493: 
                   59494:             // parse name with channel
                   59495:             foreach ($reg->listPackages($channel) as $name) {
                   59496:                 $upgrade[] = $reg->parsedPackageNameToString(array(
                   59497:                         'channel' => $channel,
                   59498:                         'package' => $name
                   59499:                     ));
                   59500:             }
                   59501:         }
                   59502: 
                   59503:         $err = $this->doInstall($command, $options, $upgrade);
                   59504:         if (PEAR::isError($err)) {
                   59505:             $this->ui->outputData($err->getMessage(), $command);
                   59506:         }
                   59507:    }
                   59508: 
                   59509:     // }}}
                   59510:     // {{{ doUninstall()
                   59511: 
                   59512:     function doUninstall($command, $options, $params)
                   59513:     {
                   59514:         if (count($params) < 1) {
                   59515:             return $this->raiseError("Please supply the package(s) you want to uninstall");
                   59516:         }
                   59517: 
                   59518:         if (empty($this->installer)) {
                   59519:             $this->installer = &$this->getInstaller($this->ui);
                   59520:         }
                   59521: 
                   59522:         if (isset($options['remoteconfig'])) {
                   59523:             $e = $this->config->readFTPConfigFile($options['remoteconfig']);
                   59524:             if (!PEAR::isError($e)) {
                   59525:                 $this->installer->setConfig($this->config);
                   59526:             }
                   59527:         }
                   59528: 
                   59529:         $reg = &$this->config->getRegistry();
                   59530:         $newparams = array();
                   59531:         $binaries = array();
                   59532:         $badparams = array();
                   59533:         foreach ($params as $pkg) {
                   59534:             $channel = $this->config->get('default_channel');
                   59535:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59536:             $parsed = $reg->parsePackageName($pkg, $channel);
                   59537:             PEAR::staticPopErrorHandling();
                   59538:             if (!$parsed || PEAR::isError($parsed)) {
                   59539:                 $badparams[] = $pkg;
                   59540:                 continue;
                   59541:             }
                   59542:             $package = $parsed['package'];
                   59543:             $channel = $parsed['channel'];
                   59544:             $info = &$reg->getPackage($package, $channel);
                   59545:             if ($info === null &&
                   59546:                  ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
                   59547:                 // make sure this isn't a package that has flipped from pear to pecl but
                   59548:                 // used a package.xml 1.0
                   59549:                 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
                   59550:                 $info = &$reg->getPackage($package, $testc);
                   59551:                 if ($info !== null) {
                   59552:                     $channel = $testc;
                   59553:                 }
                   59554:             }
                   59555:             if ($info === null) {
                   59556:                 $badparams[] = $pkg;
                   59557:             } else {
                   59558:                 $newparams[] = &$info;
                   59559:                 // check for binary packages (this is an alias for those packages if so)
                   59560:                 if ($installedbinary = $info->getInstalledBinary()) {
                   59561:                     $this->ui->log('adding binary package ' .
                   59562:                         $reg->parsedPackageNameToString(array('channel' => $channel,
                   59563:                             'package' => $installedbinary), true));
                   59564:                     $newparams[] = &$reg->getPackage($installedbinary, $channel);
                   59565:                 }
                   59566:                 // add the contents of a dependency group to the list of installed packages
                   59567:                 if (isset($parsed['group'])) {
                   59568:                     $group = $info->getDependencyGroup($parsed['group']);
                   59569:                     if ($group) {
                   59570:                         $installed = $reg->getInstalledGroup($group);
                   59571:                         if ($installed) {
                   59572:                             foreach ($installed as $i => $p) {
                   59573:                                 $newparams[] = &$installed[$i];
                   59574:                             }
                   59575:                         }
                   59576:                     }
                   59577:                 }
                   59578:             }
                   59579:         }
                   59580:         $err = $this->installer->sortPackagesForUninstall($newparams);
                   59581:         if (PEAR::isError($err)) {
                   59582:             $this->ui->outputData($err->getMessage(), $command);
                   59583:             return true;
                   59584:         }
                   59585:         $params = $newparams;
                   59586:         // twist this to use it to check on whether dependent packages are also being uninstalled
                   59587:         // for circular dependencies like subpackages
                   59588:         $this->installer->setUninstallPackages($newparams);
                   59589:         $params = array_merge($params, $badparams);
                   59590:         $binaries = array();
                   59591:         foreach ($params as $pkg) {
                   59592:             $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   59593:             if ($err = $this->installer->uninstall($pkg, $options)) {
                   59594:                 $this->installer->popErrorHandling();
                   59595:                 if (PEAR::isError($err)) {
                   59596:                     $this->ui->outputData($err->getMessage(), $command);
                   59597:                     continue;
                   59598:                 }
                   59599:                 if ($pkg->getPackageType() == 'extsrc' ||
                   59600:                       $pkg->getPackageType() == 'extbin' ||
                   59601:                       $pkg->getPackageType() == 'zendextsrc' ||
                   59602:                       $pkg->getPackageType() == 'zendextbin') {
                   59603:                     if ($instbin = $pkg->getInstalledBinary()) {
                   59604:                         continue; // this will be uninstalled later
                   59605:                     }
                   59606: 
                   59607:                     foreach ($pkg->getFilelist() as $name => $atts) {
                   59608:                         $pinfo = pathinfo($atts['installed_as']);
                   59609:                         if (!isset($pinfo['extension']) ||
                   59610:                               in_array($pinfo['extension'], array('c', 'h'))) {
                   59611:                             continue; // make sure we don't match php_blah.h
                   59612:                         }
                   59613:                         if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   59614:                               $pinfo['extension'] == 'dll') ||
                   59615:                               // most unices
                   59616:                               $pinfo['extension'] == 'so' ||
                   59617:                               // hp-ux
                   59618:                               $pinfo['extension'] == 'sl') {
                   59619:                             $binaries[] = array($atts['installed_as'], $pinfo);
                   59620:                             break;
                   59621:                         }
                   59622:                     }
                   59623:                     if (count($binaries)) {
                   59624:                         foreach ($binaries as $pinfo) {
                   59625:                             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59626:                             $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
                   59627:                             PEAR::staticPopErrorHandling();
                   59628:                             if (PEAR::isError($ret)) {
                   59629:                                 $extrainfo[] = $ret->getMessage();
                   59630:                                 if ($pkg->getPackageType() == 'extsrc' ||
                   59631:                                       $pkg->getPackageType() == 'extbin') {
                   59632:                                     $exttype = 'extension';
                   59633:                                 } else {
                   59634:                                     ob_start();
                   59635:                                     phpinfo(INFO_GENERAL);
                   59636:                                     $info = ob_get_contents();
                   59637:                                     ob_end_clean();
                   59638:                                     $debug = function_exists('leak') ? '_debug' : '';
                   59639:                                     $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   59640:                                     $exttype = 'zend_extension' . $debug . $ts;
                   59641:                                 }
                   59642:                                 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
                   59643:                                     $pinfo[1]['basename'] . '" from php.ini', $command);
                   59644:                             } else {
                   59645:                                 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
                   59646:                                     ' disabled in php.ini', $command);
                   59647:                             }
                   59648:                         }
                   59649:                     }
                   59650:                 }
                   59651:                 $savepkg = $pkg;
                   59652:                 if ($this->config->get('verbose') > 0) {
                   59653:                     if (is_object($pkg)) {
                   59654:                         $pkg = $reg->parsedPackageNameToString($pkg);
                   59655:                     }
                   59656:                     $this->ui->outputData("uninstall ok: $pkg", $command);
                   59657:                 }
                   59658:                 if (!isset($options['offline']) && is_object($savepkg) &&
                   59659:                       defined('PEAR_REMOTEINSTALL_OK')) {
                   59660:                     if ($this->config->isDefinedLayer('ftp')) {
                   59661:                         $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   59662:                         $info = $this->installer->ftpUninstall($savepkg);
                   59663:                         $this->installer->popErrorHandling();
                   59664:                         if (PEAR::isError($info)) {
                   59665:                             $this->ui->outputData($info->getMessage());
                   59666:                             $this->ui->outputData("remote uninstall failed: $pkg");
                   59667:                         } else {
                   59668:                             $this->ui->outputData("remote uninstall ok: $pkg");
                   59669:                         }
                   59670:                     }
                   59671:                 }
                   59672:             } else {
                   59673:                 $this->installer->popErrorHandling();
                   59674:                 if (!is_object($pkg)) {
                   59675:                     return $this->raiseError("uninstall failed: $pkg");
                   59676:                 }
                   59677:                 $pkg = $reg->parsedPackageNameToString($pkg);
                   59678:             }
                   59679:         }
                   59680: 
                   59681:         return true;
                   59682:     }
                   59683: 
                   59684:     // }}}
                   59685: 
                   59686: 
                   59687:     // }}}
                   59688:     // {{{ doBundle()
                   59689:     /*
                   59690:     (cox) It just downloads and untars the package, does not do
                   59691:             any check that the PEAR_Installer::_installFile() does.
                   59692:     */
                   59693: 
                   59694:     function doBundle($command, $options, $params)
                   59695:     {
                   59696:         $opts = array(
                   59697:             'force'        => true,
                   59698:             'nodeps'       => true,
                   59699:             'soft'         => true,
                   59700:             'downloadonly' => true
                   59701:         );
                   59702:         $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
                   59703:         $reg = &$this->config->getRegistry();
                   59704:         if (count($params) < 1) {
                   59705:             return $this->raiseError("Please supply the package you want to bundle");
                   59706:         }
                   59707: 
                   59708:         if (isset($options['destination'])) {
                   59709:             if (!is_dir($options['destination'])) {
                   59710:                 System::mkdir('-p ' . $options['destination']);
                   59711:             }
                   59712:             $dest = realpath($options['destination']);
                   59713:         } else {
                   59714:             $pwd  = getcwd();
                   59715:             $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
                   59716:             $dest = is_dir($dir) ? $dir : $pwd;
                   59717:         }
                   59718:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59719:         $err = $downloader->setDownloadDir($dest);
                   59720:         PEAR::staticPopErrorHandling();
                   59721:         if (PEAR::isError($err)) {
                   59722:             return PEAR::raiseError('download directory "' . $dest .
                   59723:                 '" is not writeable.');
                   59724:         }
                   59725:         $result = &$downloader->download(array($params[0]));
                   59726:         if (PEAR::isError($result)) {
                   59727:             return $result;
                   59728:         }
                   59729:         if (!isset($result[0])) {
                   59730:             return $this->raiseError('unable to unpack ' . $params[0]);
                   59731:         }
                   59732:         $pkgfile = &$result[0]->getPackageFile();
                   59733:         $pkgname = $pkgfile->getName();
                   59734:         $pkgversion = $pkgfile->getVersion();
                   59735: 
                   59736:         // Unpacking -------------------------------------------------
                   59737:         $dest .= DIRECTORY_SEPARATOR . $pkgname;
                   59738:         $orig = $pkgname . '-' . $pkgversion;
                   59739: 
                   59740:         $tar = &new Archive_Tar($pkgfile->getArchiveFile());
                   59741:         if (!$tar->extractModify($dest, $orig)) {
                   59742:             return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
                   59743:         }
                   59744:         $this->ui->outputData("Package ready at '$dest'");
                   59745:     // }}}
                   59746:     }
                   59747: 
                   59748:     // }}}
                   59749: 
                   59750:     function doRunScripts($command, $options, $params)
                   59751:     {
                   59752:         if (!isset($params[0])) {
                   59753:             return $this->raiseError('run-scripts expects 1 parameter: a package name');
                   59754:         }
                   59755: 
                   59756:         $reg = &$this->config->getRegistry();
                   59757:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59758:         $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   59759:         PEAR::staticPopErrorHandling();
                   59760:         if (PEAR::isError($parsed)) {
                   59761:             return $this->raiseError($parsed);
                   59762:         }
                   59763: 
                   59764:         $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
                   59765:         if (!is_object($package)) {
                   59766:             return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
                   59767:         }
                   59768: 
                   59769:         $package->setConfig($this->config);
                   59770:         $package->runPostinstallScripts();
                   59771:         $this->ui->outputData('Install scripts complete', $command);
                   59772:         return true;
                   59773:     }
                   59774: 
                   59775:     /**
                   59776:      * Given a list of packages, filter out those ones that are already up to date
                   59777:      *
                   59778:      * @param $packages: packages, in parsed array format !
                   59779:      * @return list of packages that can be upgraded
                   59780:      */
                   59781:     function _filterUptodatePackages($packages, $command)
                   59782:     {
                   59783:         $reg = &$this->config->getRegistry();
                   59784:         $latestReleases = array();
                   59785: 
                   59786:         $ret = array();
                   59787:         foreach ($packages as $package) {
                   59788:             if (isset($package['group'])) {
                   59789:                 $ret[] = $package;
                   59790:                 continue;
                   59791:             }
                   59792: 
                   59793:             $channel = $package['channel'];
                   59794:             $name    = $package['package'];
                   59795:             if (!$reg->packageExists($name, $channel)) {
                   59796:                 $ret[] = $package;
                   59797:                 continue;
                   59798:             }
                   59799: 
                   59800:             if (!isset($latestReleases[$channel])) {
                   59801:                 // fill in cache for this channel
                   59802:                 $chan = &$reg->getChannel($channel);
                   59803:                 if (PEAR::isError($chan)) {
                   59804:                     return $this->raiseError($chan);
                   59805:                 }
                   59806: 
                   59807:                 $base2 = false;
                   59808:                 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
                   59809:                 if ($chan->supportsREST($preferred_mirror) &&
                   59810:                     (
                   59811:                        //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                   59812:                        ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   59813:                     )
                   59814:                 ) {
                   59815:                     $dorest = true;
                   59816:                 }
                   59817: 
                   59818:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   59819:                 if (!isset($package['state'])) {
                   59820:                     $state = $this->config->get('preferred_state', null, $channel);
                   59821:                 } else {
                   59822:                     $state = $package['state'];
                   59823:                 }
                   59824: 
                   59825:                 if ($dorest) {
                   59826:                     if ($base2) {
                   59827:                         $rest = &$this->config->getREST('1.4', array());
                   59828:                         $base = $base2;
                   59829:                     } else {
                   59830:                         $rest = &$this->config->getREST('1.0', array());
                   59831:                     }
                   59832: 
                   59833:                     $installed = array_flip($reg->listPackages($channel));
                   59834:                     $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
                   59835:                 }
                   59836: 
                   59837:                 PEAR::staticPopErrorHandling();
                   59838:                 if (PEAR::isError($latest)) {
                   59839:                     $this->ui->outputData('Error getting channel info from ' . $channel .
                   59840:                         ': ' . $latest->getMessage());
                   59841:                     continue;
                   59842:                 }
                   59843: 
                   59844:                 $latestReleases[$channel] = array_change_key_case($latest);
                   59845:             }
                   59846: 
                   59847:             // check package for latest release
                   59848:             $name_lower = strtolower($name);
                   59849:             if (isset($latestReleases[$channel][$name_lower])) {
                   59850:                 // if not set, up to date
                   59851:                 $inst_version    = $reg->packageInfo($name, 'version', $channel);
                   59852:                 $channel_version = $latestReleases[$channel][$name_lower]['version'];
                   59853:                 if (version_compare($channel_version, $inst_version, 'le')) {
                   59854:                     // installed version is up-to-date
                   59855:                     continue;
                   59856:                 }
                   59857: 
                   59858:                 // maintain BC
                   59859:                 if ($command == 'upgrade-all') {
                   59860:                     $this->ui->outputData(array('data' => 'Will upgrade ' .
                   59861:                         $reg->parsedPackageNameToString($package)), $command);
                   59862:                 }
                   59863:                 $ret[] = $package;
                   59864:             }
                   59865:         }
                   59866: 
                   59867:         return $ret;
                   59868:     }
                   59869: }<commands version="1.0">
                   59870:  <install>
                   59871:   <summary>Install Package</summary>
                   59872:   <function>doInstall</function>
                   59873:   <shortcut>i</shortcut>
                   59874:   <options>
                   59875:    <force>
                   59876:     <shortopt>f</shortopt>
                   59877:     <doc>will overwrite newer installed packages</doc>
                   59878:    </force>
                   59879:    <loose>
                   59880:     <shortopt>l</shortopt>
                   59881:     <doc>do not check for recommended dependency version</doc>
                   59882:    </loose>
                   59883:    <nodeps>
                   59884:     <shortopt>n</shortopt>
                   59885:     <doc>ignore dependencies, install anyway</doc>
                   59886:    </nodeps>
                   59887:    <register-only>
                   59888:     <shortopt>r</shortopt>
                   59889:     <doc>do not install files, only register the package as installed</doc>
                   59890:    </register-only>
                   59891:    <soft>
                   59892:     <shortopt>s</shortopt>
                   59893:     <doc>soft install, fail silently, or upgrade if already installed</doc>
                   59894:    </soft>
                   59895:    <nobuild>
                   59896:     <shortopt>B</shortopt>
                   59897:     <doc>don&#039;t build C extensions</doc>
                   59898:    </nobuild>
                   59899:    <nocompress>
                   59900:     <shortopt>Z</shortopt>
                   59901:     <doc>request uncompressed files when downloading</doc>
                   59902:    </nocompress>
                   59903:    <installroot>
                   59904:     <shortopt>R</shortopt>
                   59905:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   59906:     <arg>DIR</arg>
                   59907:    </installroot>
                   59908:    <packagingroot>
                   59909:     <shortopt>P</shortopt>
                   59910:     <doc>root directory used when packaging files, like RPM packaging</doc>
                   59911:     <arg>DIR</arg>
                   59912:    </packagingroot>
                   59913:    <ignore-errors>
                   59914:     <shortopt></shortopt>
                   59915:     <doc>force install even if there were errors</doc>
                   59916:    </ignore-errors>
                   59917:    <alldeps>
                   59918:     <shortopt>a</shortopt>
                   59919:     <doc>install all required and optional dependencies</doc>
                   59920:    </alldeps>
                   59921:    <onlyreqdeps>
                   59922:     <shortopt>o</shortopt>
                   59923:     <doc>install all required dependencies</doc>
                   59924:    </onlyreqdeps>
                   59925:    <offline>
                   59926:     <shortopt>O</shortopt>
                   59927:     <doc>do not attempt to download any urls or contact channels</doc>
                   59928:    </offline>
                   59929:    <pretend>
                   59930:     <shortopt>p</shortopt>
                   59931:     <doc>Only list the packages that would be downloaded</doc>
                   59932:    </pretend>
                   59933:   </options>
                   59934:   <doc>[channel/]&lt;package&gt; ...
                   59935: Installs one or more PEAR packages.  You can specify a package to
                   59936: install in four ways:
                   59937: 
                   59938: &quot;Package-1.0.tgz&quot; : installs from a local file
                   59939: 
                   59940: &quot;http://example.com/Package-1.0.tgz&quot; : installs from
                   59941: anywhere on the net.
                   59942: 
                   59943: &quot;package.xml&quot; : installs the package described in
                   59944: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   59945: another package manager such as RPM.
                   59946: 
                   59947: &quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
                   59948: ({config master_server}) and downloads the newest package with
                   59949: the preferred quality/state ({config preferred_state}).
                   59950: 
                   59951: To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
                   59952: Package state beta, use &quot;Package-beta.&quot;  To retrieve an uncompressed
                   59953: file, append .tar (make sure there is no file by the same name first)
                   59954: 
                   59955: To download a package from another channel, prefix with the channel name like
                   59956: &quot;channel/Package&quot;
                   59957: 
                   59958: More than one package may be specified at once.  It is ok to mix these
                   59959: four ways of specifying packages.
                   59960: </doc>
                   59961:  </install>
                   59962:  <upgrade>
                   59963:   <summary>Upgrade Package</summary>
                   59964:   <function>doInstall</function>
                   59965:   <shortcut>up</shortcut>
                   59966:   <options>
                   59967:    <channel>
                   59968:     <shortopt>c</shortopt>
                   59969:     <doc>upgrade packages from a specific channel</doc>
                   59970:     <arg>CHAN</arg>
                   59971:    </channel>
                   59972:    <force>
                   59973:     <shortopt>f</shortopt>
                   59974:     <doc>overwrite newer installed packages</doc>
                   59975:    </force>
                   59976:    <loose>
                   59977:     <shortopt>l</shortopt>
                   59978:     <doc>do not check for recommended dependency version</doc>
                   59979:    </loose>
                   59980:    <nodeps>
                   59981:     <shortopt>n</shortopt>
                   59982:     <doc>ignore dependencies, upgrade anyway</doc>
                   59983:    </nodeps>
                   59984:    <register-only>
                   59985:     <shortopt>r</shortopt>
                   59986:     <doc>do not install files, only register the package as upgraded</doc>
                   59987:    </register-only>
                   59988:    <nobuild>
                   59989:     <shortopt>B</shortopt>
                   59990:     <doc>don&#039;t build C extensions</doc>
                   59991:    </nobuild>
                   59992:    <nocompress>
                   59993:     <shortopt>Z</shortopt>
                   59994:     <doc>request uncompressed files when downloading</doc>
                   59995:    </nocompress>
                   59996:    <installroot>
                   59997:     <shortopt>R</shortopt>
                   59998:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   59999:     <arg>DIR</arg>
                   60000:    </installroot>
                   60001:    <ignore-errors>
                   60002:     <shortopt></shortopt>
                   60003:     <doc>force install even if there were errors</doc>
                   60004:    </ignore-errors>
                   60005:    <alldeps>
                   60006:     <shortopt>a</shortopt>
                   60007:     <doc>install all required and optional dependencies</doc>
                   60008:    </alldeps>
                   60009:    <onlyreqdeps>
                   60010:     <shortopt>o</shortopt>
                   60011:     <doc>install all required dependencies</doc>
                   60012:    </onlyreqdeps>
                   60013:    <offline>
                   60014:     <shortopt>O</shortopt>
                   60015:     <doc>do not attempt to download any urls or contact channels</doc>
                   60016:    </offline>
                   60017:    <pretend>
                   60018:     <shortopt>p</shortopt>
                   60019:     <doc>Only list the packages that would be downloaded</doc>
                   60020:    </pretend>
                   60021:   </options>
                   60022:   <doc>&lt;package&gt; ...
                   60023: Upgrades one or more PEAR packages.  See documentation for the
                   60024: &quot;install&quot; command for ways to specify a package.
                   60025: 
                   60026: When upgrading, your package will be updated if the provided new
                   60027: package has a higher version number (use the -f option if you need to
                   60028: upgrade anyway).
                   60029: 
                   60030: More than one package may be specified at once.
                   60031: </doc>
                   60032:  </upgrade>
                   60033:  <upgrade-all>
                   60034:   <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
                   60035:   <function>doUpgradeAll</function>
                   60036:   <shortcut>ua</shortcut>
                   60037:   <options>
                   60038:    <channel>
                   60039:     <shortopt>c</shortopt>
                   60040:     <doc>upgrade packages from a specific channel</doc>
                   60041:     <arg>CHAN</arg>
                   60042:    </channel>
                   60043:    <nodeps>
                   60044:     <shortopt>n</shortopt>
                   60045:     <doc>ignore dependencies, upgrade anyway</doc>
                   60046:    </nodeps>
                   60047:    <register-only>
                   60048:     <shortopt>r</shortopt>
                   60049:     <doc>do not install files, only register the package as upgraded</doc>
                   60050:    </register-only>
                   60051:    <nobuild>
                   60052:     <shortopt>B</shortopt>
                   60053:     <doc>don&#039;t build C extensions</doc>
                   60054:    </nobuild>
                   60055:    <nocompress>
                   60056:     <shortopt>Z</shortopt>
                   60057:     <doc>request uncompressed files when downloading</doc>
                   60058:    </nocompress>
                   60059:    <installroot>
                   60060:     <shortopt>R</shortopt>
                   60061:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   60062:     <arg>DIR</arg>
                   60063:    </installroot>
                   60064:    <ignore-errors>
                   60065:     <shortopt></shortopt>
                   60066:     <doc>force install even if there were errors</doc>
                   60067:    </ignore-errors>
                   60068:    <loose>
                   60069:     <shortopt></shortopt>
                   60070:     <doc>do not check for recommended dependency version</doc>
                   60071:    </loose>
                   60072:   </options>
                   60073:   <doc>
                   60074: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   60075: 
                   60076: Upgrades all packages that have a newer release available.  Upgrades are
                   60077: done only if there is a release available of the state specified in
                   60078: &quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
                   60079: more stable.
                   60080: </doc>
                   60081:  </upgrade-all>
                   60082:  <uninstall>
                   60083:   <summary>Un-install Package</summary>
                   60084:   <function>doUninstall</function>
                   60085:   <shortcut>un</shortcut>
                   60086:   <options>
                   60087:    <nodeps>
                   60088:     <shortopt>n</shortopt>
                   60089:     <doc>ignore dependencies, uninstall anyway</doc>
                   60090:    </nodeps>
                   60091:    <register-only>
                   60092:     <shortopt>r</shortopt>
                   60093:     <doc>do not remove files, only register the packages as not installed</doc>
                   60094:    </register-only>
                   60095:    <installroot>
                   60096:     <shortopt>R</shortopt>
                   60097:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   60098:     <arg>DIR</arg>
                   60099:    </installroot>
                   60100:    <ignore-errors>
                   60101:     <shortopt></shortopt>
                   60102:     <doc>force install even if there were errors</doc>
                   60103:    </ignore-errors>
                   60104:    <offline>
                   60105:     <shortopt>O</shortopt>
                   60106:     <doc>do not attempt to uninstall remotely</doc>
                   60107:    </offline>
                   60108:   </options>
                   60109:   <doc>[channel/]&lt;package&gt; ...
                   60110: Uninstalls one or more PEAR packages.  More than one package may be
                   60111: specified at once.  Prefix with channel name to uninstall from a
                   60112: channel not in your default channel ({config default_channel})
                   60113: </doc>
                   60114:  </uninstall>
                   60115:  <bundle>
                   60116:   <summary>Unpacks a Pecl Package</summary>
                   60117:   <function>doBundle</function>
                   60118:   <shortcut>bun</shortcut>
                   60119:   <options>
                   60120:    <destination>
                   60121:     <shortopt>d</shortopt>
                   60122:     <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
                   60123:     <arg>DIR</arg>
                   60124:    </destination>
                   60125:    <force>
                   60126:     <shortopt>f</shortopt>
                   60127:     <doc>Force the unpacking even if there were errors in the package</doc>
                   60128:    </force>
                   60129:   </options>
                   60130:   <doc>&lt;package&gt;
                   60131: Unpacks a Pecl Package into the selected location. It will download the
                   60132: package if needed.
                   60133: </doc>
                   60134:  </bundle>
                   60135:  <run-scripts>
                   60136:   <summary>Run Post-Install Scripts bundled with a package</summary>
                   60137:   <function>doRunScripts</function>
                   60138:   <shortcut>rs</shortcut>
                   60139:   <options />
                   60140:   <doc>&lt;package&gt;
                   60141: Run post-installation scripts in package &lt;package&gt;, if any exist.
                   60142: </doc>
                   60143:  </run-scripts>
                   60144: </commands><?php
                   60145: /**
                   60146:  * PEAR_Common, the base class for the PEAR Installer
                   60147:  *
                   60148:  * PHP versions 4 and 5
                   60149:  *
                   60150:  * @category   pear
                   60151:  * @package    PEAR
                   60152:  * @author     Stig Bakken <ssb@php.net>
                   60153:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   60154:  * @author     Greg Beaver <cellog@php.net>
                   60155:  * @copyright  1997-2009 The Authors
                   60156:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   60157:  * @version    CVS: $Id: Common.php 282969 2009-06-28 23:09:27Z dufuz $
                   60158:  * @link       http://pear.php.net/package/PEAR
                   60159:  * @since      File available since Release 0.1.0
                   60160:  * @deprecated File deprecated since Release 1.4.0a1
                   60161:  */
                   60162: 
                   60163: /**
                   60164:  * Include error handling
                   60165:  */
                   60166: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   60167: 
                   60168: /**
                   60169:  * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
                   60170:  */
                   60171: define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
                   60172: define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
                   60173: define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
                   60174: 
                   60175: // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
                   60176: define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
                   60177: define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
                   60178: 
                   60179: // XXX far from perfect :-)
                   60180: define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
                   60181:     ')(-([.0-9a-zA-Z]+))?');
                   60182: define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
                   60183:     '\\z/');
                   60184: 
                   60185: define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
                   60186: define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
                   60187: 
                   60188: // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
                   60189: define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
                   60190: define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
                   60191: 
                   60192: define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
                   60193:          . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
                   60194: define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
                   60195: 
                   60196: define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
                   60197:     . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
                   60198: define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
                   60199: 
                   60200: /**
                   60201:  * List of temporary files and directories registered by
                   60202:  * PEAR_Common::addTempFile().
                   60203:  * @var array
                   60204:  */
                   60205: $GLOBALS['_PEAR_Common_tempfiles'] = array();
                   60206: 
                   60207: /**
                   60208:  * Valid maintainer roles
                   60209:  * @var array
                   60210:  */
                   60211: $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
                   60212: 
                   60213: /**
                   60214:  * Valid release states
                   60215:  * @var array
                   60216:  */
                   60217: $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
                   60218: 
                   60219: /**
                   60220:  * Valid dependency types
                   60221:  * @var array
                   60222:  */
                   60223: $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
                   60224: 
                   60225: /**
                   60226:  * Valid dependency relations
                   60227:  * @var array
                   60228:  */
                   60229: $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
                   60230: 
                   60231: /**
                   60232:  * Valid file roles
                   60233:  * @var array
                   60234:  */
                   60235: $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
                   60236: 
                   60237: /**
                   60238:  * Valid replacement types
                   60239:  * @var array
                   60240:  */
                   60241: $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
                   60242: 
                   60243: /**
                   60244:  * Valid "provide" types
                   60245:  * @var array
                   60246:  */
                   60247: $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
                   60248: 
                   60249: /**
                   60250:  * Valid "provide" types
                   60251:  * @var array
                   60252:  */
                   60253: $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');
                   60254: 
                   60255: /**
                   60256:  * Class providing common functionality for PEAR administration classes.
                   60257:  * @category   pear
                   60258:  * @package    PEAR
                   60259:  * @author     Stig Bakken <ssb@php.net>
                   60260:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   60261:  * @author     Greg Beaver <cellog@php.net>
                   60262:  * @copyright  1997-2009 The Authors
                   60263:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   60264:  * @version    Release: 1.10.0beta1
                   60265:  * @link       http://pear.php.net/package/PEAR
                   60266:  * @since      Class available since Release 1.4.0a1
                   60267:  * @deprecated This class will disappear, and its components will be spread
                   60268:  *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
                   60269:  */
                   60270: class PEAR_Common extends PEAR
                   60271: {
                   60272:     /**
                   60273:      * User Interface object (PEAR_Frontend_* class).  If null,
                   60274:      * the log() method uses print.
                   60275:      * @var object
                   60276:      */
                   60277:     var $ui = null;
                   60278: 
                   60279:     /**
                   60280:      * Configuration object (PEAR_Config).
                   60281:      * @var PEAR_Config
                   60282:      */
                   60283:     var $config = null;
                   60284: 
                   60285:     /** stack of elements, gives some sort of XML context */
                   60286:     var $element_stack = array();
                   60287: 
                   60288:     /** name of currently parsed XML element */
                   60289:     var $current_element;
                   60290: 
                   60291:     /** array of attributes of the currently parsed XML element */
                   60292:     var $current_attributes = array();
                   60293: 
                   60294:     /** assoc with information about a package */
                   60295:     var $pkginfo = array();
                   60296: 
                   60297:     var $current_path = null;
                   60298: 
                   60299:     /**
                   60300:      * Flag variable used to mark a valid package file
                   60301:      * @var boolean
                   60302:      * @access private
                   60303:      */
                   60304:     var $_validPackageFile;
                   60305: 
                   60306:     /**
                   60307:      * PEAR_Common constructor
                   60308:      *
                   60309:      * @access public
                   60310:      */
                   60311:     function PEAR_Common()
                   60312:     {
                   60313:         parent::PEAR();
                   60314:         $this->config = &PEAR_Config::singleton();
                   60315:         $this->debug = $this->config->get('verbose');
                   60316:     }
                   60317: 
                   60318:     /**
                   60319:      * PEAR_Common destructor
                   60320:      *
                   60321:      * @access private
                   60322:      */
                   60323:     function _PEAR_Common()
                   60324:     {
                   60325:         // doesn't work due to bug #14744
                   60326:         //$tempfiles = $this->_tempfiles;
                   60327:         $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
                   60328:         while ($file = array_shift($tempfiles)) {
                   60329:             if (@is_dir($file)) {
                   60330:                 if (!class_exists('System')) {
                   60331:                     require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   60332:                 }
                   60333: 
                   60334:                 System::rm(array('-rf', $file));
                   60335:             } elseif (file_exists($file)) {
                   60336:                 unlink($file);
                   60337:             }
                   60338:         }
                   60339:     }
                   60340: 
                   60341:     /**
                   60342:      * Register a temporary file or directory.  When the destructor is
                   60343:      * executed, all registered temporary files and directories are
                   60344:      * removed.
                   60345:      *
                   60346:      * @param string  $file  name of file or directory
                   60347:      *
                   60348:      * @return void
                   60349:      *
                   60350:      * @access public
                   60351:      */
                   60352:     function addTempFile($file)
                   60353:     {
                   60354:         if (!class_exists('PEAR_Frontend')) {
                   60355:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
                   60356:         }
                   60357:         PEAR_Frontend::addTempFile($file);
                   60358:     }
                   60359: 
                   60360:     /**
                   60361:      * Wrapper to System::mkDir(), creates a directory as well as
                   60362:      * any necessary parent directories.
                   60363:      *
                   60364:      * @param string  $dir  directory name
                   60365:      *
                   60366:      * @return bool TRUE on success, or a PEAR error
                   60367:      *
                   60368:      * @access public
                   60369:      */
                   60370:     function mkDirHier($dir)
                   60371:     {
                   60372:         // Only used in Installer - move it there ?
                   60373:         $this->log(2, "+ create dir $dir");
                   60374:         if (!class_exists('System')) {
                   60375:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   60376:         }
                   60377:         return System::mkDir(array('-p', $dir));
                   60378:     }
                   60379: 
                   60380:     /**
                   60381:      * Logging method.
                   60382:      *
                   60383:      * @param int    $level  log level (0 is quiet, higher is noisier)
                   60384:      * @param string $msg    message to write to the log
                   60385:      *
                   60386:      * @return void
                   60387:      *
                   60388:      * @access public
                   60389:      * @static
                   60390:      */
                   60391:     function log($level, $msg, $append_crlf = true)
                   60392:     {
                   60393:         if ($this->debug >= $level) {
                   60394:             if (!class_exists('PEAR_Frontend')) {
                   60395:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
                   60396:             }
                   60397: 
                   60398:             $ui = &PEAR_Frontend::singleton();
                   60399:             if (is_a($ui, 'PEAR_Frontend')) {
                   60400:                 $ui->log($msg, $append_crlf);
                   60401:             } else {
                   60402:                 print "$msg\n";
                   60403:             }
                   60404:         }
                   60405:     }
                   60406: 
                   60407:     /**
                   60408:      * Create and register a temporary directory.
                   60409:      *
                   60410:      * @param string $tmpdir (optional) Directory to use as tmpdir.
                   60411:      *                       Will use system defaults (for example
                   60412:      *                       /tmp or c:\windows\temp) if not specified
                   60413:      *
                   60414:      * @return string name of created directory
                   60415:      *
                   60416:      * @access public
                   60417:      */
                   60418:     function mkTempDir($tmpdir = '')
                   60419:     {
                   60420:         $topt = $tmpdir ? array('-t', $tmpdir) : array();
                   60421:         $topt = array_merge($topt, array('-d', 'pear'));
                   60422:         if (!class_exists('System')) {
                   60423:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   60424:         }
                   60425: 
                   60426:         if (!$tmpdir = System::mktemp($topt)) {
                   60427:             return false;
                   60428:         }
                   60429: 
                   60430:         $this->addTempFile($tmpdir);
                   60431:         return $tmpdir;
                   60432:     }
                   60433: 
                   60434:     /**
                   60435:      * Set object that represents the frontend to be used.
                   60436:      *
                   60437:      * @param  object Reference of the frontend object
                   60438:      * @return void
                   60439:      * @access public
                   60440:      */
                   60441:     function setFrontendObject(&$ui)
                   60442:     {
                   60443:         $this->ui = &$ui;
                   60444:     }
                   60445: 
                   60446:     /**
                   60447:      * Return an array containing all of the states that are more stable than
                   60448:      * or equal to the passed in state
                   60449:      *
                   60450:      * @param string Release state
                   60451:      * @param boolean Determines whether to include $state in the list
                   60452:      * @return false|array False if $state is not a valid release state
                   60453:      */
                   60454:     function betterStates($state, $include = false)
                   60455:     {
                   60456:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   60457:         $i = array_search($state, $states);
                   60458:         if ($i === false) {
                   60459:             return false;
                   60460:         }
                   60461:         if ($include) {
                   60462:             $i--;
                   60463:         }
                   60464:         return array_slice($states, $i + 1);
                   60465:     }
                   60466: 
                   60467:     /**
                   60468:      * Get the valid roles for a PEAR package maintainer
                   60469:      *
                   60470:      * @return array
                   60471:      * @static
                   60472:      */
                   60473:     function getUserRoles()
                   60474:     {
                   60475:         return $GLOBALS['_PEAR_Common_maintainer_roles'];
                   60476:     }
                   60477: 
                   60478:     /**
                   60479:      * Get the valid package release states of packages
                   60480:      *
                   60481:      * @return array
                   60482:      * @static
                   60483:      */
                   60484:     function getReleaseStates()
                   60485:     {
                   60486:         return $GLOBALS['_PEAR_Common_release_states'];
                   60487:     }
                   60488: 
                   60489:     /**
                   60490:      * Get the implemented dependency types (php, ext, pkg etc.)
                   60491:      *
                   60492:      * @return array
                   60493:      * @static
                   60494:      */
                   60495:     function getDependencyTypes()
                   60496:     {
                   60497:         return $GLOBALS['_PEAR_Common_dependency_types'];
                   60498:     }
                   60499: 
                   60500:     /**
                   60501:      * Get the implemented dependency relations (has, lt, ge etc.)
                   60502:      *
                   60503:      * @return array
                   60504:      * @static
                   60505:      */
                   60506:     function getDependencyRelations()
                   60507:     {
                   60508:         return $GLOBALS['_PEAR_Common_dependency_relations'];
                   60509:     }
                   60510: 
                   60511:     /**
                   60512:      * Get the implemented file roles
                   60513:      *
                   60514:      * @return array
                   60515:      * @static
                   60516:      */
                   60517:     function getFileRoles()
                   60518:     {
                   60519:         return $GLOBALS['_PEAR_Common_file_roles'];
                   60520:     }
                   60521: 
                   60522:     /**
                   60523:      * Get the implemented file replacement types in
                   60524:      *
                   60525:      * @return array
                   60526:      * @static
                   60527:      */
                   60528:     function getReplacementTypes()
                   60529:     {
                   60530:         return $GLOBALS['_PEAR_Common_replacement_types'];
                   60531:     }
                   60532: 
                   60533:     /**
                   60534:      * Get the implemented file replacement types in
                   60535:      *
                   60536:      * @return array
                   60537:      * @static
                   60538:      */
                   60539:     function getProvideTypes()
                   60540:     {
                   60541:         return $GLOBALS['_PEAR_Common_provide_types'];
                   60542:     }
                   60543: 
                   60544:     /**
                   60545:      * Get the implemented file replacement types in
                   60546:      *
                   60547:      * @return array
                   60548:      * @static
                   60549:      */
                   60550:     function getScriptPhases()
                   60551:     {
                   60552:         return $GLOBALS['_PEAR_Common_script_phases'];
                   60553:     }
                   60554: 
                   60555:     /**
                   60556:      * Test whether a string contains a valid package name.
                   60557:      *
                   60558:      * @param string $name the package name to test
                   60559:      *
                   60560:      * @return bool
                   60561:      *
                   60562:      * @access public
                   60563:      */
                   60564:     function validPackageName($name)
                   60565:     {
                   60566:         return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
                   60567:     }
                   60568: 
                   60569:     /**
                   60570:      * Test whether a string contains a valid package version.
                   60571:      *
                   60572:      * @param string $ver the package version to test
                   60573:      *
                   60574:      * @return bool
                   60575:      *
                   60576:      * @access public
                   60577:      */
                   60578:     function validPackageVersion($ver)
                   60579:     {
                   60580:         return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   60581:     }
                   60582: 
                   60583:     /**
                   60584:      * @param string $path relative or absolute include path
                   60585:      * @return boolean
                   60586:      * @static
                   60587:      */
                   60588:     function isIncludeable($path)
                   60589:     {
                   60590:         if (file_exists($path) && is_readable($path)) {
                   60591:             return true;
                   60592:         }
                   60593: 
                   60594:         $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
                   60595:         foreach ($ipath as $include) {
                   60596:             $test = realpath($include . DIRECTORY_SEPARATOR . $path);
                   60597:             if (file_exists($test) && is_readable($test)) {
                   60598:                 return true;
                   60599:             }
                   60600:         }
                   60601: 
                   60602:         return false;
                   60603:     }
                   60604: 
                   60605:     function _postProcessChecks($pf)
                   60606:     {
                   60607:         if (!PEAR::isError($pf)) {
                   60608:             return $this->_postProcessValidPackagexml($pf);
                   60609:         }
                   60610: 
                   60611:         $errs = $pf->getUserinfo();
                   60612:         if (is_array($errs)) {
                   60613:             foreach ($errs as $error) {
                   60614:                 $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   60615:             }
                   60616:         }
                   60617: 
                   60618:         return $pf;
                   60619:     }
                   60620: 
                   60621:     /**
                   60622:      * Returns information about a package file.  Expects the name of
                   60623:      * a gzipped tar file as input.
                   60624:      *
                   60625:      * @param string  $file  name of .tgz file
                   60626:      *
                   60627:      * @return array  array with package information
                   60628:      *
                   60629:      * @access public
                   60630:      * @deprecated use PEAR_PackageFile->fromTgzFile() instead
                   60631:      *
                   60632:      */
                   60633:     function infoFromTgzFile($file)
                   60634:     {
                   60635:         $packagefile = &new PEAR_PackageFile($this->config);
                   60636:         $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
                   60637:         return $this->_postProcessChecks($pf);
                   60638:     }
                   60639: 
                   60640:     /**
                   60641:      * Returns information about a package file.  Expects the name of
                   60642:      * a package xml file as input.
                   60643:      *
                   60644:      * @param string  $descfile  name of package xml file
                   60645:      *
                   60646:      * @return array  array with package information
                   60647:      *
                   60648:      * @access public
                   60649:      * @deprecated use PEAR_PackageFile->fromPackageFile() instead
                   60650:      *
                   60651:      */
                   60652:     function infoFromDescriptionFile($descfile)
                   60653:     {
                   60654:         $packagefile = &new PEAR_PackageFile($this->config);
                   60655:         $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   60656:         return $this->_postProcessChecks($pf);
                   60657:     }
                   60658: 
                   60659:     /**
                   60660:      * Returns information about a package file.  Expects the contents
                   60661:      * of a package xml file as input.
                   60662:      *
                   60663:      * @param string  $data  contents of package.xml file
                   60664:      *
                   60665:      * @return array   array with package information
                   60666:      *
                   60667:      * @access public
                   60668:      * @deprecated use PEAR_PackageFile->fromXmlstring() instead
                   60669:      *
                   60670:      */
                   60671:     function infoFromString($data)
                   60672:     {
                   60673:         $packagefile = &new PEAR_PackageFile($this->config);
                   60674:         $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
                   60675:         return $this->_postProcessChecks($pf);
                   60676:     }
                   60677: 
                   60678:     /**
                   60679:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   60680:      * @return array
                   60681:      */
                   60682:     function _postProcessValidPackagexml(&$pf)
                   60683:     {
                   60684:         if (!is_a($pf, 'PEAR_PackageFile_v2')) {
                   60685:             $this->pkginfo = $pf->toArray();
                   60686:             return $this->pkginfo;
                   60687:         }
                   60688: 
                   60689:         // sort of make this into a package.xml 1.0-style array
                   60690:         // changelog is not converted to old format.
                   60691:         $arr = $pf->toArray(true);
                   60692:         $arr = array_merge($arr, $arr['old']);
                   60693:         unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
                   60694:               $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
                   60695:               $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
                   60696:               $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
                   60697:               $arr['helper'], $arr['contributor']);
                   60698:         $arr['filelist'] = $pf->getFilelist();
                   60699:         $this->pkginfo = $arr;
                   60700:         return $arr;
                   60701:     }
                   60702: 
                   60703:     /**
                   60704:      * Returns package information from different sources
                   60705:      *
                   60706:      * This method is able to extract information about a package
                   60707:      * from a .tgz archive or from a XML package definition file.
                   60708:      *
                   60709:      * @access public
                   60710:      * @param  string Filename of the source ('package.xml', '<package>.tgz')
                   60711:      * @return string
                   60712:      * @deprecated use PEAR_PackageFile->fromAnyFile() instead
                   60713:      */
                   60714:     function infoFromAny($info)
                   60715:     {
                   60716:         if (is_string($info) && file_exists($info)) {
                   60717:             $packagefile = &new PEAR_PackageFile($this->config);
                   60718:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   60719:             if (PEAR::isError($pf)) {
                   60720:                 $errs = $pf->getUserinfo();
                   60721:                 if (is_array($errs)) {
                   60722:                     foreach ($errs as $error) {
                   60723:                         $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   60724:                     }
                   60725:                 }
                   60726: 
                   60727:                 return $pf;
                   60728:             }
                   60729: 
                   60730:             return $this->_postProcessValidPackagexml($pf);
                   60731:         }
                   60732: 
                   60733:         return $info;
                   60734:     }
                   60735: 
                   60736:     /**
                   60737:      * Return an XML document based on the package info (as returned
                   60738:      * by the PEAR_Common::infoFrom* methods).
                   60739:      *
                   60740:      * @param array  $pkginfo  package info
                   60741:      *
                   60742:      * @return string XML data
                   60743:      *
                   60744:      * @access public
                   60745:      * @deprecated use a PEAR_PackageFile_v* object's generator instead
                   60746:      */
                   60747:     function xmlFromInfo($pkginfo)
                   60748:     {
                   60749:         $config      = &PEAR_Config::singleton();
                   60750:         $packagefile = &new PEAR_PackageFile($config);
                   60751:         $pf = &$packagefile->fromArray($pkginfo);
                   60752:         $gen = &$pf->getDefaultGenerator();
                   60753:         return $gen->toXml(PEAR_VALIDATE_PACKAGING);
                   60754:     }
                   60755: 
                   60756:     /**
                   60757:      * Validate XML package definition file.
                   60758:      *
                   60759:      * @param  string $info Filename of the package archive or of the
                   60760:      *                package definition file
                   60761:      * @param  array $errors Array that will contain the errors
                   60762:      * @param  array $warnings Array that will contain the warnings
                   60763:      * @param  string $dir_prefix (optional) directory where source files
                   60764:      *                may be found, or empty if they are not available
                   60765:      * @access public
                   60766:      * @return boolean
                   60767:      * @deprecated use the validation of PEAR_PackageFile objects
                   60768:      */
                   60769:     function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
                   60770:     {
                   60771:         $config      = &PEAR_Config::singleton();
                   60772:         $packagefile = &new PEAR_PackageFile($config);
                   60773:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   60774:         if (strpos($info, '<?xml') !== false) {
                   60775:             $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
                   60776:         } else {
                   60777:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   60778:         }
                   60779: 
                   60780:         PEAR::staticPopErrorHandling();
                   60781:         if (PEAR::isError($pf)) {
                   60782:             $errs = $pf->getUserinfo();
                   60783:             if (is_array($errs)) {
                   60784:                 foreach ($errs as $error) {
                   60785:                     if ($error['level'] == 'error') {
                   60786:                         $errors[] = $error['message'];
                   60787:                     } else {
                   60788:                         $warnings[] = $error['message'];
                   60789:                     }
                   60790:                 }
                   60791:             }
                   60792: 
                   60793:             return false;
                   60794:         }
                   60795: 
                   60796:         return true;
                   60797:     }
                   60798: 
                   60799:     /**
                   60800:      * Build a "provides" array from data returned by
                   60801:      * analyzeSourceCode().  The format of the built array is like
                   60802:      * this:
                   60803:      *
                   60804:      *  array(
                   60805:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   60806:      *    ...
                   60807:      *  )
                   60808:      *
                   60809:      *
                   60810:      * @param array $srcinfo array with information about a source file
                   60811:      * as returned by the analyzeSourceCode() method.
                   60812:      *
                   60813:      * @return void
                   60814:      *
                   60815:      * @access public
                   60816:      *
                   60817:      */
                   60818:     function buildProvidesArray($srcinfo)
                   60819:     {
                   60820:         $file = basename($srcinfo['source_file']);
                   60821:         $pn = '';
                   60822:         if (isset($this->_packageName)) {
                   60823:             $pn = $this->_packageName;
                   60824:         }
                   60825: 
                   60826:         $pnl = strlen($pn);
                   60827:         foreach ($srcinfo['declared_classes'] as $class) {
                   60828:             $key = "class;$class";
                   60829:             if (isset($this->pkginfo['provides'][$key])) {
                   60830:                 continue;
                   60831:             }
                   60832: 
                   60833:             $this->pkginfo['provides'][$key] =
                   60834:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   60835:             if (isset($srcinfo['inheritance'][$class])) {
                   60836:                 $this->pkginfo['provides'][$key]['extends'] =
                   60837:                     $srcinfo['inheritance'][$class];
                   60838:             }
                   60839:         }
                   60840: 
                   60841:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   60842:             foreach ($methods as $method) {
                   60843:                 $function = "$class::$method";
                   60844:                 $key = "function;$function";
                   60845:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   60846:                     isset($this->pkginfo['provides'][$key])) {
                   60847:                     continue;
                   60848:                 }
                   60849: 
                   60850:                 $this->pkginfo['provides'][$key] =
                   60851:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   60852:             }
                   60853:         }
                   60854: 
                   60855:         foreach ($srcinfo['declared_functions'] as $function) {
                   60856:             $key = "function;$function";
                   60857:             if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
                   60858:                 continue;
                   60859:             }
                   60860: 
                   60861:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   60862:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   60863:             }
                   60864: 
                   60865:             $this->pkginfo['provides'][$key] =
                   60866:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   60867:         }
                   60868:     }
                   60869: 
                   60870:     /**
                   60871:      * Analyze the source code of the given PHP file
                   60872:      *
                   60873:      * @param  string Filename of the PHP file
                   60874:      * @return mixed
                   60875:      * @access public
                   60876:      */
                   60877:     function analyzeSourceCode($file)
                   60878:     {
                   60879:         if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   60880:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
                   60881:         }
                   60882: 
                   60883:         $a = new PEAR_PackageFile_v2_Validator;
                   60884:         return $a->analyzeSourceCode($file);
                   60885:     }
                   60886: 
                   60887:     function detectDependencies($any, $status_callback = null)
                   60888:     {
                   60889:         if (!function_exists("token_get_all")) {
                   60890:             return false;
                   60891:         }
                   60892: 
                   60893:         if (PEAR::isError($info = $this->infoFromAny($any))) {
                   60894:             return $this->raiseError($info);
                   60895:         }
                   60896: 
                   60897:         if (!is_array($info)) {
                   60898:             return false;
                   60899:         }
                   60900: 
                   60901:         $deps = array();
                   60902:         $used_c = $decl_c = $decl_f = $decl_m = array();
                   60903:         foreach ($info['filelist'] as $file => $fa) {
                   60904:             $tmp = $this->analyzeSourceCode($file);
                   60905:             $used_c = @array_merge($used_c, $tmp['used_classes']);
                   60906:             $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
                   60907:             $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
                   60908:             $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
                   60909:             $inheri = @array_merge($inheri, $tmp['inheritance']);
                   60910:         }
                   60911: 
                   60912:         $used_c = array_unique($used_c);
                   60913:         $decl_c = array_unique($decl_c);
                   60914:         $undecl_c = array_diff($used_c, $decl_c);
                   60915: 
                   60916:         return array('used_classes' => $used_c,
                   60917:                      'declared_classes' => $decl_c,
                   60918:                      'declared_methods' => $decl_m,
                   60919:                      'declared_functions' => $decl_f,
                   60920:                      'undeclared_classes' => $undecl_c,
                   60921:                      'inheritance' => $inheri,
                   60922:                      );
                   60923:     }
                   60924: 
                   60925:     /**
                   60926:      * Download a file through HTTP.  Considers suggested file name in
                   60927:      * Content-disposition: header and can run a callback function for
                   60928:      * different events.  The callback will be called with two
                   60929:      * parameters: the callback type, and parameters.  The implemented
                   60930:      * callback types are:
                   60931:      *
                   60932:      *  'setup'       called at the very beginning, parameter is a UI object
                   60933:      *                that should be used for all output
                   60934:      *  'message'     the parameter is a string with an informational message
                   60935:      *  'saveas'      may be used to save with a different file name, the
                   60936:      *                parameter is the filename that is about to be used.
                   60937:      *                If a 'saveas' callback returns a non-empty string,
                   60938:      *                that file name will be used as the filename instead.
                   60939:      *                Note that $save_dir will not be affected by this, only
                   60940:      *                the basename of the file.
                   60941:      *  'start'       download is starting, parameter is number of bytes
                   60942:      *                that are expected, or -1 if unknown
                   60943:      *  'bytesread'   parameter is the number of bytes read so far
                   60944:      *  'done'        download is complete, parameter is the total number
                   60945:      *                of bytes read
                   60946:      *  'connfailed'  if the TCP connection fails, this callback is called
                   60947:      *                with array(host,port,errno,errmsg)
                   60948:      *  'writefailed' if writing to disk fails, this callback is called
                   60949:      *                with array(destfile,errmsg)
                   60950:      *
                   60951:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   60952:      * setting), the proxy will be used.
                   60953:      *
                   60954:      * @param string  $url       the URL to download
                   60955:      * @param object  $ui        PEAR_Frontend_* instance
                   60956:      * @param object  $config    PEAR_Config instance
                   60957:      * @param string  $save_dir  (optional) directory to save file in
                   60958:      * @param mixed   $callback  (optional) function/method to call for status
                   60959:      *                           updates
                   60960:      *
                   60961:      * @return string  Returns the full path of the downloaded file or a PEAR
                   60962:      *                 error on failure.  If the error is caused by
                   60963:      *                 socket-related errors, the error object will
                   60964:      *                 have the fsockopen error code available through
                   60965:      *                 getCode().
                   60966:      *
                   60967:      * @access public
                   60968:      * @deprecated in favor of PEAR_Downloader::downloadHttp()
                   60969:      */
                   60970:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
                   60971:     {
                   60972:         if (!class_exists('PEAR_Downloader')) {
                   60973:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
                   60974:         }
                   60975:         return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
                   60976:     }
                   60977: }
                   60978: 
                   60979: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
                   60980: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';<?php
                   60981: /**
                   60982:  * PEAR_Config, customized configuration handling for the PEAR Installer
                   60983:  *
                   60984:  * PHP versions 4 and 5
                   60985:  *
                   60986:  * @category   pear
                   60987:  * @package    PEAR
                   60988:  * @author     Stig Bakken <ssb@php.net>
                   60989:  * @author     Greg Beaver <cellog@php.net>
                   60990:  * @copyright  1997-2009 The Authors
                   60991:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   60992:  * @version    CVS: $Id: Config.php 286480 2009-07-29 02:50:02Z dufuz $
                   60993:  * @link       http://pear.php.net/package/PEAR
                   60994:  * @since      File available since Release 0.1
                   60995:  */
                   60996: 
                   60997: /**
                   60998:  * Required for error handling
                   60999:  */
                   61000: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   61001: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Registry.php';
                   61002: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
                   61003: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   61004: 
                   61005: /**
                   61006:  * Last created PEAR_Config instance.
                   61007:  * @var object
                   61008:  */
                   61009: $GLOBALS['_PEAR_Config_instance'] = null;
                   61010: if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
                   61011:     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
                   61012: } else {
                   61013:     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
                   61014: }
                   61015: 
                   61016: // Below we define constants with default values for all configuration
                   61017: // parameters except username/password.  All of them can have their
                   61018: // defaults set through environment variables.  The reason we use the
                   61019: // PHP_ prefix is for some security, PHP protects environment
                   61020: // variables starting with PHP_*.
                   61021: 
                   61022: // default channel and preferred mirror is based on whether we are invoked through
                   61023: // the "pear" or the "pecl" command
                   61024: if (!defined('PEAR_RUNTYPE')) {
                   61025:     define('PEAR_RUNTYPE', 'pear');
                   61026: }
                   61027: 
                   61028: if (PEAR_RUNTYPE == 'pear') {
                   61029:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
                   61030: } else {
                   61031:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
                   61032: }
                   61033: 
                   61034: if (getenv('PHP_PEAR_SYSCONF_DIR')) {
                   61035:     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
                   61036: } elseif (getenv('SystemRoot')) {
                   61037:     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
                   61038: } else {
                   61039:     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
                   61040: }
                   61041: 
                   61042: // Default for master_server
                   61043: if (getenv('PHP_PEAR_MASTER_SERVER')) {
                   61044:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
                   61045: } else {
                   61046:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
                   61047: }
                   61048: 
                   61049: // Default for http_proxy
                   61050: if (getenv('PHP_PEAR_HTTP_PROXY')) {
                   61051:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
                   61052: } elseif (getenv('http_proxy')) {
                   61053:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
                   61054: } else {
                   61055:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
                   61056: }
                   61057: 
                   61058: // Default for php_dir
                   61059: if (getenv('PHP_PEAR_INSTALL_DIR')) {
                   61060:     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
                   61061: } else {
                   61062:     if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
                   61063:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   61064:     } else {
                   61065:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   61066:     }
                   61067: }
                   61068: 
                   61069: // Default for ext_dir
                   61070: if (getenv('PHP_PEAR_EXTENSION_DIR')) {
                   61071:     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
                   61072: } else {
                   61073:     if (ini_get('extension_dir')) {
                   61074:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
                   61075:     } elseif (defined('PEAR_EXTENSION_DIR') &&
                   61076:               file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
                   61077:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
                   61078:     } elseif (defined('PHP_EXTENSION_DIR')) {
                   61079:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
                   61080:     } else {
                   61081:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
                   61082:     }
                   61083: }
                   61084: 
                   61085: // Default for doc_dir
                   61086: if (getenv('PHP_PEAR_DOC_DIR')) {
                   61087:     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
                   61088: } else {
                   61089:     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
                   61090:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
                   61091: }
                   61092: 
                   61093: // Default for bin_dir
                   61094: if (getenv('PHP_PEAR_BIN_DIR')) {
                   61095:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
                   61096: } else {
                   61097:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
                   61098: }
                   61099: 
                   61100: // Default for data_dir
                   61101: if (getenv('PHP_PEAR_DATA_DIR')) {
                   61102:     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
                   61103: } else {
                   61104:     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
                   61105:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
                   61106: }
                   61107: 
                   61108: // Default for cfg_dir
                   61109: if (getenv('PHP_PEAR_CFG_DIR')) {
                   61110:     define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
                   61111: } else {
                   61112:     define('PEAR_CONFIG_DEFAULT_CFG_DIR',
                   61113:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
                   61114: }
                   61115: 
                   61116: // Default for www_dir
                   61117: if (getenv('PHP_PEAR_WWW_DIR')) {
                   61118:     define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
                   61119: } else {
                   61120:     define('PEAR_CONFIG_DEFAULT_WWW_DIR',
                   61121:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
                   61122: }
                   61123: 
                   61124: // Default for test_dir
                   61125: if (getenv('PHP_PEAR_TEST_DIR')) {
                   61126:     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
                   61127: } else {
                   61128:     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
                   61129:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
                   61130: }
                   61131: 
                   61132: // Default for temp_dir
                   61133: if (getenv('PHP_PEAR_TEMP_DIR')) {
                   61134:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
                   61135: } else {
                   61136:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
                   61137:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   61138:            DIRECTORY_SEPARATOR . 'temp');
                   61139: }
                   61140: 
                   61141: // Default for cache_dir
                   61142: if (getenv('PHP_PEAR_CACHE_DIR')) {
                   61143:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
                   61144: } else {
                   61145:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
                   61146:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   61147:            DIRECTORY_SEPARATOR . 'cache');
                   61148: }
                   61149: 
                   61150: // Default for download_dir
                   61151: if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
                   61152:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
                   61153: } else {
                   61154:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
                   61155:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   61156:            DIRECTORY_SEPARATOR . 'download');
                   61157: }
                   61158: 
                   61159: // Default for php_bin
                   61160: if (getenv('PHP_PEAR_PHP_BIN')) {
                   61161:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
                   61162: } else {
                   61163:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
                   61164:            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
                   61165: }
                   61166: 
                   61167: // Default for verbose
                   61168: if (getenv('PHP_PEAR_VERBOSE')) {
                   61169:     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
                   61170: } else {
                   61171:     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
                   61172: }
                   61173: 
                   61174: // Default for preferred_state
                   61175: if (getenv('PHP_PEAR_PREFERRED_STATE')) {
                   61176:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
                   61177: } else {
                   61178:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
                   61179: }
                   61180: 
                   61181: // Default for umask
                   61182: if (getenv('PHP_PEAR_UMASK')) {
                   61183:     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
                   61184: } else {
                   61185:     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
                   61186: }
                   61187: 
                   61188: // Default for cache_ttl
                   61189: if (getenv('PHP_PEAR_CACHE_TTL')) {
                   61190:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
                   61191: } else {
                   61192:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
                   61193: }
                   61194: 
                   61195: // Default for sig_type
                   61196: if (getenv('PHP_PEAR_SIG_TYPE')) {
                   61197:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
                   61198: } else {
                   61199:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
                   61200: }
                   61201: 
                   61202: // Default for sig_bin
                   61203: if (getenv('PHP_PEAR_SIG_BIN')) {
                   61204:     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
                   61205: } else {
                   61206:     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
                   61207:            System::which(
                   61208:                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
                   61209: }
                   61210: 
                   61211: // Default for sig_keydir
                   61212: if (getenv('PHP_PEAR_SIG_KEYDIR')) {
                   61213:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
                   61214: } else {
                   61215:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
                   61216:            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
                   61217: }
                   61218: 
                   61219: /**
                   61220:  * This is a class for storing configuration data, keeping track of
                   61221:  * which are system-defined, user-defined or defaulted.
                   61222:  * @category   pear
                   61223:  * @package    PEAR
                   61224:  * @author     Stig Bakken <ssb@php.net>
                   61225:  * @author     Greg Beaver <cellog@php.net>
                   61226:  * @copyright  1997-2009 The Authors
                   61227:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   61228:  * @version    Release: 1.10.0beta1
                   61229:  * @link       http://pear.php.net/package/PEAR
                   61230:  * @since      Class available since Release 0.1
                   61231:  */
                   61232: class PEAR_Config extends PEAR
                   61233: {
                   61234:     /**
                   61235:      * Array of config files used.
                   61236:      *
                   61237:      * @var array layer => config file
                   61238:      */
                   61239:     var $files = array(
                   61240:         'system' => '',
                   61241:         'user' => '',
                   61242:         );
                   61243: 
                   61244:     var $layers = array();
                   61245: 
                   61246:     /**
                   61247:      * Configuration data, two-dimensional array where the first
                   61248:      * dimension is the config layer ('user', 'system' and 'default'),
                   61249:      * and the second dimension is keyname => value.
                   61250:      *
                   61251:      * The order in the first dimension is important!  Earlier
                   61252:      * layers will shadow later ones when a config value is
                   61253:      * requested (if a 'user' value exists, it will be returned first,
                   61254:      * then 'system' and finally 'default').
                   61255:      *
                   61256:      * @var array layer => array(keyname => value, ...)
                   61257:      */
                   61258:     var $configuration = array(
                   61259:         'user' => array(),
                   61260:         'system' => array(),
                   61261:         'default' => array(),
                   61262:         );
                   61263: 
                   61264:     /**
                   61265:      * Configuration values that can be set for a channel
                   61266:      *
                   61267:      * All other configuration values can only have a global value
                   61268:      * @var array
                   61269:      * @access private
                   61270:      */
                   61271:     var $_channelConfigInfo = array(
                   61272:         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
                   61273:         'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
                   61274:         'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
                   61275:         );
                   61276: 
                   61277:     /**
                   61278:      * Channels that can be accessed
                   61279:      * @see setChannels()
                   61280:      * @var array
                   61281:      * @access private
                   61282:      */
                   61283:     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
                   61284: 
                   61285:     /**
                   61286:      * This variable is used to control the directory values returned
                   61287:      * @see setInstallRoot();
                   61288:      * @var string|false
                   61289:      * @access private
                   61290:      */
                   61291:     var $_installRoot = false;
                   61292: 
                   61293:     /**
                   61294:      * If requested, this will always refer to the registry
                   61295:      * contained in php_dir
                   61296:      * @var PEAR_Registry
                   61297:      */
                   61298:     var $_registry = array();
                   61299: 
                   61300:     /**
                   61301:      * @var array
                   61302:      * @access private
                   61303:      */
                   61304:     var $_regInitialized = array();
                   61305: 
                   61306:     /**
                   61307:      * @var bool
                   61308:      * @access private
                   61309:      */
                   61310:     var $_noRegistry = false;
                   61311: 
                   61312:     /**
                   61313:      * amount of errors found while parsing config
                   61314:      * @var integer
                   61315:      * @access private
                   61316:      */
                   61317:     var $_errorsFound = 0;
                   61318:     var $_lastError = null;
                   61319: 
                   61320:     /**
                   61321:      * Information about the configuration data.  Stores the type,
                   61322:      * default value and a documentation string for each configuration
                   61323:      * value.
                   61324:      *
                   61325:      * @var array layer => array(infotype => value, ...)
                   61326:      */
                   61327:     var $configuration_info = array(
                   61328:         // Channels/Internet Access
                   61329:         'default_channel' => array(
                   61330:             'type' => 'string',
                   61331:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   61332:             'doc' => 'the default channel to use for all non explicit commands',
                   61333:             'prompt' => 'Default Channel',
                   61334:             'group' => 'Internet Access',
                   61335:             ),
                   61336:         'preferred_mirror' => array(
                   61337:             'type' => 'string',
                   61338:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   61339:             'doc' => 'the default server or mirror to use for channel actions',
                   61340:             'prompt' => 'Default Channel Mirror',
                   61341:             'group' => 'Internet Access',
                   61342:             ),
                   61343:         'remote_config' => array(
                   61344:             'type' => 'password',
                   61345:             'default' => '',
                   61346:             'doc' => 'ftp url of remote configuration file to use for synchronized install',
                   61347:             'prompt' => 'Remote Configuration File',
                   61348:             'group' => 'Internet Access',
                   61349:             ),
                   61350:         'auto_discover' => array(
                   61351:             'type' => 'integer',
                   61352:             'default' => 0,
                   61353:             'doc' => 'whether to automatically discover new channels',
                   61354:             'prompt' => 'Auto-discover new Channels',
                   61355:             'group' => 'Internet Access',
                   61356:             ),
                   61357:         // Internet Access
                   61358:         'master_server' => array(
                   61359:             'type' => 'string',
                   61360:             'default' => 'pear.php.net',
                   61361:             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
                   61362:             'prompt' => 'PEAR server [DEPRECATED]',
                   61363:             'group' => 'Internet Access',
                   61364:             ),
                   61365:         'http_proxy' => array(
                   61366:             'type' => 'string',
                   61367:             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
                   61368:             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
                   61369:             'prompt' => 'HTTP Proxy Server Address',
                   61370:             'group' => 'Internet Access',
                   61371:             ),
                   61372:         // File Locations
                   61373:         'php_dir' => array(
                   61374:             'type' => 'directory',
                   61375:             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
                   61376:             'doc' => 'directory where .php files are installed',
                   61377:             'prompt' => 'PEAR directory',
                   61378:             'group' => 'File Locations',
                   61379:             ),
                   61380:         'ext_dir' => array(
                   61381:             'type' => 'directory',
                   61382:             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
                   61383:             'doc' => 'directory where loadable extensions are installed',
                   61384:             'prompt' => 'PHP extension directory',
                   61385:             'group' => 'File Locations',
                   61386:             ),
                   61387:         'doc_dir' => array(
                   61388:             'type' => 'directory',
                   61389:             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
                   61390:             'doc' => 'directory where documentation is installed',
                   61391:             'prompt' => 'PEAR documentation directory',
                   61392:             'group' => 'File Locations',
                   61393:             ),
                   61394:         'bin_dir' => array(
                   61395:             'type' => 'directory',
                   61396:             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
                   61397:             'doc' => 'directory where executables are installed',
                   61398:             'prompt' => 'PEAR executables directory',
                   61399:             'group' => 'File Locations',
                   61400:             ),
                   61401:         'data_dir' => array(
                   61402:             'type' => 'directory',
                   61403:             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
                   61404:             'doc' => 'directory where data files are installed',
                   61405:             'prompt' => 'PEAR data directory',
                   61406:             'group' => 'File Locations (Advanced)',
                   61407:             ),
                   61408:         'cfg_dir' => array(
                   61409:             'type' => 'directory',
                   61410:             'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
                   61411:             'doc' => 'directory where modifiable configuration files are installed',
                   61412:             'prompt' => 'PEAR configuration file directory',
                   61413:             'group' => 'File Locations (Advanced)',
                   61414:             ),
                   61415:         'www_dir' => array(
                   61416:             'type' => 'directory',
                   61417:             'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
                   61418:             'doc' => 'directory where www frontend files (html/js) are installed',
                   61419:             'prompt' => 'PEAR www files directory',
                   61420:             'group' => 'File Locations (Advanced)',
                   61421:             ),
                   61422:         'test_dir' => array(
                   61423:             'type' => 'directory',
                   61424:             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
                   61425:             'doc' => 'directory where regression tests are installed',
                   61426:             'prompt' => 'PEAR test directory',
                   61427:             'group' => 'File Locations (Advanced)',
                   61428:             ),
                   61429:         'cache_dir' => array(
                   61430:             'type' => 'directory',
                   61431:             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
                   61432:             'doc' => 'directory which is used for web service cache',
                   61433:             'prompt' => 'PEAR Installer cache directory',
                   61434:             'group' => 'File Locations (Advanced)',
                   61435:             ),
                   61436:         'temp_dir' => array(
                   61437:             'type' => 'directory',
                   61438:             'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
                   61439:             'doc' => 'directory which is used for all temp files',
                   61440:             'prompt' => 'PEAR Installer temp directory',
                   61441:             'group' => 'File Locations (Advanced)',
                   61442:             ),
                   61443:         'download_dir' => array(
                   61444:             'type' => 'directory',
                   61445:             'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
                   61446:             'doc' => 'directory which is used for all downloaded files',
                   61447:             'prompt' => 'PEAR Installer download directory',
                   61448:             'group' => 'File Locations (Advanced)',
                   61449:             ),
                   61450:         'php_bin' => array(
                   61451:             'type' => 'file',
                   61452:             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
                   61453:             'doc' => 'PHP CLI/CGI binary for executing scripts',
                   61454:             'prompt' => 'PHP CLI/CGI binary',
                   61455:             'group' => 'File Locations (Advanced)',
                   61456:             ),
                   61457:         'php_prefix' => array(
                   61458:             'type' => 'string',
                   61459:             'default' => '',
                   61460:             'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
                   61461:             'prompt' => '--program-prefix passed to PHP\'s ./configure',
                   61462:             'group' => 'File Locations (Advanced)',
                   61463:             ),
                   61464:         'php_suffix' => array(
                   61465:             'type' => 'string',
                   61466:             'default' => '',
                   61467:             'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
                   61468:             'prompt' => '--program-suffix passed to PHP\'s ./configure',
                   61469:             'group' => 'File Locations (Advanced)',
                   61470:             ),
                   61471:         'php_ini' => array(
                   61472:             'type' => 'file',
                   61473:             'default' => '',
                   61474:             'doc' => 'location of php.ini in which to enable PECL extensions on install',
                   61475:             'prompt' => 'php.ini location',
                   61476:             'group' => 'File Locations (Advanced)',
                   61477:             ),
                   61478:         // Maintainers
                   61479:         'username' => array(
                   61480:             'type' => 'string',
                   61481:             'default' => '',
                   61482:             'doc' => '(maintainers) your PEAR account name',
                   61483:             'prompt' => 'PEAR username (for maintainers)',
                   61484:             'group' => 'Maintainers',
                   61485:             ),
                   61486:         'password' => array(
                   61487:             'type' => 'password',
                   61488:             'default' => '',
                   61489:             'doc' => '(maintainers) your PEAR account password',
                   61490:             'prompt' => 'PEAR password (for maintainers)',
                   61491:             'group' => 'Maintainers',
                   61492:             ),
                   61493:         // Advanced
                   61494:         'verbose' => array(
                   61495:             'type' => 'integer',
                   61496:             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
                   61497:             'doc' => 'verbosity level
                   61498: 0: really quiet
                   61499: 1: somewhat quiet
                   61500: 2: verbose
                   61501: 3: debug',
                   61502:             'prompt' => 'Debug Log Level',
                   61503:             'group' => 'Advanced',
                   61504:             ),
                   61505:         'preferred_state' => array(
                   61506:             'type' => 'set',
                   61507:             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
                   61508:             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
                   61509:             'valid_set' => array(
                   61510:                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
                   61511:             'prompt' => 'Preferred Package State',
                   61512:             'group' => 'Advanced',
                   61513:             ),
                   61514:         'umask' => array(
                   61515:             'type' => 'mask',
                   61516:             'default' => PEAR_CONFIG_DEFAULT_UMASK,
                   61517:             'doc' => 'umask used when creating files (Unix-like systems only)',
                   61518:             'prompt' => 'Unix file mask',
                   61519:             'group' => 'Advanced',
                   61520:             ),
                   61521:         'cache_ttl' => array(
                   61522:             'type' => 'integer',
                   61523:             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
                   61524:             'doc' => 'amount of secs where the local cache is used and not updated',
                   61525:             'prompt' => 'Cache TimeToLive',
                   61526:             'group' => 'Advanced',
                   61527:             ),
                   61528:         'sig_type' => array(
                   61529:             'type' => 'set',
                   61530:             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
                   61531:             'doc' => 'which package signature mechanism to use',
                   61532:             'valid_set' => array('gpg'),
                   61533:             'prompt' => 'Package Signature Type',
                   61534:             'group' => 'Maintainers',
                   61535:             ),
                   61536:         'sig_bin' => array(
                   61537:             'type' => 'string',
                   61538:             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
                   61539:             'doc' => 'which package signature mechanism to use',
                   61540:             'prompt' => 'Signature Handling Program',
                   61541:             'group' => 'Maintainers',
                   61542:             ),
                   61543:         'sig_keyid' => array(
                   61544:             'type' => 'string',
                   61545:             'default' => '',
                   61546:             'doc' => 'which key to use for signing with',
                   61547:             'prompt' => 'Signature Key Id',
                   61548:             'group' => 'Maintainers',
                   61549:             ),
                   61550:         'sig_keydir' => array(
                   61551:             'type' => 'directory',
                   61552:             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
                   61553:             'doc' => 'directory where signature keys are located',
                   61554:             'prompt' => 'Signature Key Directory',
                   61555:             'group' => 'Maintainers',
                   61556:             ),
                   61557:         // __channels is reserved - used for channel-specific configuration
                   61558:         );
                   61559: 
                   61560:     /**
                   61561:      * Constructor.
                   61562:      *
                   61563:      * @param string file to read user-defined options from
                   61564:      * @param string file to read system-wide defaults from
                   61565:      * @param bool   determines whether a registry object "follows"
                   61566:      *               the value of php_dir (is automatically created
                   61567:      *               and moved when php_dir is changed)
                   61568:      * @param bool   if true, fails if configuration files cannot be loaded
                   61569:      *
                   61570:      * @access public
                   61571:      *
                   61572:      * @see PEAR_Config::singleton
                   61573:      */
                   61574:     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
                   61575:                          $strict = true)
                   61576:     {
                   61577:         $this->PEAR();
                   61578:         PEAR_Installer_Role::initializeConfig($this);
                   61579:         $sl = DIRECTORY_SEPARATOR;
                   61580:         if (empty($user_file)) {
                   61581:             if (OS_WINDOWS) {
                   61582:                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
                   61583:             } else {
                   61584:                 $user_file = getenv('HOME') . $sl . '.pearrc';
                   61585:             }
                   61586:         }
                   61587: 
                   61588:         if (empty($system_file)) {
                   61589:             $system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
                   61590:             if (OS_WINDOWS) {
                   61591:                 $system_file .= 'pearsys.ini';
                   61592:             } else {
                   61593:                 $system_file .= 'pear.conf';
                   61594:             }
                   61595:         }
                   61596: 
                   61597:         $this->layers = array_keys($this->configuration);
                   61598:         $this->files['user']   = $user_file;
                   61599:         $this->files['system'] = $system_file;
                   61600:         if ($user_file && file_exists($user_file)) {
                   61601:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   61602:             $this->readConfigFile($user_file, 'user', $strict);
                   61603:             $this->popErrorHandling();
                   61604:             if ($this->_errorsFound > 0) {
                   61605:                 return;
                   61606:             }
                   61607:         }
                   61608: 
                   61609:         if ($system_file && @file_exists($system_file)) {
                   61610:             $this->mergeConfigFile($system_file, false, 'system', $strict);
                   61611:             if ($this->_errorsFound > 0) {
                   61612:                 return;
                   61613:             }
                   61614: 
                   61615:         }
                   61616: 
                   61617:         if (!$ftp_file) {
                   61618:             $ftp_file = $this->get('remote_config');
                   61619:         }
                   61620: 
                   61621:         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
                   61622:             $this->readFTPConfigFile($ftp_file);
                   61623:         }
                   61624: 
                   61625:         foreach ($this->configuration_info as $key => $info) {
                   61626:             $this->configuration['default'][$key] = $info['default'];
                   61627:         }
                   61628: 
                   61629:         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
                   61630:         $this->_registry['default']->setConfig($this, false);
                   61631:         $this->_regInitialized['default'] = false;
                   61632:         //$GLOBALS['_PEAR_Config_instance'] = &$this;
                   61633:     }
                   61634: 
                   61635:     /**
                   61636:      * Return the default locations of user and system configuration files
                   61637:      * @static
                   61638:      */
                   61639:     function getDefaultConfigFiles()
                   61640:     {
                   61641:         $sl = DIRECTORY_SEPARATOR;
                   61642:         if (OS_WINDOWS) {
                   61643:             return array(
                   61644:                 'user'   => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
                   61645:                 'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
                   61646:             );
                   61647:         }
                   61648: 
                   61649:         return array(
                   61650:             'user'   => getenv('HOME') . $sl . '.pearrc',
                   61651:             'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
                   61652:         );
                   61653:     }
                   61654: 
                   61655:     /**
                   61656:      * Static singleton method.  If you want to keep only one instance
                   61657:      * of this class in use, this method will give you a reference to
                   61658:      * the last created PEAR_Config object if one exists, or create a
                   61659:      * new object.
                   61660:      *
                   61661:      * @param string (optional) file to read user-defined options from
                   61662:      * @param string (optional) file to read system-wide defaults from
                   61663:      *
                   61664:      * @return object an existing or new PEAR_Config instance
                   61665:      *
                   61666:      * @access public
                   61667:      *
                   61668:      * @see PEAR_Config::PEAR_Config
                   61669:      */
                   61670:     function &singleton($user_file = '', $system_file = '', $strict = true)
                   61671:     {
                   61672:         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
                   61673:             return $GLOBALS['_PEAR_Config_instance'];
                   61674:         }
                   61675: 
                   61676:         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
                   61677:         if ($t_conf->_errorsFound > 0) {
                   61678:              return $t_conf->lastError;
                   61679:         }
                   61680: 
                   61681:         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
                   61682:         return $GLOBALS['_PEAR_Config_instance'];
                   61683:     }
                   61684: 
                   61685:     /**
                   61686:      * Determine whether any configuration files have been detected, and whether a
                   61687:      * registry object can be retrieved from this configuration.
                   61688:      * @return bool
                   61689:      * @since PEAR 1.4.0a1
                   61690:      */
                   61691:     function validConfiguration()
                   61692:     {
                   61693:         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
                   61694:             return true;
                   61695:         }
                   61696: 
                   61697:         return false;
                   61698:     }
                   61699: 
                   61700:     /**
                   61701:      * Reads configuration data from a file.  All existing values in
                   61702:      * the config layer are discarded and replaced with data from the
                   61703:      * file.
                   61704:      * @param string file to read from, if NULL or not specified, the
                   61705:      *               last-used file for the same layer (second param) is used
                   61706:      * @param string config layer to insert data into ('user' or 'system')
                   61707:      * @return bool TRUE on success or a PEAR error on failure
                   61708:      */
                   61709:     function readConfigFile($file = null, $layer = 'user', $strict = true)
                   61710:     {
                   61711:         if (empty($this->files[$layer])) {
                   61712:             return $this->raiseError("unknown config layer `$layer'");
                   61713:         }
                   61714: 
                   61715:         if ($file === null) {
                   61716:             $file = $this->files[$layer];
                   61717:         }
                   61718: 
                   61719:         $data = $this->_readConfigDataFrom($file);
                   61720:         if (PEAR::isError($data)) {
                   61721:             if (!$strict) {
                   61722:                 return true;
                   61723:             }
                   61724: 
                   61725:             $this->_errorsFound++;
                   61726:             $this->lastError = $data;
                   61727: 
                   61728:             return $data;
                   61729:         }
                   61730: 
                   61731:         $this->files[$layer] = $file;
                   61732:         $this->_decodeInput($data);
                   61733:         $this->configuration[$layer] = $data;
                   61734:         $this->_setupChannels();
                   61735:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   61736:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   61737:             $this->_registry[$layer]->setConfig($this, false);
                   61738:             $this->_regInitialized[$layer] = false;
                   61739:         } else {
                   61740:             unset($this->_registry[$layer]);
                   61741:         }
                   61742:         return true;
                   61743:     }
                   61744: 
                   61745:     /**
                   61746:      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
                   61747:      * @return true|PEAR_Error
                   61748:      */
                   61749:     function readFTPConfigFile($path)
                   61750:     {
                   61751:         do { // poor man's try
                   61752:             if (!class_exists('PEAR_FTP')) {
                   61753:                 if (!class_exists('PEAR_Common')) {
                   61754:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   61755:                 }
                   61756:                 if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
                   61757:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/FTP.php';
                   61758:                 }
                   61759:             }
                   61760: 
                   61761:             if (!class_exists('PEAR_FTP')) {
                   61762:                 return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
                   61763:             }
                   61764: 
                   61765:             $this->_ftp = &new PEAR_FTP;
                   61766:             $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
                   61767:             $e = $this->_ftp->init($path);
                   61768:             if (PEAR::isError($e)) {
                   61769:                 $this->_ftp->popErrorHandling();
                   61770:                 return $e;
                   61771:             }
                   61772: 
                   61773:             $tmp = System::mktemp('-d');
                   61774:             PEAR_Common::addTempFile($tmp);
                   61775:             $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
                   61776:                 'pear.ini', false, FTP_BINARY);
                   61777:             if (PEAR::isError($e)) {
                   61778:                 $this->_ftp->popErrorHandling();
                   61779:                 return $e;
                   61780:             }
                   61781: 
                   61782:             PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
                   61783:             $this->_ftp->disconnect();
                   61784:             $this->_ftp->popErrorHandling();
                   61785:             $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
                   61786:             $e = $this->readConfigFile(null, 'ftp');
                   61787:             if (PEAR::isError($e)) {
                   61788:                 return $e;
                   61789:             }
                   61790: 
                   61791:             $fail = array();
                   61792:             foreach ($this->configuration_info as $key => $val) {
                   61793:                 if (in_array($this->getGroup($key),
                   61794:                       array('File Locations', 'File Locations (Advanced)')) &&
                   61795:                       $this->getType($key) == 'directory') {
                   61796:                     // any directory configs must be set for this to work
                   61797:                     if (!isset($this->configuration['ftp'][$key])) {
                   61798:                         $fail[] = $key;
                   61799:                     }
                   61800:                 }
                   61801:             }
                   61802: 
                   61803:             if (!count($fail)) {
                   61804:                 return true;
                   61805:             }
                   61806: 
                   61807:             $fail = '"' . implode('", "', $fail) . '"';
                   61808:             unset($this->files['ftp']);
                   61809:             unset($this->configuration['ftp']);
                   61810:             return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
                   61811:                 'directory configuration variables.  These variables were not set: ' .
                   61812:                 $fail);
                   61813:         } while (false); // poor man's catch
                   61814:         unset($this->files['ftp']);
                   61815:         return PEAR::raiseError('no remote host specified');
                   61816:     }
                   61817: 
                   61818:     /**
                   61819:      * Reads the existing configurations and creates the _channels array from it
                   61820:      */
                   61821:     function _setupChannels()
                   61822:     {
                   61823:         $set = array_flip(array_values($this->_channels));
                   61824:         foreach ($this->configuration as $layer => $data) {
                   61825:             $i = 1000;
                   61826:             if (isset($data['__channels']) && is_array($data['__channels'])) {
                   61827:                 foreach ($data['__channels'] as $channel => $info) {
                   61828:                     $set[$channel] = $i++;
                   61829:                 }
                   61830:             }
                   61831:         }
                   61832:         $this->_channels = array_values(array_flip($set));
                   61833:         $this->setChannels($this->_channels);
                   61834:     }
                   61835: 
                   61836:     function deleteChannel($channel)
                   61837:     {
                   61838:         $ch = strtolower($channel);
                   61839:         foreach ($this->configuration as $layer => $data) {
                   61840:             if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
                   61841:                 unset($this->configuration[$layer]['__channels'][$ch]);
                   61842:             }
                   61843:         }
                   61844: 
                   61845:         $this->_channels = array_flip($this->_channels);
                   61846:         unset($this->_channels[$ch]);
                   61847:         $this->_channels = array_flip($this->_channels);
                   61848:     }
                   61849: 
                   61850:     /**
                   61851:      * Merges data into a config layer from a file.  Does the same
                   61852:      * thing as readConfigFile, except it does not replace all
                   61853:      * existing values in the config layer.
                   61854:      * @param string file to read from
                   61855:      * @param bool whether to overwrite existing data (default TRUE)
                   61856:      * @param string config layer to insert data into ('user' or 'system')
                   61857:      * @param string if true, errors are returned if file opening fails
                   61858:      * @return bool TRUE on success or a PEAR error on failure
                   61859:      */
                   61860:     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
                   61861:     {
                   61862:         if (empty($this->files[$layer])) {
                   61863:             return $this->raiseError("unknown config layer `$layer'");
                   61864:         }
                   61865: 
                   61866:         if ($file === null) {
                   61867:             $file = $this->files[$layer];
                   61868:         }
                   61869: 
                   61870:         $data = $this->_readConfigDataFrom($file);
                   61871:         if (PEAR::isError($data)) {
                   61872:             if (!$strict) {
                   61873:                 return true;
                   61874:             }
                   61875: 
                   61876:             $this->_errorsFound++;
                   61877:             $this->lastError = $data;
                   61878: 
                   61879:             return $data;
                   61880:         }
                   61881: 
                   61882:         $this->_decodeInput($data);
                   61883:         if ($override) {
                   61884:             $this->configuration[$layer] =
                   61885:                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
                   61886:         } else {
                   61887:             $this->configuration[$layer] =
                   61888:                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
                   61889:         }
                   61890: 
                   61891:         $this->_setupChannels();
                   61892:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   61893:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   61894:             $this->_registry[$layer]->setConfig($this, false);
                   61895:             $this->_regInitialized[$layer] = false;
                   61896:         } else {
                   61897:             unset($this->_registry[$layer]);
                   61898:         }
                   61899:         return true;
                   61900:     }
                   61901: 
                   61902:     /**
                   61903:      * @param array
                   61904:      * @param array
                   61905:      * @return array
                   61906:      * @static
                   61907:      */
                   61908:     function arrayMergeRecursive($arr2, $arr1)
                   61909:     {
                   61910:         $ret = array();
                   61911:         foreach ($arr2 as $key => $data) {
                   61912:             if (!isset($arr1[$key])) {
                   61913:                 $ret[$key] = $data;
                   61914:                 unset($arr1[$key]);
                   61915:                 continue;
                   61916:             }
                   61917:             if (is_array($data)) {
                   61918:                 if (!is_array($arr1[$key])) {
                   61919:                     $ret[$key] = $arr1[$key];
                   61920:                     unset($arr1[$key]);
                   61921:                     continue;
                   61922:                 }
                   61923:                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
                   61924:                 unset($arr1[$key]);
                   61925:             }
                   61926:         }
                   61927: 
                   61928:         return array_merge($ret, $arr1);
                   61929:     }
                   61930: 
                   61931:     /**
                   61932:      * Writes data into a config layer from a file.
                   61933:      *
                   61934:      * @param string|null file to read from, or null for default
                   61935:      * @param string config layer to insert data into ('user' or
                   61936:      *               'system')
                   61937:      * @param string|null data to write to config file or null for internal data [DEPRECATED]
                   61938:      * @return bool TRUE on success or a PEAR error on failure
                   61939:      */
                   61940:     function writeConfigFile($file = null, $layer = 'user', $data = null)
                   61941:     {
                   61942:         $this->_lazyChannelSetup($layer);
                   61943:         if ($layer == 'both' || $layer == 'all') {
                   61944:             foreach ($this->files as $type => $file) {
                   61945:                 $err = $this->writeConfigFile($file, $type, $data);
                   61946:                 if (PEAR::isError($err)) {
                   61947:                     return $err;
                   61948:                 }
                   61949:             }
                   61950:             return true;
                   61951:         }
                   61952: 
                   61953:         if (empty($this->files[$layer])) {
                   61954:             return $this->raiseError("unknown config file type `$layer'");
                   61955:         }
                   61956: 
                   61957:         if ($file === null) {
                   61958:             $file = $this->files[$layer];
                   61959:         }
                   61960: 
                   61961:         $data = ($data === null) ? $this->configuration[$layer] : $data;
                   61962:         $this->_encodeOutput($data);
                   61963:         $opt = array('-p', dirname($file));
                   61964:         if (!@System::mkDir($opt)) {
                   61965:             return $this->raiseError("could not create directory: " . dirname($file));
                   61966:         }
                   61967: 
                   61968:         if (file_exists($file) && is_file($file) && !is_writeable($file)) {
                   61969:             return $this->raiseError("no write access to $file!");
                   61970:         }
                   61971: 
                   61972:         $fp = @fopen($file, "w");
                   61973:         if (!$fp) {
                   61974:             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
                   61975:         }
                   61976: 
                   61977:         $contents = "#PEAR_Config 0.9\n" . serialize($data);
                   61978:         if (!@fwrite($fp, $contents)) {
                   61979:             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
                   61980:         }
                   61981:         return true;
                   61982:     }
                   61983: 
                   61984:     /**
                   61985:      * Reads configuration data from a file and returns the parsed data
                   61986:      * in an array.
                   61987:      *
                   61988:      * @param string file to read from
                   61989:      * @return array configuration data or a PEAR error on failure
                   61990:      * @access private
                   61991:      */
                   61992:     function _readConfigDataFrom($file)
                   61993:     {
                   61994:         $fp = false;
                   61995:         if (file_exists($file)) {
                   61996:             $fp = @fopen($file, "r");
                   61997:         }
                   61998: 
                   61999:         if (!$fp) {
                   62000:             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
                   62001:         }
                   62002: 
                   62003:         $size = filesize($file);
                   62004:         $rt = get_magic_quotes_runtime();
                   62005:         set_magic_quotes_runtime(0);
                   62006:         fclose($fp);
                   62007:         $contents = file_get_contents($file);
                   62008:         if (empty($contents)) {
                   62009:             return $this->raiseError('Configuration file "' . $file . '" is empty');
                   62010:         }
                   62011: 
                   62012:         set_magic_quotes_runtime($rt);
                   62013: 
                   62014:         $version = false;
                   62015:         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
                   62016:             $version = $matches[1];
                   62017:             $contents = substr($contents, strlen($matches[0]));
                   62018:         } else {
                   62019:             // Museum config file
                   62020:             if (substr($contents,0,2) == 'a:') {
                   62021:                 $version = '0.1';
                   62022:             }
                   62023:         }
                   62024: 
                   62025:         if ($version && version_compare("$version", '1', '<')) {
                   62026:             // no '@', it is possible that unserialize
                   62027:             // raises a notice but it seems to block IO to
                   62028:             // STDOUT if a '@' is used and a notice is raise
                   62029:             $data = unserialize($contents);
                   62030: 
                   62031:             if (!is_array($data) && !$data) {
                   62032:                 if ($contents == serialize(false)) {
                   62033:                     $data = array();
                   62034:                 } else {
                   62035:                     $err = $this->raiseError("PEAR_Config: bad data in $file");
                   62036:                     return $err;
                   62037:                 }
                   62038:             }
                   62039:             if (!is_array($data)) {
                   62040:                 if (strlen(trim($contents)) > 0) {
                   62041:                     $error = "PEAR_Config: bad data in $file";
                   62042:                     $err = $this->raiseError($error);
                   62043:                     return $err;
                   62044:                 }
                   62045: 
                   62046:                 $data = array();
                   62047:             }
                   62048:         // add parsing of newer formats here...
                   62049:         } else {
                   62050:             $err = $this->raiseError("$file: unknown version `$version'");
                   62051:             return $err;
                   62052:         }
                   62053: 
                   62054:         return $data;
                   62055:     }
                   62056: 
                   62057:     /**
                   62058:     * Gets the file used for storing the config for a layer
                   62059:     *
                   62060:     * @param string $layer 'user' or 'system'
                   62061:     */
                   62062:     function getConfFile($layer)
                   62063:     {
                   62064:         return $this->files[$layer];
                   62065:     }
                   62066: 
                   62067:     /**
                   62068:      * @param string Configuration class name, used for detecting duplicate calls
                   62069:      * @param array information on a role as parsed from its xml file
                   62070:      * @return true|PEAR_Error
                   62071:      * @access private
                   62072:      */
                   62073:     function _addConfigVars($class, $vars)
                   62074:     {
                   62075:         static $called = array();
                   62076:         if (isset($called[$class])) {
                   62077:             return;
                   62078:         }
                   62079: 
                   62080:         $called[$class] = 1;
                   62081:         if (count($vars) > 3) {
                   62082:             return $this->raiseError('Roles can only define 3 new config variables or less');
                   62083:         }
                   62084: 
                   62085:         foreach ($vars as $name => $var) {
                   62086:             if (!is_array($var)) {
                   62087:                 return $this->raiseError('Configuration information must be an array');
                   62088:             }
                   62089: 
                   62090:             if (!isset($var['type'])) {
                   62091:                 return $this->raiseError('Configuration information must contain a type');
                   62092:             } elseif (!in_array($var['type'],
                   62093:                     array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
                   62094:                   return $this->raiseError(
                   62095:                       'Configuration type must be one of directory, file, string, ' .
                   62096:                       'mask, set, or password');
                   62097:             }
                   62098:             if (!isset($var['default'])) {
                   62099:                 return $this->raiseError(
                   62100:                     'Configuration information must contain a default value ("default" index)');
                   62101:             }
                   62102: 
                   62103:             if (is_array($var['default'])) {
                   62104:                 $real_default = '';
                   62105:                 foreach ($var['default'] as $config_var => $val) {
                   62106:                     if (strpos($config_var, 'text') === 0) {
                   62107:                         $real_default .= $val;
                   62108:                     } elseif (strpos($config_var, 'constant') === 0) {
                   62109:                         if (!defined($val)) {
                   62110:                             return $this->raiseError(
                   62111:                                 'Unknown constant "' . $val . '" requested in ' .
                   62112:                                 'default value for configuration variable "' .
                   62113:                                 $name . '"');
                   62114:                         }
                   62115: 
                   62116:                         $real_default .= constant($val);
                   62117:                     } elseif (isset($this->configuration_info[$config_var])) {
                   62118:                         $real_default .=
                   62119:                             $this->configuration_info[$config_var]['default'];
                   62120:                     } else {
                   62121:                         return $this->raiseError(
                   62122:                             'Unknown request for "' . $config_var . '" value in ' .
                   62123:                             'default value for configuration variable "' .
                   62124:                             $name . '"');
                   62125:                     }
                   62126:                 }
                   62127:                 $var['default'] = $real_default;
                   62128:             }
                   62129: 
                   62130:             if ($var['type'] == 'integer') {
                   62131:                 $var['default'] = (integer) $var['default'];
                   62132:             }
                   62133: 
                   62134:             if (!isset($var['doc'])) {
                   62135:                 return $this->raiseError(
                   62136:                     'Configuration information must contain a summary ("doc" index)');
                   62137:             }
                   62138: 
                   62139:             if (!isset($var['prompt'])) {
                   62140:                 return $this->raiseError(
                   62141:                     'Configuration information must contain a simple prompt ("prompt" index)');
                   62142:             }
                   62143: 
                   62144:             if (!isset($var['group'])) {
                   62145:                 return $this->raiseError(
                   62146:                     'Configuration information must contain a simple group ("group" index)');
                   62147:             }
                   62148: 
                   62149:             if (isset($this->configuration_info[$name])) {
                   62150:                 return $this->raiseError('Configuration variable "' . $name .
                   62151:                     '" already exists');
                   62152:             }
                   62153: 
                   62154:             $this->configuration_info[$name] = $var;
                   62155:             // fix bug #7351: setting custom config variable in a channel fails
                   62156:             $this->_channelConfigInfo[] = $name;
                   62157:         }
                   62158: 
                   62159:         return true;
                   62160:     }
                   62161: 
                   62162:     /**
                   62163:      * Encodes/scrambles configuration data before writing to files.
                   62164:      * Currently, 'password' values will be base64-encoded as to avoid
                   62165:      * that people spot cleartext passwords by accident.
                   62166:      *
                   62167:      * @param array (reference) array to encode values in
                   62168:      * @return bool TRUE on success
                   62169:      * @access private
                   62170:      */
                   62171:     function _encodeOutput(&$data)
                   62172:     {
                   62173:         foreach ($data as $key => $value) {
                   62174:             if ($key == '__channels') {
                   62175:                 foreach ($data['__channels'] as $channel => $blah) {
                   62176:                     $this->_encodeOutput($data['__channels'][$channel]);
                   62177:                 }
                   62178:             }
                   62179: 
                   62180:             if (!isset($this->configuration_info[$key])) {
                   62181:                 continue;
                   62182:             }
                   62183: 
                   62184:             $type = $this->configuration_info[$key]['type'];
                   62185:             switch ($type) {
                   62186:                 // we base64-encode passwords so they are at least
                   62187:                 // not shown in plain by accident
                   62188:                 case 'password': {
                   62189:                     $data[$key] = base64_encode($data[$key]);
                   62190:                     break;
                   62191:                 }
                   62192:                 case 'mask': {
                   62193:                     $data[$key] = octdec($data[$key]);
                   62194:                     break;
                   62195:                 }
                   62196:             }
                   62197:         }
                   62198: 
                   62199:         return true;
                   62200:     }
                   62201: 
                   62202:     /**
                   62203:      * Decodes/unscrambles configuration data after reading from files.
                   62204:      *
                   62205:      * @param array (reference) array to encode values in
                   62206:      * @return bool TRUE on success
                   62207:      * @access private
                   62208:      *
                   62209:      * @see PEAR_Config::_encodeOutput
                   62210:      */
                   62211:     function _decodeInput(&$data)
                   62212:     {
                   62213:         if (!is_array($data)) {
                   62214:             return true;
                   62215:         }
                   62216: 
                   62217:         foreach ($data as $key => $value) {
                   62218:             if ($key == '__channels') {
                   62219:                 foreach ($data['__channels'] as $channel => $blah) {
                   62220:                     $this->_decodeInput($data['__channels'][$channel]);
                   62221:                 }
                   62222:             }
                   62223: 
                   62224:             if (!isset($this->configuration_info[$key])) {
                   62225:                 continue;
                   62226:             }
                   62227: 
                   62228:             $type = $this->configuration_info[$key]['type'];
                   62229:             switch ($type) {
                   62230:                 case 'password': {
                   62231:                     $data[$key] = base64_decode($data[$key]);
                   62232:                     break;
                   62233:                 }
                   62234:                 case 'mask': {
                   62235:                     $data[$key] = decoct($data[$key]);
                   62236:                     break;
                   62237:                 }
                   62238:             }
                   62239:         }
                   62240: 
                   62241:         return true;
                   62242:     }
                   62243: 
                   62244:     /**
                   62245:      * Retrieve the default channel.
                   62246:      *
                   62247:      * On startup, channels are not initialized, so if the default channel is not
                   62248:      * pear.php.net, then initialize the config.
                   62249:      * @param string registry layer
                   62250:      * @return string|false
                   62251:      */
                   62252:     function getDefaultChannel($layer = null)
                   62253:     {
                   62254:         $ret = false;
                   62255:         if ($layer === null) {
                   62256:             foreach ($this->layers as $layer) {
                   62257:                 if (isset($this->configuration[$layer]['default_channel'])) {
                   62258:                     $ret = $this->configuration[$layer]['default_channel'];
                   62259:                     break;
                   62260:                 }
                   62261:             }
                   62262:         } elseif (isset($this->configuration[$layer]['default_channel'])) {
                   62263:             $ret = $this->configuration[$layer]['default_channel'];
                   62264:         }
                   62265: 
                   62266:         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
                   62267:             $ret = 'pecl.php.net';
                   62268:         }
                   62269: 
                   62270:         if ($ret) {
                   62271:             if ($ret != 'pear.php.net') {
                   62272:                 $this->_lazyChannelSetup();
                   62273:             }
                   62274: 
                   62275:             return $ret;
                   62276:         }
                   62277: 
                   62278:         return PEAR_CONFIG_DEFAULT_CHANNEL;
                   62279:     }
                   62280: 
                   62281:     /**
                   62282:      * Returns a configuration value, prioritizing layers as per the
                   62283:      * layers property.
                   62284:      *
                   62285:      * @param string config key
                   62286:      * @return mixed the config value, or NULL if not found
                   62287:      * @access public
                   62288:      */
                   62289:     function get($key, $layer = null, $channel = false)
                   62290:     {
                   62291:         if (!isset($this->configuration_info[$key])) {
                   62292:             return null;
                   62293:         }
                   62294: 
                   62295:         if ($key == '__channels') {
                   62296:             return null;
                   62297:         }
                   62298: 
                   62299:         if ($key == 'default_channel') {
                   62300:             return $this->getDefaultChannel($layer);
                   62301:         }
                   62302: 
                   62303:         if (!$channel) {
                   62304:             $channel = $this->getDefaultChannel();
                   62305:         } elseif ($channel != 'pear.php.net') {
                   62306:             $this->_lazyChannelSetup();
                   62307:         }
                   62308:         $channel = strtolower($channel);
                   62309: 
                   62310:         $test = (in_array($key, $this->_channelConfigInfo)) ?
                   62311:             $this->_getChannelValue($key, $layer, $channel) :
                   62312:             null;
                   62313:         if ($test !== null) {
                   62314:             if ($this->_installRoot) {
                   62315:                 if (in_array($this->getGroup($key),
                   62316:                       array('File Locations', 'File Locations (Advanced)')) &&
                   62317:                       $this->getType($key) == 'directory') {
                   62318:                     return $this->_prependPath($test, $this->_installRoot);
                   62319:                 }
                   62320:             }
                   62321:             return $test;
                   62322:         }
                   62323: 
                   62324:         if ($layer === null) {
                   62325:             foreach ($this->layers as $layer) {
                   62326:                 if (isset($this->configuration[$layer][$key])) {
                   62327:                     $test = $this->configuration[$layer][$key];
                   62328:                     if ($this->_installRoot) {
                   62329:                         if (in_array($this->getGroup($key),
                   62330:                               array('File Locations', 'File Locations (Advanced)')) &&
                   62331:                               $this->getType($key) == 'directory') {
                   62332:                             return $this->_prependPath($test, $this->_installRoot);
                   62333:                         }
                   62334:                     }
                   62335: 
                   62336:                     if ($key == 'preferred_mirror') {
                   62337:                         $reg = &$this->getRegistry();
                   62338:                         if (is_object($reg)) {
                   62339:                             $chan = &$reg->getChannel($channel);
                   62340:                             if (PEAR::isError($chan)) {
                   62341:                                 return $channel;
                   62342:                             }
                   62343: 
                   62344:                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   62345:                                 return $channel; // mirror does not exist
                   62346:                             }
                   62347:                         }
                   62348:                     }
                   62349:                     return $test;
                   62350:                 }
                   62351:             }
                   62352:         } elseif (isset($this->configuration[$layer][$key])) {
                   62353:             $test = $this->configuration[$layer][$key];
                   62354:             if ($this->_installRoot) {
                   62355:                 if (in_array($this->getGroup($key),
                   62356:                       array('File Locations', 'File Locations (Advanced)')) &&
                   62357:                       $this->getType($key) == 'directory') {
                   62358:                     return $this->_prependPath($test, $this->_installRoot);
                   62359:                 }
                   62360:             }
                   62361: 
                   62362:             if ($key == 'preferred_mirror') {
                   62363:                 $reg = &$this->getRegistry();
                   62364:                 if (is_object($reg)) {
                   62365:                     $chan = &$reg->getChannel($channel);
                   62366:                     if (PEAR::isError($chan)) {
                   62367:                         return $channel;
                   62368:                     }
                   62369: 
                   62370:                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   62371:                         return $channel; // mirror does not exist
                   62372:                     }
                   62373:                 }
                   62374:             }
                   62375: 
                   62376:             return $test;
                   62377:         }
                   62378: 
                   62379:         return null;
                   62380:     }
                   62381: 
                   62382:     /**
                   62383:      * Returns a channel-specific configuration value, prioritizing layers as per the
                   62384:      * layers property.
                   62385:      *
                   62386:      * @param string config key
                   62387:      * @return mixed the config value, or NULL if not found
                   62388:      * @access private
                   62389:      */
                   62390:     function _getChannelValue($key, $layer, $channel)
                   62391:     {
                   62392:         if ($key == '__channels' || $channel == 'pear.php.net') {
                   62393:             return null;
                   62394:         }
                   62395: 
                   62396:         $ret = null;
                   62397:         if ($layer === null) {
                   62398:             foreach ($this->layers as $ilayer) {
                   62399:                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
                   62400:                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
                   62401:                     break;
                   62402:                 }
                   62403:             }
                   62404:         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   62405:             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
                   62406:         }
                   62407: 
                   62408:         if ($key != 'preferred_mirror') {
                   62409:             return $ret;
                   62410:         }
                   62411: 
                   62412: 
                   62413:         if ($ret !== null) {
                   62414:             $reg = &$this->getRegistry($layer);
                   62415:             if (is_object($reg)) {
                   62416:                 $chan = &$reg->getChannel($channel);
                   62417:                 if (PEAR::isError($chan)) {
                   62418:                     return $channel;
                   62419:                 }
                   62420: 
                   62421:                 if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
                   62422:                     return $channel; // mirror does not exist
                   62423:                 }
                   62424:             }
                   62425: 
                   62426:             return $ret;
                   62427:         }
                   62428: 
                   62429:         if ($channel != $this->getDefaultChannel($layer)) {
                   62430:             return $channel; // we must use the channel name as the preferred mirror
                   62431:                              // if the user has not chosen an alternate
                   62432:         }
                   62433: 
                   62434:         return $this->getDefaultChannel($layer);
                   62435:     }
                   62436: 
                   62437:     /**
                   62438:      * Set a config value in a specific layer (defaults to 'user').
                   62439:      * Enforces the types defined in the configuration_info array.  An
                   62440:      * integer config variable will be cast to int, and a set config
                   62441:      * variable will be validated against its legal values.
                   62442:      *
                   62443:      * @param string config key
                   62444:      * @param string config value
                   62445:      * @param string (optional) config layer
                   62446:      * @param string channel to set this value for, or null for global value
                   62447:      * @return bool TRUE on success, FALSE on failure
                   62448:      */
                   62449:     function set($key, $value, $layer = 'user', $channel = false)
                   62450:     {
                   62451:         if ($key == '__channels') {
                   62452:             return false;
                   62453:         }
                   62454: 
                   62455:         if (!isset($this->configuration[$layer])) {
                   62456:             return false;
                   62457:         }
                   62458: 
                   62459:         if ($key == 'default_channel') {
                   62460:             // can only set this value globally
                   62461:             $channel = 'pear.php.net';
                   62462:             if ($value != 'pear.php.net') {
                   62463:                 $this->_lazyChannelSetup($layer);
                   62464:             }
                   62465:         }
                   62466: 
                   62467:         if ($key == 'preferred_mirror') {
                   62468:             if ($channel == '__uri') {
                   62469:                 return false; // can't set the __uri pseudo-channel's mirror
                   62470:             }
                   62471: 
                   62472:             $reg = &$this->getRegistry($layer);
                   62473:             if (is_object($reg)) {
                   62474:                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
                   62475:                 if (PEAR::isError($chan)) {
                   62476:                     return false;
                   62477:                 }
                   62478: 
                   62479:                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
                   62480:                     return false; // mirror does not exist
                   62481:                 }
                   62482:             }
                   62483:         }
                   62484: 
                   62485:         if (!isset($this->configuration_info[$key])) {
                   62486:             return false;
                   62487:         }
                   62488: 
                   62489:         extract($this->configuration_info[$key]);
                   62490:         switch ($type) {
                   62491:             case 'integer':
                   62492:                 $value = (int)$value;
                   62493:                 break;
                   62494:             case 'set': {
                   62495:                 // If a valid_set is specified, require the value to
                   62496:                 // be in the set.  If there is no valid_set, accept
                   62497:                 // any value.
                   62498:                 if ($valid_set) {
                   62499:                     reset($valid_set);
                   62500:                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
                   62501:                         (key($valid_set) !== 0 && empty($valid_set[$value])))
                   62502:                     {
                   62503:                         return false;
                   62504:                     }
                   62505:                 }
                   62506:                 break;
                   62507:             }
                   62508:         }
                   62509: 
                   62510:         if (!$channel) {
                   62511:             $channel = $this->get('default_channel', null, 'pear.php.net');
                   62512:         }
                   62513: 
                   62514:         if (!in_array($channel, $this->_channels)) {
                   62515:             $this->_lazyChannelSetup($layer);
                   62516:             $reg = &$this->getRegistry($layer);
                   62517:             if ($reg) {
                   62518:                 $channel = $reg->channelName($channel);
                   62519:             }
                   62520: 
                   62521:             if (!in_array($channel, $this->_channels)) {
                   62522:                 return false;
                   62523:             }
                   62524:         }
                   62525: 
                   62526:         if ($channel != 'pear.php.net') {
                   62527:             if (in_array($key, $this->_channelConfigInfo)) {
                   62528:                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
                   62529:                 return true;
                   62530:             }
                   62531: 
                   62532:             return false;
                   62533:         }
                   62534: 
                   62535:         if ($key == 'default_channel') {
                   62536:             if (!isset($reg)) {
                   62537:                 $reg = &$this->getRegistry($layer);
                   62538:                 if (!$reg) {
                   62539:                     $reg = &$this->getRegistry();
                   62540:                 }
                   62541:             }
                   62542: 
                   62543:             if ($reg) {
                   62544:                 $value = $reg->channelName($value);
                   62545:             }
                   62546: 
                   62547:             if (!$value) {
                   62548:                 return false;
                   62549:             }
                   62550:         }
                   62551: 
                   62552:         $this->configuration[$layer][$key] = $value;
                   62553:         if ($key == 'php_dir' && !$this->_noRegistry) {
                   62554:             if (!isset($this->_registry[$layer]) ||
                   62555:                   $value != $this->_registry[$layer]->install_dir) {
                   62556:                 $this->_registry[$layer] = &new PEAR_Registry($value);
                   62557:                 $this->_regInitialized[$layer] = false;
                   62558:                 $this->_registry[$layer]->setConfig($this, false);
                   62559:             }
                   62560:         }
                   62561: 
                   62562:         return true;
                   62563:     }
                   62564: 
                   62565:     function _lazyChannelSetup($uselayer = false)
                   62566:     {
                   62567:         if ($this->_noRegistry) {
                   62568:             return;
                   62569:         }
                   62570: 
                   62571:         $merge = false;
                   62572:         foreach ($this->_registry as $layer => $p) {
                   62573:             if ($uselayer && $uselayer != $layer) {
                   62574:                 continue;
                   62575:             }
                   62576: 
                   62577:             if (!$this->_regInitialized[$layer]) {
                   62578:                 if ($layer == 'default' && isset($this->_registry['user']) ||
                   62579:                       isset($this->_registry['system'])) {
                   62580:                     // only use the default registry if there are no alternatives
                   62581:                     continue;
                   62582:                 }
                   62583: 
                   62584:                 if (!is_object($this->_registry[$layer])) {
                   62585:                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
                   62586:                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   62587:                         $this->_registry[$layer]->setConfig($this, false);
                   62588:                         $this->_regInitialized[$layer] = false;
                   62589:                     } else {
                   62590:                         unset($this->_registry[$layer]);
                   62591:                         return;
                   62592:                     }
                   62593:                 }
                   62594: 
                   62595:                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
                   62596:                 $this->_regInitialized[$layer] = true;
                   62597:                 $merge = true;
                   62598:             }
                   62599:         }
                   62600:     }
                   62601: 
                   62602:     /**
                   62603:      * Set the list of channels.
                   62604:      *
                   62605:      * This should be set via a call to {@link PEAR_Registry::listChannels()}
                   62606:      * @param array
                   62607:      * @param bool
                   62608:      * @return bool success of operation
                   62609:      */
                   62610:     function setChannels($channels, $merge = false)
                   62611:     {
                   62612:         if (!is_array($channels)) {
                   62613:             return false;
                   62614:         }
                   62615: 
                   62616:         if ($merge) {
                   62617:             $this->_channels = array_merge($this->_channels, $channels);
                   62618:         } else {
                   62619:             $this->_channels = $channels;
                   62620:         }
                   62621: 
                   62622:         foreach ($channels as $channel) {
                   62623:             $channel = strtolower($channel);
                   62624:             if ($channel == 'pear.php.net') {
                   62625:                 continue;
                   62626:             }
                   62627: 
                   62628:             foreach ($this->layers as $layer) {
                   62629:                 if (!isset($this->configuration[$layer]['__channels'])) {
                   62630:                     $this->configuration[$layer]['__channels'] = array();
                   62631:                 }
                   62632:                 if (!isset($this->configuration[$layer]['__channels'][$channel])
                   62633:                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
                   62634:                     $this->configuration[$layer]['__channels'][$channel] = array();
                   62635:                 }
                   62636:             }
                   62637:         }
                   62638: 
                   62639:         return true;
                   62640:     }
                   62641: 
                   62642:     /**
                   62643:      * Get the type of a config value.
                   62644:      *
                   62645:      * @param string  config key
                   62646:      *
                   62647:      * @return string type, one of "string", "integer", "file",
                   62648:      * "directory", "set" or "password".
                   62649:      *
                   62650:      * @access public
                   62651:      *
                   62652:      */
                   62653:     function getType($key)
                   62654:     {
                   62655:         if (isset($this->configuration_info[$key])) {
                   62656:             return $this->configuration_info[$key]['type'];
                   62657:         }
                   62658:         return false;
                   62659:     }
                   62660: 
                   62661:     /**
                   62662:      * Get the documentation for a config value.
                   62663:      *
                   62664:      * @param string  config key
                   62665:      * @return string documentation string
                   62666:      *
                   62667:      * @access public
                   62668:      *
                   62669:      */
                   62670:     function getDocs($key)
                   62671:     {
                   62672:         if (isset($this->configuration_info[$key])) {
                   62673:             return $this->configuration_info[$key]['doc'];
                   62674:         }
                   62675: 
                   62676:         return false;
                   62677:     }
                   62678: 
                   62679:     /**
                   62680:      * Get the short documentation for a config value.
                   62681:      *
                   62682:      * @param string  config key
                   62683:      * @return string short documentation string
                   62684:      *
                   62685:      * @access public
                   62686:      *
                   62687:      */
                   62688:     function getPrompt($key)
                   62689:     {
                   62690:         if (isset($this->configuration_info[$key])) {
                   62691:             return $this->configuration_info[$key]['prompt'];
                   62692:         }
                   62693: 
                   62694:         return false;
                   62695:     }
                   62696: 
                   62697:     /**
                   62698:      * Get the parameter group for a config key.
                   62699:      *
                   62700:      * @param string  config key
                   62701:      * @return string parameter group
                   62702:      *
                   62703:      * @access public
                   62704:      *
                   62705:      */
                   62706:     function getGroup($key)
                   62707:     {
                   62708:         if (isset($this->configuration_info[$key])) {
                   62709:             return $this->configuration_info[$key]['group'];
                   62710:         }
                   62711: 
                   62712:         return false;
                   62713:     }
                   62714: 
                   62715:     /**
                   62716:      * Get the list of parameter groups.
                   62717:      *
                   62718:      * @return array list of parameter groups
                   62719:      *
                   62720:      * @access public
                   62721:      *
                   62722:      */
                   62723:     function getGroups()
                   62724:     {
                   62725:         $tmp = array();
                   62726:         foreach ($this->configuration_info as $key => $info) {
                   62727:             $tmp[$info['group']] = 1;
                   62728:         }
                   62729: 
                   62730:         return array_keys($tmp);
                   62731:     }
                   62732: 
                   62733:     /**
                   62734:      * Get the list of the parameters in a group.
                   62735:      *
                   62736:      * @param string $group parameter group
                   62737:      * @return array list of parameters in $group
                   62738:      *
                   62739:      * @access public
                   62740:      *
                   62741:      */
                   62742:     function getGroupKeys($group)
                   62743:     {
                   62744:         $keys = array();
                   62745:         foreach ($this->configuration_info as $key => $info) {
                   62746:             if ($info['group'] == $group) {
                   62747:                 $keys[] = $key;
                   62748:             }
                   62749:         }
                   62750: 
                   62751:         return $keys;
                   62752:     }
                   62753: 
                   62754:     /**
                   62755:      * Get the list of allowed set values for a config value.  Returns
                   62756:      * NULL for config values that are not sets.
                   62757:      *
                   62758:      * @param string  config key
                   62759:      * @return array enumerated array of set values, or NULL if the
                   62760:      *               config key is unknown or not a set
                   62761:      *
                   62762:      * @access public
                   62763:      *
                   62764:      */
                   62765:     function getSetValues($key)
                   62766:     {
                   62767:         if (isset($this->configuration_info[$key]) &&
                   62768:             isset($this->configuration_info[$key]['type']) &&
                   62769:             $this->configuration_info[$key]['type'] == 'set')
                   62770:         {
                   62771:             $valid_set = $this->configuration_info[$key]['valid_set'];
                   62772:             reset($valid_set);
                   62773:             if (key($valid_set) === 0) {
                   62774:                 return $valid_set;
                   62775:             }
                   62776: 
                   62777:             return array_keys($valid_set);
                   62778:         }
                   62779: 
                   62780:         return null;
                   62781:     }
                   62782: 
                   62783:     /**
                   62784:      * Get all the current config keys.
                   62785:      *
                   62786:      * @return array simple array of config keys
                   62787:      *
                   62788:      * @access public
                   62789:      */
                   62790:     function getKeys()
                   62791:     {
                   62792:         $keys = array();
                   62793:         foreach ($this->layers as $layer) {
                   62794:             $test = $this->configuration[$layer];
                   62795:             if (isset($test['__channels'])) {
                   62796:                 foreach ($test['__channels'] as $channel => $configs) {
                   62797:                     $keys = array_merge($keys, $configs);
                   62798:                 }
                   62799:             }
                   62800: 
                   62801:             unset($test['__channels']);
                   62802:             $keys = array_merge($keys, $test);
                   62803: 
                   62804:         }
                   62805:         return array_keys($keys);
                   62806:     }
                   62807: 
                   62808:     /**
                   62809:      * Remove the a config key from a specific config layer.
                   62810:      *
                   62811:      * @param string config key
                   62812:      * @param string (optional) config layer
                   62813:      * @param string (optional) channel (defaults to default channel)
                   62814:      * @return bool TRUE on success, FALSE on failure
                   62815:      *
                   62816:      * @access public
                   62817:      */
                   62818:     function remove($key, $layer = 'user', $channel = null)
                   62819:     {
                   62820:         if ($channel === null) {
                   62821:             $channel = $this->getDefaultChannel();
                   62822:         }
                   62823: 
                   62824:         if ($channel !== 'pear.php.net') {
                   62825:             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   62826:                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
                   62827:                 return true;
                   62828:             }
                   62829:         }
                   62830: 
                   62831:         if (isset($this->configuration[$layer][$key])) {
                   62832:             unset($this->configuration[$layer][$key]);
                   62833:             return true;
                   62834:         }
                   62835: 
                   62836:         return false;
                   62837:     }
                   62838: 
                   62839:     /**
                   62840:      * Temporarily remove an entire config layer.  USE WITH CARE!
                   62841:      *
                   62842:      * @param string config key
                   62843:      * @param string (optional) config layer
                   62844:      * @return bool TRUE on success, FALSE on failure
                   62845:      *
                   62846:      * @access public
                   62847:      */
                   62848:     function removeLayer($layer)
                   62849:     {
                   62850:         if (isset($this->configuration[$layer])) {
                   62851:             $this->configuration[$layer] = array();
                   62852:             return true;
                   62853:         }
                   62854: 
                   62855:         return false;
                   62856:     }
                   62857: 
                   62858:     /**
                   62859:      * Stores configuration data in a layer.
                   62860:      *
                   62861:      * @param string config layer to store
                   62862:      * @return bool TRUE on success, or PEAR error on failure
                   62863:      *
                   62864:      * @access public
                   62865:      */
                   62866:     function store($layer = 'user', $data = null)
                   62867:     {
                   62868:         return $this->writeConfigFile(null, $layer, $data);
                   62869:     }
                   62870: 
                   62871:     /**
                   62872:      * Tells what config layer that gets to define a key.
                   62873:      *
                   62874:      * @param string config key
                   62875:      * @param boolean return the defining channel
                   62876:      *
                   62877:      * @return string|array the config layer, or an empty string if not found.
                   62878:      *
                   62879:      *         if $returnchannel, the return is an array array('layer' => layername,
                   62880:      *         'channel' => channelname), or an empty string if not found
                   62881:      *
                   62882:      * @access public
                   62883:      */
                   62884:     function definedBy($key, $returnchannel = false)
                   62885:     {
                   62886:         foreach ($this->layers as $layer) {
                   62887:             $channel = $this->getDefaultChannel();
                   62888:             if ($channel !== 'pear.php.net') {
                   62889:                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   62890:                     if ($returnchannel) {
                   62891:                         return array('layer' => $layer, 'channel' => $channel);
                   62892:                     }
                   62893:                     return $layer;
                   62894:                 }
                   62895:             }
                   62896: 
                   62897:             if (isset($this->configuration[$layer][$key])) {
                   62898:                 if ($returnchannel) {
                   62899:                     return array('layer' => $layer, 'channel' => 'pear.php.net');
                   62900:                 }
                   62901:                 return $layer;
                   62902:             }
                   62903:         }
                   62904: 
                   62905:         return '';
                   62906:     }
                   62907: 
                   62908:     /**
                   62909:      * Tells whether a given key exists as a config value.
                   62910:      *
                   62911:      * @param string config key
                   62912:      * @return bool whether <config key> exists in this object
                   62913:      *
                   62914:      * @access public
                   62915:      */
                   62916:     function isDefined($key)
                   62917:     {
                   62918:         foreach ($this->layers as $layer) {
                   62919:             if (isset($this->configuration[$layer][$key])) {
                   62920:                 return true;
                   62921:             }
                   62922:         }
                   62923: 
                   62924:         return false;
                   62925:     }
                   62926: 
                   62927:     /**
                   62928:      * Tells whether a given config layer exists.
                   62929:      *
                   62930:      * @param string config layer
                   62931:      * @return bool whether <config layer> exists in this object
                   62932:      *
                   62933:      * @access public
                   62934:      */
                   62935:     function isDefinedLayer($layer)
                   62936:     {
                   62937:         return isset($this->configuration[$layer]);
                   62938:     }
                   62939: 
                   62940:     /**
                   62941:      * Returns the layers defined (except the 'default' one)
                   62942:      *
                   62943:      * @return array of the defined layers
                   62944:      */
                   62945:     function getLayers()
                   62946:     {
                   62947:         $cf = $this->configuration;
                   62948:         unset($cf['default']);
                   62949:         return array_keys($cf);
                   62950:     }
                   62951: 
                   62952:     function apiVersion()
                   62953:     {
                   62954:         return '1.1';
                   62955:     }
                   62956: 
                   62957:     /**
                   62958:      * @return PEAR_Registry
                   62959:      */
                   62960:     function &getRegistry($use = null)
                   62961:     {
                   62962:         $layer = $use === null ? 'user' : $use;
                   62963:         if (isset($this->_registry[$layer])) {
                   62964:             return $this->_registry[$layer];
                   62965:         } elseif ($use === null && isset($this->_registry['system'])) {
                   62966:             return $this->_registry['system'];
                   62967:         } elseif ($use === null && isset($this->_registry['default'])) {
                   62968:             return $this->_registry['default'];
                   62969:         } elseif ($use) {
                   62970:             $a = false;
                   62971:             return $a;
                   62972:         }
                   62973: 
                   62974:         // only go here if null was passed in
                   62975:         echo "CRITICAL ERROR: Registry could not be initialized from any value";
                   62976:         exit(1);
                   62977:     }
                   62978: 
                   62979:     /**
                   62980:      * This is to allow customization like the use of installroot
                   62981:      * @param PEAR_Registry
                   62982:      * @return bool
                   62983:      */
                   62984:     function setRegistry(&$reg, $layer = 'user')
                   62985:     {
                   62986:         if ($this->_noRegistry) {
                   62987:             return false;
                   62988:         }
                   62989: 
                   62990:         if (!in_array($layer, array('user', 'system'))) {
                   62991:             return false;
                   62992:         }
                   62993: 
                   62994:         $this->_registry[$layer] = &$reg;
                   62995:         if (is_object($reg)) {
                   62996:             $this->_registry[$layer]->setConfig($this, false);
                   62997:         }
                   62998: 
                   62999:         return true;
                   63000:     }
                   63001: 
                   63002:     function noRegistry()
                   63003:     {
                   63004:         $this->_noRegistry = true;
                   63005:     }
                   63006: 
                   63007:     /**
                   63008:      * @return PEAR_REST
                   63009:      */
                   63010:     function &getREST($version, $options = array())
                   63011:     {
                   63012:         $version = str_replace('.', '', $version);
                   63013:         if (!class_exists($class = 'PEAR_REST_' . $version)) {
                   63014:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST/' . $version . '.php';
                   63015:         }
                   63016: 
                   63017:         $remote = &new $class($this, $options);
                   63018:         return $remote;
                   63019:     }
                   63020: 
                   63021:     /**
                   63022:      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
                   63023:      * remote configuration file has been specified
                   63024:      * @return PEAR_FTP|false
                   63025:      */
                   63026:     function &getFTP()
                   63027:     {
                   63028:         if (isset($this->_ftp)) {
                   63029:             return $this->_ftp;
                   63030:         }
                   63031: 
                   63032:         $a = false;
                   63033:         return $a;
                   63034:     }
                   63035: 
                   63036:     function _prependPath($path, $prepend)
                   63037:     {
                   63038:         if (strlen($prepend) > 0) {
                   63039:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   63040:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   63041:                     $prepend = substr($prepend, 2);
                   63042:                 } elseif ($prepend{0} != '\\') {
                   63043:                     $prepend = "\\$prepend";
                   63044:                 }
                   63045:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   63046:             } else {
                   63047:                 $path = $prepend . $path;
                   63048:             }
                   63049:         }
                   63050:         return $path;
                   63051:     }
                   63052: 
                   63053:     /**
                   63054:      * @param string|false installation directory to prepend to all _dir variables, or false to
                   63055:      *                     disable
                   63056:      */
                   63057:     function setInstallRoot($root)
                   63058:     {
                   63059:         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
                   63060:             $root = substr($root, 0, -1);
                   63061:         }
                   63062:         $old = $this->_installRoot;
                   63063:         $this->_installRoot = $root;
                   63064:         if (($old != $root) && !$this->_noRegistry) {
                   63065:             foreach (array_keys($this->_registry) as $layer) {
                   63066:                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
                   63067:                     continue;
                   63068:                 }
                   63069:                 $this->_registry[$layer] =
                   63070:                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
                   63071:                 $this->_registry[$layer]->setConfig($this, false);
                   63072:                 $this->_regInitialized[$layer] = false;
                   63073:             }
                   63074:         }
                   63075:     }
                   63076: }
                   63077: <?php
                   63078: /**
                   63079:  * PEAR_Dependency2, advanced dependency validation
                   63080:  *
                   63081:  * PHP versions 4 and 5
                   63082:  *
                   63083:  * @category   pear
                   63084:  * @package    PEAR
                   63085:  * @author     Greg Beaver <cellog@php.net>
                   63086:  * @copyright  1997-2009 The Authors
                   63087:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   63088:  * @version    CVS: $Id: Dependency2.php 286494 2009-07-29 06:57:11Z dufuz $
                   63089:  * @link       http://pear.php.net/package/PEAR
                   63090:  * @since      File available since Release 1.4.0a1
                   63091:  */
                   63092: 
                   63093: /**
                   63094:  * Required for the PEAR_VALIDATE_* constants
                   63095:  */
                   63096: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   63097: 
                   63098: /**
                   63099:  * Dependency check for PEAR packages
                   63100:  *
                   63101:  * This class handles both version 1.0 and 2.0 dependencies
                   63102:  * WARNING: *any* changes to this class must be duplicated in the
                   63103:  * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
                   63104:  * or unit tests will not actually validate the changes
                   63105:  * @category   pear
                   63106:  * @package    PEAR
                   63107:  * @author     Greg Beaver <cellog@php.net>
                   63108:  * @copyright  1997-2009 The Authors
                   63109:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   63110:  * @version    Release: 1.10.0beta1
                   63111:  * @link       http://pear.php.net/package/PEAR
                   63112:  * @since      Class available since Release 1.4.0a1
                   63113:  */
                   63114: class PEAR_Dependency2
                   63115: {
                   63116:     /**
                   63117:      * One of the PEAR_VALIDATE_* states
                   63118:      * @see PEAR_VALIDATE_NORMAL
                   63119:      * @var integer
                   63120:      */
                   63121:     var $_state;
                   63122: 
                   63123:     /**
                   63124:      * Command-line options to install/upgrade/uninstall commands
                   63125:      * @param array
                   63126:      */
                   63127:     var $_options;
                   63128: 
                   63129:     /**
                   63130:      * @var OS_Guess
                   63131:      */
                   63132:     var $_os;
                   63133: 
                   63134:     /**
                   63135:      * @var PEAR_Registry
                   63136:      */
                   63137:     var $_registry;
                   63138: 
                   63139:     /**
                   63140:      * @var PEAR_Config
                   63141:      */
                   63142:     var $_config;
                   63143: 
                   63144:     /**
                   63145:      * @var PEAR_DependencyDB
                   63146:      */
                   63147:     var $_dependencydb;
                   63148: 
                   63149:     /**
                   63150:      * Output of PEAR_Registry::parsedPackageName()
                   63151:      * @var array
                   63152:      */
                   63153:     var $_currentPackage;
                   63154: 
                   63155:     /**
                   63156:      * @param PEAR_Config
                   63157:      * @param array installation options
                   63158:      * @param array format of PEAR_Registry::parsedPackageName()
                   63159:      * @param int installation state (one of PEAR_VALIDATE_*)
                   63160:      */
                   63161:     function PEAR_Dependency2(&$config, $installoptions, $package,
                   63162:                               $state = PEAR_VALIDATE_INSTALLING)
                   63163:     {
                   63164:         $this->_config = &$config;
                   63165:         if (!class_exists('PEAR_DependencyDB')) {
                   63166:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/DependencyDB.php';
                   63167:         }
                   63168: 
                   63169:         if (isset($installoptions['packagingroot'])) {
                   63170:             // make sure depdb is in the right location
                   63171:             $config->setInstallRoot($installoptions['packagingroot']);
                   63172:         }
                   63173: 
                   63174:         $this->_registry = &$config->getRegistry();
                   63175:         $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
                   63176:         if (isset($installoptions['packagingroot'])) {
                   63177:             $config->setInstallRoot(false);
                   63178:         }
                   63179: 
                   63180:         $this->_options = $installoptions;
                   63181:         $this->_state = $state;
                   63182:         if (!class_exists('OS_Guess')) {
                   63183:             require_once 'phar://install-pear-nozlib.phar/' . 'OS/Guess.php';
                   63184:         }
                   63185: 
                   63186:         $this->_os = new OS_Guess;
                   63187:         $this->_currentPackage = $package;
                   63188:     }
                   63189: 
                   63190:     function _getExtraString($dep)
                   63191:     {
                   63192:         $extra = ' (';
                   63193:         if (isset($dep['uri'])) {
                   63194:             return '';
                   63195:         }
                   63196: 
                   63197:         if (isset($dep['recommended'])) {
                   63198:             $extra .= 'recommended version ' . $dep['recommended'];
                   63199:         } else {
                   63200:             if (isset($dep['min'])) {
                   63201:                 $extra .= 'version >= ' . $dep['min'];
                   63202:             }
                   63203: 
                   63204:             if (isset($dep['max'])) {
                   63205:                 if ($extra != ' (') {
                   63206:                     $extra .= ', ';
                   63207:                 }
                   63208:                 $extra .= 'version <= ' . $dep['max'];
                   63209:             }
                   63210: 
                   63211:             if (isset($dep['exclude'])) {
                   63212:                 if (!is_array($dep['exclude'])) {
                   63213:                     $dep['exclude'] = array($dep['exclude']);
                   63214:                 }
                   63215: 
                   63216:                 if ($extra != ' (') {
                   63217:                     $extra .= ', ';
                   63218:                 }
                   63219: 
                   63220:                 $extra .= 'excluded versions: ';
                   63221:                 foreach ($dep['exclude'] as $i => $exclude) {
                   63222:                     if ($i) {
                   63223:                         $extra .= ', ';
                   63224:                     }
                   63225:                     $extra .= $exclude;
                   63226:                 }
                   63227:             }
                   63228:         }
                   63229: 
                   63230:         $extra .= ')';
                   63231:         if ($extra == ' ()') {
                   63232:             $extra = '';
                   63233:         }
                   63234: 
                   63235:         return $extra;
                   63236:     }
                   63237: 
                   63238:     /**
                   63239:      * This makes unit-testing a heck of a lot easier
                   63240:      */
                   63241:     function getPHP_OS()
                   63242:     {
                   63243:         return PHP_OS;
                   63244:     }
                   63245: 
                   63246:     /**
                   63247:      * This makes unit-testing a heck of a lot easier
                   63248:      */
                   63249:     function getsysname()
                   63250:     {
                   63251:         return $this->_os->getSysname();
                   63252:     }
                   63253: 
                   63254:     /**
                   63255:      * Specify a dependency on an OS.  Use arch for detailed os/processor information
                   63256:      *
                   63257:      * There are two generic OS dependencies that will be the most common, unix and windows.
                   63258:      * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
                   63259:      */
                   63260:     function validateOsDependency($dep)
                   63261:     {
                   63262:         if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   63263:             return true;
                   63264:         }
                   63265: 
                   63266:         if ($dep['name'] == '*') {
                   63267:             return true;
                   63268:         }
                   63269: 
                   63270:         $not = isset($dep['conflicts']) ? true : false;
                   63271:         switch (strtolower($dep['name'])) {
                   63272:             case 'windows' :
                   63273:                 if ($not) {
                   63274:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
                   63275:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63276:                             return $this->raiseError("Cannot install %s on Windows");
                   63277:                         }
                   63278: 
                   63279:                         return $this->warning("warning: Cannot install %s on Windows");
                   63280:                     }
                   63281:                 } else {
                   63282:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
                   63283:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63284:                             return $this->raiseError("Can only install %s on Windows");
                   63285:                         }
                   63286: 
                   63287:                         return $this->warning("warning: Can only install %s on Windows");
                   63288:                     }
                   63289:                 }
                   63290:             break;
                   63291:             case 'unix' :
                   63292:                 $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
                   63293:                 if ($not) {
                   63294:                     if (in_array($this->getSysname(), $unices)) {
                   63295:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63296:                             return $this->raiseError("Cannot install %s on any Unix system");
                   63297:                         }
                   63298: 
                   63299:                         return $this->warning( "warning: Cannot install %s on any Unix system");
                   63300:                     }
                   63301:                 } else {
                   63302:                     if (!in_array($this->getSysname(), $unices)) {
                   63303:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63304:                             return $this->raiseError("Can only install %s on a Unix system");
                   63305:                         }
                   63306: 
                   63307:                         return $this->warning("warning: Can only install %s on a Unix system");
                   63308:                     }
                   63309:                 }
                   63310:             break;
                   63311:             default :
                   63312:                 if ($not) {
                   63313:                     if (strtolower($dep['name']) == strtolower($this->getSysname())) {
                   63314:                         if (!isset($this->_options['nodeps']) &&
                   63315:                               !isset($this->_options['force'])) {
                   63316:                             return $this->raiseError('Cannot install %s on ' . $dep['name'] .
                   63317:                                 ' operating system');
                   63318:                         }
                   63319: 
                   63320:                         return $this->warning('warning: Cannot install %s on ' .
                   63321:                             $dep['name'] . ' operating system');
                   63322:                     }
                   63323:                 } else {
                   63324:                     if (strtolower($dep['name']) != strtolower($this->getSysname())) {
                   63325:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63326:                             return $this->raiseError('Cannot install %s on ' .
                   63327:                                 $this->getSysname() .
                   63328:                                 ' operating system, can only install on ' . $dep['name']);
                   63329:                         }
                   63330: 
                   63331:                         return $this->warning('warning: Cannot install %s on ' .
                   63332:                             $this->getSysname() .
                   63333:                             ' operating system, can only install on ' . $dep['name']);
                   63334:                     }
                   63335:                 }
                   63336:         }
                   63337:         return true;
                   63338:     }
                   63339: 
                   63340:     /**
                   63341:      * This makes unit-testing a heck of a lot easier
                   63342:      */
                   63343:     function matchSignature($pattern)
                   63344:     {
                   63345:         return $this->_os->matchSignature($pattern);
                   63346:     }
                   63347: 
                   63348:     /**
                   63349:      * Specify a complex dependency on an OS/processor/kernel version,
                   63350:      * Use OS for simple operating system dependency.
                   63351:      *
                   63352:      * This is the only dependency that accepts an eregable pattern.  The pattern
                   63353:      * will be matched against the php_uname() output parsed by OS_Guess
                   63354:      */
                   63355:     function validateArchDependency($dep)
                   63356:     {
                   63357:         if ($this->_state != PEAR_VALIDATE_INSTALLING) {
                   63358:             return true;
                   63359:         }
                   63360: 
                   63361:         $not = isset($dep['conflicts']) ? true : false;
                   63362:         if (!$this->matchSignature($dep['pattern'])) {
                   63363:             if (!$not) {
                   63364:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63365:                     return $this->raiseError('%s Architecture dependency failed, does not ' .
                   63366:                         'match "' . $dep['pattern'] . '"');
                   63367:                 }
                   63368: 
                   63369:                 return $this->warning('warning: %s Architecture dependency failed, does ' .
                   63370:                     'not match "' . $dep['pattern'] . '"');
                   63371:             }
                   63372: 
                   63373:             return true;
                   63374:         }
                   63375: 
                   63376:         if ($not) {
                   63377:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63378:                 return $this->raiseError('%s Architecture dependency failed, required "' .
                   63379:                     $dep['pattern'] . '"');
                   63380:             }
                   63381: 
                   63382:             return $this->warning('warning: %s Architecture dependency failed, ' .
                   63383:                 'required "' . $dep['pattern'] . '"');
                   63384:         }
                   63385: 
                   63386:         return true;
                   63387:     }
                   63388: 
                   63389:     /**
                   63390:      * This makes unit-testing a heck of a lot easier
                   63391:      */
                   63392:     function extension_loaded($name)
                   63393:     {
                   63394:         return extension_loaded($name);
                   63395:     }
                   63396: 
                   63397:     /**
                   63398:      * This makes unit-testing a heck of a lot easier
                   63399:      */
                   63400:     function phpversion($name = null)
                   63401:     {
                   63402:         if ($name !== null) {
                   63403:             return phpversion($name);
                   63404:         }
                   63405: 
                   63406:         return phpversion();
                   63407:     }
                   63408: 
                   63409:     function validateExtensionDependency($dep, $required = true)
                   63410:     {
                   63411:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   63412:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   63413:             return true;
                   63414:         }
                   63415: 
                   63416:         $loaded = $this->extension_loaded($dep['name']);
                   63417:         $extra  = $this->_getExtraString($dep);
                   63418:         if (isset($dep['exclude'])) {
                   63419:             if (!is_array($dep['exclude'])) {
                   63420:                 $dep['exclude'] = array($dep['exclude']);
                   63421:             }
                   63422:         }
                   63423: 
                   63424:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   63425:             !isset($dep['recommended']) && !isset($dep['exclude'])
                   63426:         ) {
                   63427:             if ($loaded) {
                   63428:                 if (isset($dep['conflicts'])) {
                   63429:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63430:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   63431:                             $dep['name'] . '"' . $extra);
                   63432:                     }
                   63433: 
                   63434:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   63435:                         $dep['name'] . '"' . $extra);
                   63436:                 }
                   63437: 
                   63438:                 return true;
                   63439:             }
                   63440: 
                   63441:             if (isset($dep['conflicts'])) {
                   63442:                 return true;
                   63443:             }
                   63444: 
                   63445:             if ($required) {
                   63446:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63447:                     return $this->raiseError('%s requires PHP extension "' .
                   63448:                         $dep['name'] . '"' . $extra);
                   63449:                 }
                   63450: 
                   63451:                 return $this->warning('warning: %s requires PHP extension "' .
                   63452:                     $dep['name'] . '"' . $extra);
                   63453:             }
                   63454: 
                   63455:             return $this->warning('%s can optionally use PHP extension "' .
                   63456:                 $dep['name'] . '"' . $extra);
                   63457:         }
                   63458: 
                   63459:         if (!$loaded) {
                   63460:             if (isset($dep['conflicts'])) {
                   63461:                 return true;
                   63462:             }
                   63463: 
                   63464:             if (!$required) {
                   63465:                 return $this->warning('%s can optionally use PHP extension "' .
                   63466:                     $dep['name'] . '"' . $extra);
                   63467:             }
                   63468: 
                   63469:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63470:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   63471:                     '"' . $extra);
                   63472:             }
                   63473: 
                   63474:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   63475:                     '"' . $extra);
                   63476:         }
                   63477: 
                   63478:         $version = (string) $this->phpversion($dep['name']);
                   63479:         if (empty($version)) {
                   63480:             $version = '0';
                   63481:         }
                   63482: 
                   63483:         $fail = false;
                   63484:         if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
                   63485:             $fail = true;
                   63486:         }
                   63487: 
                   63488:         if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
                   63489:             $fail = true;
                   63490:         }
                   63491: 
                   63492:         if ($fail && !isset($dep['conflicts'])) {
                   63493:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63494:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   63495:                     '"' . $extra . ', installed version is ' . $version);
                   63496:             }
                   63497: 
                   63498:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   63499:                 '"' . $extra . ', installed version is ' . $version);
                   63500:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
                   63501:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63502:                 return $this->raiseError('%s conflicts with PHP extension "' .
                   63503:                     $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   63504:             }
                   63505: 
                   63506:             return $this->warning('warning: %s conflicts with PHP extension "' .
                   63507:                 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   63508:         }
                   63509: 
                   63510:         if (isset($dep['exclude'])) {
                   63511:             foreach ($dep['exclude'] as $exclude) {
                   63512:                 if (version_compare($version, $exclude, '==')) {
                   63513:                     if (isset($dep['conflicts'])) {
                   63514:                         continue;
                   63515:                     }
                   63516: 
                   63517:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63518:                         return $this->raiseError('%s is not compatible with PHP extension "' .
                   63519:                             $dep['name'] . '" version ' .
                   63520:                             $exclude);
                   63521:                     }
                   63522: 
                   63523:                     return $this->warning('warning: %s is not compatible with PHP extension "' .
                   63524:                         $dep['name'] . '" version ' .
                   63525:                         $exclude);
                   63526:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   63527:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63528:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   63529:                             $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   63530:                     }
                   63531: 
                   63532:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   63533:                         $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   63534:                 }
                   63535:             }
                   63536:         }
                   63537: 
                   63538:         if (isset($dep['recommended'])) {
                   63539:             if (version_compare($version, $dep['recommended'], '==')) {
                   63540:                 return true;
                   63541:             }
                   63542: 
                   63543:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63544:                 return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
                   63545:                     ' version "' . $version . '"' .
                   63546:                     ' is not the recommended version "' . $dep['recommended'] .
                   63547:                     '", but may be compatible, use --force to install');
                   63548:             }
                   63549: 
                   63550:             return $this->warning('warning: %s dependency: PHP extension ' .
                   63551:                 $dep['name'] . ' version "' . $version . '"' .
                   63552:                 ' is not the recommended version "' . $dep['recommended'].'"');
                   63553:         }
                   63554: 
                   63555:         return true;
                   63556:     }
                   63557: 
                   63558:     function validatePhpDependency($dep)
                   63559:     {
                   63560:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   63561:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   63562:             return true;
                   63563:         }
                   63564: 
                   63565:         $version = $this->phpversion();
                   63566:         $extra   = $this->_getExtraString($dep);
                   63567:         if (isset($dep['exclude'])) {
                   63568:             if (!is_array($dep['exclude'])) {
                   63569:                 $dep['exclude'] = array($dep['exclude']);
                   63570:             }
                   63571:         }
                   63572: 
                   63573:         if (isset($dep['min'])) {
                   63574:             if (!version_compare($version, $dep['min'], '>=')) {
                   63575:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63576:                     return $this->raiseError('%s requires PHP' .
                   63577:                         $extra . ', installed version is ' . $version);
                   63578:                 }
                   63579: 
                   63580:                 return $this->warning('warning: %s requires PHP' .
                   63581:                     $extra . ', installed version is ' . $version);
                   63582:             }
                   63583:         }
                   63584: 
                   63585:         if (isset($dep['max'])) {
                   63586:             if (!version_compare($version, $dep['max'], '<=')) {
                   63587:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63588:                     return $this->raiseError('%s requires PHP' .
                   63589:                         $extra . ', installed version is ' . $version);
                   63590:                 }
                   63591: 
                   63592:                 return $this->warning('warning: %s requires PHP' .
                   63593:                     $extra . ', installed version is ' . $version);
                   63594:             }
                   63595:         }
                   63596: 
                   63597:         if (isset($dep['exclude'])) {
                   63598:             foreach ($dep['exclude'] as $exclude) {
                   63599:                 if (version_compare($version, $exclude, '==')) {
                   63600:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63601:                         return $this->raiseError('%s is not compatible with PHP version ' .
                   63602:                             $exclude);
                   63603:                     }
                   63604: 
                   63605:                     return $this->warning(
                   63606:                         'warning: %s is not compatible with PHP version ' .
                   63607:                         $exclude);
                   63608:                 }
                   63609:             }
                   63610:         }
                   63611: 
                   63612:         return true;
                   63613:     }
                   63614: 
                   63615:     /**
                   63616:      * This makes unit-testing a heck of a lot easier
                   63617:      */
                   63618:     function getPEARVersion()
                   63619:     {
                   63620:         return '1.10.0beta1';
                   63621:     }
                   63622: 
                   63623:     function validatePearinstallerDependency($dep)
                   63624:     {
                   63625:         $pearversion = $this->getPEARVersion();
                   63626:         $extra = $this->_getExtraString($dep);
                   63627:         if (isset($dep['exclude'])) {
                   63628:             if (!is_array($dep['exclude'])) {
                   63629:                 $dep['exclude'] = array($dep['exclude']);
                   63630:             }
                   63631:         }
                   63632: 
                   63633:         if (version_compare($pearversion, $dep['min'], '<')) {
                   63634:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63635:                 return $this->raiseError('%s requires PEAR Installer' . $extra .
                   63636:                     ', installed version is ' . $pearversion);
                   63637:             }
                   63638: 
                   63639:             return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   63640:                 ', installed version is ' . $pearversion);
                   63641:         }
                   63642: 
                   63643:         if (isset($dep['max'])) {
                   63644:             if (version_compare($pearversion, $dep['max'], '>')) {
                   63645:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63646:                     return $this->raiseError('%s requires PEAR Installer' . $extra .
                   63647:                         ', installed version is ' . $pearversion);
                   63648:                 }
                   63649: 
                   63650:                 return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   63651:                     ', installed version is ' . $pearversion);
                   63652:             }
                   63653:         }
                   63654: 
                   63655:         if (isset($dep['exclude'])) {
                   63656:             if (!isset($dep['exclude'][0])) {
                   63657:                 $dep['exclude'] = array($dep['exclude']);
                   63658:             }
                   63659: 
                   63660:             foreach ($dep['exclude'] as $exclude) {
                   63661:                 if (version_compare($exclude, $pearversion, '==')) {
                   63662:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63663:                         return $this->raiseError('%s is not compatible with PEAR Installer ' .
                   63664:                             'version ' . $exclude);
                   63665:                     }
                   63666: 
                   63667:                     return $this->warning('warning: %s is not compatible with PEAR ' .
                   63668:                         'Installer version ' . $exclude);
                   63669:                 }
                   63670:             }
                   63671:         }
                   63672: 
                   63673:         return true;
                   63674:     }
                   63675: 
                   63676:     function validateSubpackageDependency($dep, $required, $params)
                   63677:     {
                   63678:         return $this->validatePackageDependency($dep, $required, $params);
                   63679:     }
                   63680: 
                   63681:     /**
                   63682:      * @param array dependency information (2.0 format)
                   63683:      * @param boolean whether this is a required dependency
                   63684:      * @param array a list of downloaded packages to be installed, if any
                   63685:      * @param boolean if true, then deps on pear.php.net that fail will also check
                   63686:      *                against pecl.php.net packages to accomodate extensions that have
                   63687:      *                moved to pecl.php.net from pear.php.net
                   63688:      */
                   63689:     function validatePackageDependency($dep, $required, $params, $depv1 = false)
                   63690:     {
                   63691:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   63692:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   63693:             return true;
                   63694:         }
                   63695: 
                   63696:         if (isset($dep['providesextension'])) {
                   63697:             if ($this->extension_loaded($dep['providesextension'])) {
                   63698:                 $save = $dep;
                   63699:                 $subdep = $dep;
                   63700:                 $subdep['name'] = $subdep['providesextension'];
                   63701:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   63702:                 $ret = $this->validateExtensionDependency($subdep, $required);
                   63703:                 PEAR::popErrorHandling();
                   63704:                 if (!PEAR::isError($ret)) {
                   63705:                     return true;
                   63706:                 }
                   63707:             }
                   63708:         }
                   63709: 
                   63710:         if ($this->_state == PEAR_VALIDATE_INSTALLING) {
                   63711:             return $this->_validatePackageInstall($dep, $required, $depv1);
                   63712:         }
                   63713: 
                   63714:         if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
                   63715:             return $this->_validatePackageDownload($dep, $required, $params, $depv1);
                   63716:         }
                   63717:     }
                   63718: 
                   63719:     function _validatePackageDownload($dep, $required, $params, $depv1 = false)
                   63720:     {
                   63721:         $dep['package'] = $dep['name'];
                   63722:         if (isset($dep['uri'])) {
                   63723:             $dep['channel'] = '__uri';
                   63724:         }
                   63725: 
                   63726:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   63727:         $found = false;
                   63728:         foreach ($params as $param) {
                   63729:             if ($param->isEqual(
                   63730:                   array('package' => $dep['name'],
                   63731:                         'channel' => $dep['channel']))) {
                   63732:                 $found = true;
                   63733:                 break;
                   63734:             }
                   63735: 
                   63736:             if ($depv1 && $dep['channel'] == 'pear.php.net') {
                   63737:                 if ($param->isEqual(
                   63738:                   array('package' => $dep['name'],
                   63739:                         'channel' => 'pecl.php.net'))) {
                   63740:                     $found = true;
                   63741:                     break;
                   63742:                 }
                   63743:             }
                   63744:         }
                   63745: 
                   63746:         if (!$found && isset($dep['providesextension'])) {
                   63747:             foreach ($params as $param) {
                   63748:                 if ($param->isExtension($dep['providesextension'])) {
                   63749:                     $found = true;
                   63750:                     break;
                   63751:                 }
                   63752:             }
                   63753:         }
                   63754: 
                   63755:         if ($found) {
                   63756:             $version = $param->getVersion();
                   63757:             $installed = false;
                   63758:             $downloaded = true;
                   63759:         } else {
                   63760:             if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
                   63761:                 $installed = true;
                   63762:                 $downloaded = false;
                   63763:                 $version = $this->_registry->packageinfo($dep['name'], 'version',
                   63764:                     $dep['channel']);
                   63765:             } else {
                   63766:                 if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
                   63767:                       'pear.php.net')) {
                   63768:                     $installed = true;
                   63769:                     $downloaded = false;
                   63770:                     $version = $this->_registry->packageinfo($dep['name'], 'version',
                   63771:                         'pear.php.net');
                   63772:                 } else {
                   63773:                     $version = 'not installed or downloaded';
                   63774:                     $installed = false;
                   63775:                     $downloaded = false;
                   63776:                 }
                   63777:             }
                   63778:         }
                   63779: 
                   63780:         $extra = $this->_getExtraString($dep);
                   63781:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   63782:             $dep['exclude'] = array($dep['exclude']);
                   63783:         }
                   63784: 
                   63785:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   63786:               !isset($dep['recommended']) && !isset($dep['exclude'])
                   63787:         ) {
                   63788:             if ($installed || $downloaded) {
                   63789:                 $installed = $installed ? 'installed' : 'downloaded';
                   63790:                 if (isset($dep['conflicts'])) {
                   63791:                     $rest = '';
                   63792:                     if ($version) {
                   63793:                         $rest = ", $installed version is " . $version;
                   63794:                     }
                   63795: 
                   63796:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63797:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
                   63798:                     }
                   63799: 
                   63800:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
                   63801:                 }
                   63802: 
                   63803:                 return true;
                   63804:             }
                   63805: 
                   63806:             if (isset($dep['conflicts'])) {
                   63807:                 return true;
                   63808:             }
                   63809: 
                   63810:             if ($required) {
                   63811:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63812:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   63813:                 }
                   63814: 
                   63815:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   63816:             }
                   63817: 
                   63818:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   63819:         }
                   63820: 
                   63821:         if (!$installed && !$downloaded) {
                   63822:             if (isset($dep['conflicts'])) {
                   63823:                 return true;
                   63824:             }
                   63825: 
                   63826:             if ($required) {
                   63827:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63828:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   63829:                 }
                   63830: 
                   63831:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   63832:             }
                   63833: 
                   63834:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   63835:         }
                   63836: 
                   63837:         $fail = false;
                   63838:         if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
                   63839:             $fail = true;
                   63840:         }
                   63841: 
                   63842:         if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
                   63843:             $fail = true;
                   63844:         }
                   63845: 
                   63846:         if ($fail && !isset($dep['conflicts'])) {
                   63847:             $installed = $installed ? 'installed' : 'downloaded';
                   63848:             $dep['package'] = $dep['name'];
                   63849:             $dep = $this->_registry->parsedPackageNameToString($dep, true);
                   63850:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63851:                 return $this->raiseError('%s requires package "' . $depname . '"' .
                   63852:                     $extra . ", $installed version is " . $version);
                   63853:             }
                   63854: 
                   63855:             return $this->warning('warning: %s requires package "' . $depname . '"' .
                   63856:                 $extra . ", $installed version is " . $version);
                   63857:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
                   63858:               isset($dep['conflicts']) && !isset($dep['exclude'])) {
                   63859:             $installed = $installed ? 'installed' : 'downloaded';
                   63860:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63861:                 return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
                   63862:                     ", $installed version is " . $version);
                   63863:             }
                   63864: 
                   63865:             return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   63866:                 $extra . ", $installed version is " . $version);
                   63867:         }
                   63868: 
                   63869:         if (isset($dep['exclude'])) {
                   63870:             $installed = $installed ? 'installed' : 'downloaded';
                   63871:             foreach ($dep['exclude'] as $exclude) {
                   63872:                 if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
                   63873:                     if (!isset($this->_options['nodeps']) &&
                   63874:                           !isset($this->_options['force'])
                   63875:                     ) {
                   63876:                         return $this->raiseError('%s is not compatible with ' .
                   63877:                             $installed . ' package "' .
                   63878:                             $depname . '" version ' .
                   63879:                             $exclude);
                   63880:                     }
                   63881: 
                   63882:                     return $this->warning('warning: %s is not compatible with ' .
                   63883:                         $installed . ' package "' .
                   63884:                         $depname . '" version ' .
                   63885:                         $exclude);
                   63886:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   63887:                     $installed = $installed ? 'installed' : 'downloaded';
                   63888:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   63889:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' .
                   63890:                             $extra . ", $installed version is " . $version);
                   63891:                     }
                   63892: 
                   63893:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   63894:                         $extra . ", $installed version is " . $version);
                   63895:                 }
                   63896:             }
                   63897:         }
                   63898: 
                   63899:         if (isset($dep['recommended'])) {
                   63900:             $installed = $installed ? 'installed' : 'downloaded';
                   63901:             if (version_compare($version, $dep['recommended'], '==')) {
                   63902:                 return true;
                   63903:             }
                   63904: 
                   63905:             if (!$found && $installed) {
                   63906:                 $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
                   63907:             }
                   63908: 
                   63909:             if ($param) {
                   63910:                 $found = false;
                   63911:                 foreach ($params as $parent) {
                   63912:                     if ($parent->isEqual($this->_currentPackage)) {
                   63913:                         $found = true;
                   63914:                         break;
                   63915:                     }
                   63916:                 }
                   63917: 
                   63918:                 if ($found) {
                   63919:                     if ($param->isCompatible($parent)) {
                   63920:                         return true;
                   63921:                     }
                   63922:                 } else { // this is for validPackage() calls
                   63923:                     $parent = $this->_registry->getPackage($this->_currentPackage['package'],
                   63924:                         $this->_currentPackage['channel']);
                   63925:                     if ($parent !== null && $param->isCompatible($parent)) {
                   63926:                         return true;
                   63927:                     }
                   63928:                 }
                   63929:             }
                   63930: 
                   63931:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
                   63932:                   !isset($this->_options['loose'])
                   63933:             ) {
                   63934:                 return $this->raiseError('%s dependency package "' . $depname .
                   63935:                     '" ' . $installed . ' version ' . $version .
                   63936:                     ' is not the recommended version ' . $dep['recommended'] .
                   63937:                     ', but may be compatible, use --force to install');
                   63938:             }
                   63939: 
                   63940:             return $this->warning('warning: %s dependency package "' . $depname .
                   63941:                 '" ' . $installed . ' version ' . $version .
                   63942:                 ' is not the recommended version ' . $dep['recommended']);
                   63943:         }
                   63944: 
                   63945:         return true;
                   63946:     }
                   63947: 
                   63948:     function _validatePackageInstall($dep, $required, $depv1 = false)
                   63949:     {
                   63950:         return $this->_validatePackageDownload($dep, $required, array(), $depv1);
                   63951:     }
                   63952: 
                   63953:     /**
                   63954:      * Verify that uninstalling packages passed in to command line is OK.
                   63955:      *
                   63956:      * @param PEAR_Installer $dl
                   63957:      * @return PEAR_Error|true
                   63958:      */
                   63959:     function validatePackageUninstall(&$dl)
                   63960:     {
                   63961:         if (PEAR::isError($this->_dependencydb)) {
                   63962:             return $this->_dependencydb;
                   63963:         }
                   63964: 
                   63965:         $params = array();
                   63966:         // construct an array of "downloaded" packages to fool the package dependency checker
                   63967:         // into using these to validate uninstalls of circular dependencies
                   63968:         $downloaded = &$dl->getUninstallPackages();
                   63969:         foreach ($downloaded as $i => $pf) {
                   63970:             if (!class_exists('PEAR_Downloader_Package')) {
                   63971:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
                   63972:             }
                   63973:             $dp = &new PEAR_Downloader_Package($dl);
                   63974:             $dp->setPackageFile($downloaded[$i]);
                   63975:             $params[$i] = &$dp;
                   63976:         }
                   63977: 
                   63978:         // check cache
                   63979:         $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
                   63980:             strtolower($this->_currentPackage['package']);
                   63981:         if (isset($dl->___uninstall_package_cache)) {
                   63982:             $badpackages = $dl->___uninstall_package_cache;
                   63983:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   63984:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   63985:                     $dl->log(0, $warning[0]);
                   63986:                 }
                   63987:             }
                   63988: 
                   63989:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   63990:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   63991:                     if (is_array($error)) {
                   63992:                         $dl->log(0, $error[0]);
                   63993:                     } else {
                   63994:                         $dl->log(0, $error->getMessage());
                   63995:                     }
                   63996:                 }
                   63997: 
                   63998:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   63999:                     return $this->warning(
                   64000:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   64001:                         'on this package');
                   64002:                 }
                   64003: 
                   64004:                 return $this->raiseError(
                   64005:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   64006:             }
                   64007: 
                   64008:             return true;
                   64009:         }
                   64010: 
                   64011:         // first, list the immediate parents of each package to be uninstalled
                   64012:         $perpackagelist = array();
                   64013:         $allparents = array();
                   64014:         foreach ($params as $i => $param) {
                   64015:             $a = array(
                   64016:                 'channel' => strtolower($param->getChannel()),
                   64017:                 'package' => strtolower($param->getPackage())
                   64018:             );
                   64019: 
                   64020:             $deps = $this->_dependencydb->getDependentPackages($a);
                   64021:             if ($deps) {
                   64022:                 foreach ($deps as $d) {
                   64023:                     $pardeps = $this->_dependencydb->getDependencies($d);
                   64024:                     foreach ($pardeps as $dep) {
                   64025:                         if (strtolower($dep['dep']['channel']) == $a['channel'] &&
                   64026:                               strtolower($dep['dep']['name']) == $a['package']) {
                   64027:                             if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
                   64028:                                 $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
                   64029:                             }
                   64030:                             $perpackagelist[$a['channel'] . '/' . $a['package']][]
                   64031:                                 = array($d['channel'] . '/' . $d['package'], $dep);
                   64032:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
                   64033:                                 $allparents[$d['channel'] . '/' . $d['package']] = array();
                   64034:                             }
                   64035:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
                   64036:                                 $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
                   64037:                             }
                   64038:                             $allparents[$d['channel'] . '/' . $d['package']]
                   64039:                                        [$a['channel'] . '/' . $a['package']][]
                   64040:                                 = array($d, $dep);
                   64041:                         }
                   64042:                     }
                   64043:                 }
                   64044:             }
                   64045:         }
                   64046: 
                   64047:         // next, remove any packages from the parents list that are not installed
                   64048:         $remove = array();
                   64049:         foreach ($allparents as $parent => $d1) {
                   64050:             foreach ($d1 as $d) {
                   64051:                 if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
                   64052:                     continue;
                   64053:                 }
                   64054:                 $remove[$parent] = true;
                   64055:             }
                   64056:         }
                   64057: 
                   64058:         // next remove any packages from the parents list that are not passed in for
                   64059:         // uninstallation
                   64060:         foreach ($allparents as $parent => $d1) {
                   64061:             foreach ($d1 as $d) {
                   64062:                 foreach ($params as $param) {
                   64063:                     if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
                   64064:                           strtolower($param->getPackage()) == $d[0][0]['package']) {
                   64065:                         // found it
                   64066:                         continue 3;
                   64067:                     }
                   64068:                 }
                   64069:                 $remove[$parent] = true;
                   64070:             }
                   64071:         }
                   64072: 
                   64073:         // remove all packages whose dependencies fail
                   64074:         // save which ones failed for error reporting
                   64075:         $badchildren = array();
                   64076:         do {
                   64077:             $fail = false;
                   64078:             foreach ($remove as $package => $unused) {
                   64079:                 if (!isset($allparents[$package])) {
                   64080:                     continue;
                   64081:                 }
                   64082: 
                   64083:                 foreach ($allparents[$package] as $kid => $d1) {
                   64084:                     foreach ($d1 as $depinfo) {
                   64085:                         if ($depinfo[1]['type'] != 'optional') {
                   64086:                             if (isset($badchildren[$kid])) {
                   64087:                                 continue;
                   64088:                             }
                   64089:                             $badchildren[$kid] = true;
                   64090:                             $remove[$kid] = true;
                   64091:                             $fail = true;
                   64092:                             continue 2;
                   64093:                         }
                   64094:                     }
                   64095:                 }
                   64096:                 if ($fail) {
                   64097:                     // start over, we removed some children
                   64098:                     continue 2;
                   64099:                 }
                   64100:             }
                   64101:         } while ($fail);
                   64102: 
                   64103:         // next, construct the list of packages that can't be uninstalled
                   64104:         $badpackages = array();
                   64105:         $save = $this->_currentPackage;
                   64106:         foreach ($perpackagelist as $package => $packagedeps) {
                   64107:             foreach ($packagedeps as $parent) {
                   64108:                 if (!isset($remove[$parent[0]])) {
                   64109:                     continue;
                   64110:                 }
                   64111: 
                   64112:                 $packagename = $this->_registry->parsePackageName($parent[0]);
                   64113:                 $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
                   64114:                 $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
                   64115:                 $packagename['package'] = $pa->getPackage();
                   64116:                 $this->_currentPackage = $packagename;
                   64117:                 // parent is not present in uninstall list, make sure we can actually
                   64118:                 // uninstall it (parent dep is optional)
                   64119:                 $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
                   64120:                 $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
                   64121:                 $parentname['package'] = $pa->getPackage();
                   64122:                 $parent[1]['dep']['package'] = $parentname['package'];
                   64123:                 $parent[1]['dep']['channel'] = $parentname['channel'];
                   64124:                 if ($parent[1]['type'] == 'optional') {
                   64125:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
                   64126:                     if ($test !== true) {
                   64127:                         $badpackages[$package]['warnings'][] = $test;
                   64128:                     }
                   64129:                 } else {
                   64130:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
                   64131:                     if ($test !== true) {
                   64132:                         $badpackages[$package]['errors'][] = $test;
                   64133:                     }
                   64134:                 }
                   64135:             }
                   64136:         }
                   64137: 
                   64138:         $this->_currentPackage          = $save;
                   64139:         $dl->___uninstall_package_cache = $badpackages;
                   64140:         if (isset($badpackages[$memyselfandI])) {
                   64141:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   64142:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   64143:                     $dl->log(0, $warning[0]);
                   64144:                 }
                   64145:             }
                   64146: 
                   64147:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   64148:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   64149:                     if (is_array($error)) {
                   64150:                         $dl->log(0, $error[0]);
                   64151:                     } else {
                   64152:                         $dl->log(0, $error->getMessage());
                   64153:                     }
                   64154:                 }
                   64155: 
                   64156:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   64157:                     return $this->warning(
                   64158:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   64159:                         'on this package');
                   64160:                 }
                   64161: 
                   64162:                 return $this->raiseError(
                   64163:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   64164:             }
                   64165:         }
                   64166: 
                   64167:         return true;
                   64168:     }
                   64169: 
                   64170:     function _validatePackageUninstall($dep, $required, $dl)
                   64171:     {
                   64172:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   64173:         $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
                   64174:         if (!$version) {
                   64175:             return true;
                   64176:         }
                   64177: 
                   64178:         $extra = $this->_getExtraString($dep);
                   64179:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   64180:             $dep['exclude'] = array($dep['exclude']);
                   64181:         }
                   64182: 
                   64183:         if (isset($dep['conflicts'])) {
                   64184:             return true; // uninstall OK - these packages conflict (probably installed with --force)
                   64185:         }
                   64186: 
                   64187:         if (!isset($dep['min']) && !isset($dep['max'])) {
                   64188:             if (!$required) {
                   64189:                 return $this->warning('"' . $depname . '" can be optionally used by ' .
                   64190:                         'installed package %s' . $extra);
                   64191:             }
                   64192: 
                   64193:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   64194:                 return $this->raiseError('"' . $depname . '" is required by ' .
                   64195:                     'installed package %s' . $extra);
                   64196:             }
                   64197: 
                   64198:             return $this->warning('warning: "' . $depname . '" is required by ' .
                   64199:                 'installed package %s' . $extra);
                   64200:         }
                   64201: 
                   64202:         $fail = false;
                   64203:         if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
                   64204:             $fail = true;
                   64205:         }
                   64206: 
                   64207:         if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
                   64208:             $fail = true;
                   64209:         }
                   64210: 
                   64211:         // we re-use this variable, preserve the original value
                   64212:         $saverequired = $required;
                   64213:         if (!$required) {
                   64214:             return $this->warning($depname . $extra . ' can be optionally used by installed package' .
                   64215:                     ' "%s"');
                   64216:         }
                   64217: 
                   64218:         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   64219:             return $this->raiseError($depname . $extra . ' is required by installed package' .
                   64220:                 ' "%s"');
                   64221:         }
                   64222: 
                   64223:         return $this->raiseError('warning: ' . $depname . $extra .
                   64224:             ' is required by installed package "%s"');
                   64225:     }
                   64226: 
                   64227:     /**
                   64228:      * validate a downloaded package against installed packages
                   64229:      *
                   64230:      * As of PEAR 1.4.3, this will only validate
                   64231:      *
                   64232:      * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   64233:      *              $pkg package identifier (either
                   64234:      *                   array('package' => blah, 'channel' => blah) or an array with
                   64235:      *                   index 'info' referencing an object)
                   64236:      * @param PEAR_Downloader $dl
                   64237:      * @param array $params full list of packages to install
                   64238:      * @return true|PEAR_Error
                   64239:      */
                   64240:     function validatePackage($pkg, &$dl, $params = array())
                   64241:     {
                   64242:         if (is_array($pkg) && isset($pkg['info'])) {
                   64243:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
                   64244:         } else {
                   64245:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
                   64246:         }
                   64247: 
                   64248:         $fail = false;
                   64249:         if ($deps) {
                   64250:             if (!class_exists('PEAR_Downloader_Package')) {
                   64251:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
                   64252:             }
                   64253: 
                   64254:             $dp = &new PEAR_Downloader_Package($dl);
                   64255:             if (is_object($pkg)) {
                   64256:                 $dp->setPackageFile($pkg);
                   64257:             } else {
                   64258:                 $dp->setDownloadURL($pkg);
                   64259:             }
                   64260: 
                   64261:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   64262:             foreach ($deps as $channel => $info) {
                   64263:                 foreach ($info as $package => $ds) {
                   64264:                     foreach ($params as $packd) {
                   64265:                         if (strtolower($packd->getPackage()) == strtolower($package) &&
                   64266:                               $packd->getChannel() == $channel) {
                   64267:                             $dl->log(3, 'skipping installed package check of "' .
                   64268:                                         $this->_registry->parsedPackageNameToString(
                   64269:                                             array('channel' => $channel, 'package' => $package),
                   64270:                                             true) .
                   64271:                                         '", version "' . $packd->getVersion() . '" will be ' .
                   64272:                                         'downloaded and installed');
                   64273:                             continue 2; // jump to next package
                   64274:                         }
                   64275:                     }
                   64276: 
                   64277:                     foreach ($ds as $d) {
                   64278:                         $checker = &new PEAR_Dependency2($this->_config, $this->_options,
                   64279:                             array('channel' => $channel, 'package' => $package), $this->_state);
                   64280:                         $dep = $d['dep'];
                   64281:                         $required = $d['type'] == 'required';
                   64282:                         $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
                   64283:                         if (is_array($ret)) {
                   64284:                             $dl->log(0, $ret[0]);
                   64285:                         } elseif (PEAR::isError($ret)) {
                   64286:                             $dl->log(0, $ret->getMessage());
                   64287:                             $fail = true;
                   64288:                         }
                   64289:                     }
                   64290:                 }
                   64291:             }
                   64292:             PEAR::popErrorHandling();
                   64293:         }
                   64294: 
                   64295:         if ($fail) {
                   64296:             return $this->raiseError(
                   64297:                 '%s cannot be installed, conflicts with installed packages');
                   64298:         }
                   64299: 
                   64300:         return true;
                   64301:     }
                   64302: 
                   64303:     /**
                   64304:      * validate a package.xml 1.0 dependency
                   64305:      */
                   64306:     function validateDependency1($dep, $params = array())
                   64307:     {
                   64308:         if (!isset($dep['optional'])) {
                   64309:             $dep['optional'] = 'no';
                   64310:         }
                   64311: 
                   64312:         list($newdep, $type) = $this->normalizeDep($dep);
                   64313:         if (!$newdep) {
                   64314:             return $this->raiseError("Invalid Dependency");
                   64315:         }
                   64316: 
                   64317:         if (method_exists($this, "validate{$type}Dependency")) {
                   64318:             return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
                   64319:                 $params, true);
                   64320:         }
                   64321:     }
                   64322: 
                   64323:     /**
                   64324:      * Convert a 1.0 dep into a 2.0 dep
                   64325:      */
                   64326:     function normalizeDep($dep)
                   64327:     {
                   64328:         $types = array(
                   64329:             'pkg' => 'Package',
                   64330:             'ext' => 'Extension',
                   64331:             'os' => 'Os',
                   64332:             'php' => 'Php'
                   64333:         );
                   64334: 
                   64335:         if (!isset($types[$dep['type']])) {
                   64336:             return array(false, false);
                   64337:         }
                   64338: 
                   64339:         $type = $types[$dep['type']];
                   64340: 
                   64341:         $newdep = array();
                   64342:         switch ($type) {
                   64343:             case 'Package' :
                   64344:                 $newdep['channel'] = 'pear.php.net';
                   64345:             case 'Extension' :
                   64346:             case 'Os' :
                   64347:                 $newdep['name'] = $dep['name'];
                   64348:             break;
                   64349:         }
                   64350: 
                   64351:         $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
                   64352:         switch ($dep['rel']) {
                   64353:             case 'has' :
                   64354:                 return array($newdep, $type);
                   64355:             break;
                   64356:             case 'not' :
                   64357:                 $newdep['conflicts'] = true;
                   64358:             break;
                   64359:             case '>=' :
                   64360:             case '>' :
                   64361:                 $newdep['min'] = $dep['version'];
                   64362:                 if ($dep['rel'] == '>') {
                   64363:                     $newdep['exclude'] = $dep['version'];
                   64364:                 }
                   64365:             break;
                   64366:             case '<=' :
                   64367:             case '<' :
                   64368:                 $newdep['max'] = $dep['version'];
                   64369:                 if ($dep['rel'] == '<') {
                   64370:                     $newdep['exclude'] = $dep['version'];
                   64371:                 }
                   64372:             break;
                   64373:             case 'ne' :
                   64374:             case '!=' :
                   64375:                 $newdep['min'] = '0';
                   64376:                 $newdep['max'] = '100000';
                   64377:                 $newdep['exclude'] = $dep['version'];
                   64378:             break;
                   64379:             case '==' :
                   64380:                 $newdep['min'] = $dep['version'];
                   64381:                 $newdep['max'] = $dep['version'];
                   64382:             break;
                   64383:         }
                   64384:         if ($type == 'Php') {
                   64385:             if (!isset($newdep['min'])) {
                   64386:                 $newdep['min'] = '4.4.0';
                   64387:             }
                   64388: 
                   64389:             if (!isset($newdep['max'])) {
                   64390:                 $newdep['max'] = '6.0.0';
                   64391:             }
                   64392:         }
                   64393:         return array($newdep, $type);
                   64394:     }
                   64395: 
                   64396:     /**
                   64397:      * Converts text comparing operators to them sign equivalents
                   64398:      *
                   64399:      * Example: 'ge' to '>='
                   64400:      *
                   64401:      * @access public
                   64402:      * @param  string Operator
                   64403:      * @return string Sign equivalent
                   64404:      */
                   64405:     function signOperator($operator)
                   64406:     {
                   64407:         switch($operator) {
                   64408:             case 'lt': return '<';
                   64409:             case 'le': return '<=';
                   64410:             case 'gt': return '>';
                   64411:             case 'ge': return '>=';
                   64412:             case 'eq': return '==';
                   64413:             case 'ne': return '!=';
                   64414:             default:
                   64415:                 return $operator;
                   64416:         }
                   64417:     }
                   64418: 
                   64419:     function raiseError($msg)
                   64420:     {
                   64421:         if (isset($this->_options['ignore-errors'])) {
                   64422:             return $this->warning($msg);
                   64423:         }
                   64424: 
                   64425:         return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   64426:             $this->_currentPackage, true)));
                   64427:     }
                   64428: 
                   64429:     function warning($msg)
                   64430:     {
                   64431:         return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   64432:             $this->_currentPackage, true)));
                   64433:     }
                   64434: }<?php
                   64435: /**
                   64436:  * PEAR_DependencyDB, advanced installed packages dependency database
                   64437:  *
                   64438:  * PHP versions 4 and 5
                   64439:  *
                   64440:  * @category   pear
                   64441:  * @package    PEAR
                   64442:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   64443:  * @author     Greg Beaver <cellog@php.net>
                   64444:  * @copyright  1997-2009 The Authors
                   64445:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   64446:  * @version    CVS: $Id: DependencyDB.php 286686 2009-08-02 17:38:57Z dufuz $
                   64447:  * @link       http://pear.php.net/package/PEAR
                   64448:  * @since      File available since Release 1.4.0a1
                   64449:  */
                   64450: 
                   64451: /**
                   64452:  * Needed for error handling
                   64453:  */
                   64454: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   64455: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
                   64456: 
                   64457: $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
                   64458: /**
                   64459:  * Track dependency relationships between installed packages
                   64460:  * @category   pear
                   64461:  * @package    PEAR
                   64462:  * @author     Greg Beaver <cellog@php.net>
                   64463:  * @author     Tomas V.V.Cox <cox@idec.net.com>
                   64464:  * @copyright  1997-2009 The Authors
                   64465:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   64466:  * @version    Release: 1.10.0beta1
                   64467:  * @link       http://pear.php.net/package/PEAR
                   64468:  * @since      Class available since Release 1.4.0a1
                   64469:  */
                   64470: class PEAR_DependencyDB
                   64471: {
                   64472:     // {{{ properties
                   64473: 
                   64474:     /**
                   64475:      * This is initialized by {@link setConfig()}
                   64476:      * @var PEAR_Config
                   64477:      * @access private
                   64478:      */
                   64479:     var $_config;
                   64480:     /**
                   64481:      * This is initialized by {@link setConfig()}
                   64482:      * @var PEAR_Registry
                   64483:      * @access private
                   64484:      */
                   64485:     var $_registry;
                   64486:     /**
                   64487:      * Filename of the dependency DB (usually .depdb)
                   64488:      * @var string
                   64489:      * @access private
                   64490:      */
                   64491:     var $_depdb = false;
                   64492:     /**
                   64493:      * File name of the lockfile (usually .depdblock)
                   64494:      * @var string
                   64495:      * @access private
                   64496:      */
                   64497:     var $_lockfile = false;
                   64498:     /**
                   64499:      * Open file resource for locking the lockfile
                   64500:      * @var resource|false
                   64501:      * @access private
                   64502:      */
                   64503:     var $_lockFp = false;
                   64504:     /**
                   64505:      * API version of this class, used to validate a file on-disk
                   64506:      * @var string
                   64507:      * @access private
                   64508:      */
                   64509:     var $_version = '1.0';
                   64510:     /**
                   64511:      * Cached dependency database file
                   64512:      * @var array|null
                   64513:      * @access private
                   64514:      */
                   64515:     var $_cache;
                   64516: 
                   64517:     // }}}
                   64518:     // {{{ & singleton()
                   64519: 
                   64520:     /**
                   64521:      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
                   64522:      * @param PEAR_Config
                   64523:      * @param string|false full path to the dependency database, or false to use default
                   64524:      * @return PEAR_DependencyDB|PEAR_Error
                   64525:      * @static
                   64526:      */
                   64527:     function &singleton(&$config, $depdb = false)
                   64528:     {
                   64529:         $phpdir = $config->get('php_dir', null, 'pear.php.net');
                   64530:         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
                   64531:             $a = new PEAR_DependencyDB;
                   64532:             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
                   64533:             $a->setConfig($config, $depdb);
                   64534:             $e = $a->assertDepsDB();
                   64535:             if (PEAR::isError($e)) {
                   64536:                 return $e;
                   64537:             }
                   64538:         }
                   64539: 
                   64540:         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
                   64541:     }
                   64542: 
                   64543:     /**
                   64544:      * Set up the registry/location of dependency DB
                   64545:      * @param PEAR_Config|false
                   64546:      * @param string|false full path to the dependency database, or false to use default
                   64547:      */
                   64548:     function setConfig(&$config, $depdb = false)
                   64549:     {
                   64550:         if (!$config) {
                   64551:             $this->_config = &PEAR_Config::singleton();
                   64552:         } else {
                   64553:             $this->_config = &$config;
                   64554:         }
                   64555: 
                   64556:         $this->_registry = &$this->_config->getRegistry();
                   64557:         if (!$depdb) {
                   64558:             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
                   64559:                 DIRECTORY_SEPARATOR . '.depdb';
                   64560:         } else {
                   64561:             $this->_depdb = $depdb;
                   64562:         }
                   64563: 
                   64564:         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
                   64565:     }
                   64566:     // }}}
                   64567: 
                   64568:     function hasWriteAccess()
                   64569:     {
                   64570:         if (!file_exists($this->_depdb)) {
                   64571:             $dir = $this->_depdb;
                   64572:             while ($dir && $dir != '.') {
                   64573:                 $dir = dirname($dir); // cd ..
                   64574:                 if ($dir != '.' && file_exists($dir)) {
                   64575:                     if (is_writeable($dir)) {
                   64576:                         return true;
                   64577:                     }
                   64578: 
                   64579:                     return false;
                   64580:                 }
                   64581:             }
                   64582: 
                   64583:             return false;
                   64584:         }
                   64585: 
                   64586:         return is_writeable($this->_depdb);
                   64587:     }
                   64588: 
                   64589:     // {{{ assertDepsDB()
                   64590: 
                   64591:     /**
                   64592:      * Create the dependency database, if it doesn't exist.  Error if the database is
                   64593:      * newer than the code reading it.
                   64594:      * @return void|PEAR_Error
                   64595:      */
                   64596:     function assertDepsDB()
                   64597:     {
                   64598:         if (!is_file($this->_depdb)) {
                   64599:             $this->rebuildDB();
                   64600:             return;
                   64601:         }
                   64602: 
                   64603:         $depdb = $this->_getDepDB();
                   64604:         // Datatype format has been changed, rebuild the Deps DB
                   64605:         if ($depdb['_version'] < $this->_version) {
                   64606:             $this->rebuildDB();
                   64607:         }
                   64608: 
                   64609:         if ($depdb['_version']{0} > $this->_version{0}) {
                   64610:             return PEAR::raiseError('Dependency database is version ' .
                   64611:                 $depdb['_version'] . ', and we are version ' .
                   64612:                 $this->_version . ', cannot continue');
                   64613:         }
                   64614:     }
                   64615: 
                   64616:     /**
                   64617:      * Get a list of installed packages that depend on this package
                   64618:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   64619:      * @return array|false
                   64620:      */
                   64621:     function getDependentPackages(&$pkg)
                   64622:     {
                   64623:         $data = $this->_getDepDB();
                   64624:         if (is_object($pkg)) {
                   64625:             $channel = strtolower($pkg->getChannel());
                   64626:             $package = strtolower($pkg->getPackage());
                   64627:         } else {
                   64628:             $channel = strtolower($pkg['channel']);
                   64629:             $package = strtolower($pkg['package']);
                   64630:         }
                   64631: 
                   64632:         if (isset($data['packages'][$channel][$package])) {
                   64633:             return $data['packages'][$channel][$package];
                   64634:         }
                   64635: 
                   64636:         return false;
                   64637:     }
                   64638: 
                   64639:     /**
                   64640:      * Get a list of the actual dependencies of installed packages that depend on
                   64641:      * a package.
                   64642:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   64643:      * @return array|false
                   64644:      */
                   64645:     function getDependentPackageDependencies(&$pkg)
                   64646:     {
                   64647:         $data = $this->_getDepDB();
                   64648:         if (is_object($pkg)) {
                   64649:             $channel = strtolower($pkg->getChannel());
                   64650:             $package = strtolower($pkg->getPackage());
                   64651:         } else {
                   64652:             $channel = strtolower($pkg['channel']);
                   64653:             $package = strtolower($pkg['package']);
                   64654:         }
                   64655: 
                   64656:         $depend = $this->getDependentPackages($pkg);
                   64657:         if (!$depend) {
                   64658:             return false;
                   64659:         }
                   64660: 
                   64661:         $dependencies = array();
                   64662:         foreach ($depend as $info) {
                   64663:             $temp = $this->getDependencies($info);
                   64664:             foreach ($temp as $dep) {
                   64665:                 if (
                   64666:                     isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                   64667:                     strtolower($dep['dep']['channel']) == $channel &&
                   64668:                     strtolower($dep['dep']['name']) == $package
                   64669:                 ) {
                   64670:                     if (!isset($dependencies[$info['channel']])) {
                   64671:                         $dependencies[$info['channel']] = array();
                   64672:                     }
                   64673: 
                   64674:                     if (!isset($dependencies[$info['channel']][$info['package']])) {
                   64675:                         $dependencies[$info['channel']][$info['package']] = array();
                   64676:                     }
                   64677:                     $dependencies[$info['channel']][$info['package']][] = $dep;
                   64678:                 }
                   64679:             }
                   64680:         }
                   64681: 
                   64682:         return $dependencies;
                   64683:     }
                   64684: 
                   64685:     /**
                   64686:      * Get a list of dependencies of this installed package
                   64687:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   64688:      * @return array|false
                   64689:      */
                   64690:     function getDependencies(&$pkg)
                   64691:     {
                   64692:         if (is_object($pkg)) {
                   64693:             $channel = strtolower($pkg->getChannel());
                   64694:             $package = strtolower($pkg->getPackage());
                   64695:         } else {
                   64696:             $channel = strtolower($pkg['channel']);
                   64697:             $package = strtolower($pkg['package']);
                   64698:         }
                   64699: 
                   64700:         $data = $this->_getDepDB();
                   64701:         if (isset($data['dependencies'][$channel][$package])) {
                   64702:             return $data['dependencies'][$channel][$package];
                   64703:         }
                   64704: 
                   64705:         return false;
                   64706:     }
                   64707: 
                   64708:     /**
                   64709:      * Determine whether $parent depends on $child, near or deep
                   64710:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   64711:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   64712:      */
                   64713:     function dependsOn($parent, $child)
                   64714:     {
                   64715:         $c = array();
                   64716:         $this->_getDepDB();
                   64717:         return $this->_dependsOn($parent, $child, $c);
                   64718:     }
                   64719: 
                   64720:     function _dependsOn($parent, $child, &$checked)
                   64721:     {
                   64722:         if (is_object($parent)) {
                   64723:             $channel = strtolower($parent->getChannel());
                   64724:             $package = strtolower($parent->getPackage());
                   64725:         } else {
                   64726:             $channel = strtolower($parent['channel']);
                   64727:             $package = strtolower($parent['package']);
                   64728:         }
                   64729: 
                   64730:         if (is_object($child)) {
                   64731:             $depchannel = strtolower($child->getChannel());
                   64732:             $deppackage = strtolower($child->getPackage());
                   64733:         } else {
                   64734:             $depchannel = strtolower($child['channel']);
                   64735:             $deppackage = strtolower($child['package']);
                   64736:         }
                   64737: 
                   64738:         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
                   64739:             return false; // avoid endless recursion
                   64740:         }
                   64741: 
                   64742:         $checked[$channel][$package][$depchannel][$deppackage] = true;
                   64743:         if (!isset($this->_cache['dependencies'][$channel][$package])) {
                   64744:             return false;
                   64745:         }
                   64746: 
                   64747:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   64748:             if (isset($info['dep']['uri'])) {
                   64749:                 if (is_object($child)) {
                   64750:                     if ($info['dep']['uri'] == $child->getURI()) {
                   64751:                         return true;
                   64752:                     }
                   64753:                 } elseif (isset($child['uri'])) {
                   64754:                     if ($info['dep']['uri'] == $child['uri']) {
                   64755:                         return true;
                   64756:                     }
                   64757:                 }
                   64758:                 return false;
                   64759:             }
                   64760: 
                   64761:             if (strtolower($info['dep']['channel']) == $depchannel &&
                   64762:                   strtolower($info['dep']['name']) == $deppackage) {
                   64763:                 return true;
                   64764:             }
                   64765:         }
                   64766: 
                   64767:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   64768:             if (isset($info['dep']['uri'])) {
                   64769:                 if ($this->_dependsOn(array(
                   64770:                         'uri' => $info['dep']['uri'],
                   64771:                         'package' => $info['dep']['name']), $child, $checked)) {
                   64772:                     return true;
                   64773:                 }
                   64774:             } else {
                   64775:                 if ($this->_dependsOn(array(
                   64776:                         'channel' => $info['dep']['channel'],
                   64777:                         'package' => $info['dep']['name']), $child, $checked)) {
                   64778:                     return true;
                   64779:                 }
                   64780:             }
                   64781:         }
                   64782: 
                   64783:         return false;
                   64784:     }
                   64785: 
                   64786:     /**
                   64787:      * Register dependencies of a package that is being installed or upgraded
                   64788:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   64789:      */
                   64790:     function installPackage(&$package)
                   64791:     {
                   64792:         $data = $this->_getDepDB();
                   64793:         unset($this->_cache);
                   64794:         $this->_setPackageDeps($data, $package);
                   64795:         $this->_writeDepDB($data);
                   64796:     }
                   64797: 
                   64798:     /**
                   64799:      * Remove dependencies of a package that is being uninstalled, or upgraded.
                   64800:      *
                   64801:      * Upgraded packages first uninstall, then install
                   64802:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
                   64803:      *        indices 'channel' and 'package'
                   64804:      */
                   64805:     function uninstallPackage(&$pkg)
                   64806:     {
                   64807:         $data = $this->_getDepDB();
                   64808:         unset($this->_cache);
                   64809:         if (is_object($pkg)) {
                   64810:             $channel = strtolower($pkg->getChannel());
                   64811:             $package = strtolower($pkg->getPackage());
                   64812:         } else {
                   64813:             $channel = strtolower($pkg['channel']);
                   64814:             $package = strtolower($pkg['package']);
                   64815:         }
                   64816: 
                   64817:         if (!isset($data['dependencies'][$channel][$package])) {
                   64818:             return true;
                   64819:         }
                   64820: 
                   64821:         foreach ($data['dependencies'][$channel][$package] as $dep) {
                   64822:             $found      = false;
                   64823:             $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
                   64824:             $depname    = strtolower($dep['dep']['name']);
                   64825:             if (isset($data['packages'][$depchannel][$depname])) {
                   64826:                 foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
                   64827:                     if ($info['channel'] == $channel && $info['package'] == $package) {
                   64828:                         $found = true;
                   64829:                         break;
                   64830:                     }
                   64831:                 }
                   64832:             }
                   64833: 
                   64834:             if ($found) {
                   64835:                 unset($data['packages'][$depchannel][$depname][$i]);
                   64836:                 if (!count($data['packages'][$depchannel][$depname])) {
                   64837:                     unset($data['packages'][$depchannel][$depname]);
                   64838:                     if (!count($data['packages'][$depchannel])) {
                   64839:                         unset($data['packages'][$depchannel]);
                   64840:                     }
                   64841:                 } else {
                   64842:                     $data['packages'][$depchannel][$depname] =
                   64843:                         array_values($data['packages'][$depchannel][$depname]);
                   64844:                 }
                   64845:             }
                   64846:         }
                   64847: 
                   64848:         unset($data['dependencies'][$channel][$package]);
                   64849:         if (!count($data['dependencies'][$channel])) {
                   64850:             unset($data['dependencies'][$channel]);
                   64851:         }
                   64852: 
                   64853:         if (!count($data['dependencies'])) {
                   64854:             unset($data['dependencies']);
                   64855:         }
                   64856: 
                   64857:         if (!count($data['packages'])) {
                   64858:             unset($data['packages']);
                   64859:         }
                   64860: 
                   64861:         $this->_writeDepDB($data);
                   64862:     }
                   64863: 
                   64864:     /**
                   64865:      * Rebuild the dependency DB by reading registry entries.
                   64866:      * @return true|PEAR_Error
                   64867:      */
                   64868:     function rebuildDB()
                   64869:     {
                   64870:         $depdb = array('_version' => $this->_version);
                   64871:         if (!$this->hasWriteAccess()) {
                   64872:             // allow startup for read-only with older Registry
                   64873:             return $depdb;
                   64874:         }
                   64875: 
                   64876:         $packages = $this->_registry->listAllPackages();
                   64877:         if (PEAR::isError($packages)) {
                   64878:             return $packages;
                   64879:         }
                   64880: 
                   64881:         foreach ($packages as $channel => $ps) {
                   64882:             foreach ($ps as $package) {
                   64883:                 $package = $this->_registry->getPackage($package, $channel);
                   64884:                 if (PEAR::isError($package)) {
                   64885:                     return $package;
                   64886:                 }
                   64887:                 $this->_setPackageDeps($depdb, $package);
                   64888:             }
                   64889:         }
                   64890: 
                   64891:         $error = $this->_writeDepDB($depdb);
                   64892:         if (PEAR::isError($error)) {
                   64893:             return $error;
                   64894:         }
                   64895: 
                   64896:         $this->_cache = $depdb;
                   64897:         return true;
                   64898:     }
                   64899: 
                   64900:     /**
                   64901:      * Register usage of the dependency DB to prevent race conditions
                   64902:      * @param int one of the LOCK_* constants
                   64903:      * @return true|PEAR_Error
                   64904:      * @access private
                   64905:      */
                   64906:     function _lock($mode = LOCK_EX)
                   64907:     {
                   64908:         if (stristr(php_uname(), 'Windows 9')) {
                   64909:             return true;
                   64910:         }
                   64911: 
                   64912:         if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
                   64913:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   64914:             return true;
                   64915:         }
                   64916: 
                   64917:         $open_mode = 'w';
                   64918:         // XXX People reported problems with LOCK_SH and 'w'
                   64919:         if ($mode === LOCK_SH) {
                   64920:             if (!file_exists($this->_lockfile)) {
                   64921:                 touch($this->_lockfile);
                   64922:             } elseif (!is_file($this->_lockfile)) {
                   64923:                 return PEAR::raiseError('could not create Dependency lock file, ' .
                   64924:                     'it exists and is not a regular file');
                   64925:             }
                   64926:             $open_mode = 'r';
                   64927:         }
                   64928: 
                   64929:         if (!is_resource($this->_lockFp)) {
                   64930:             $this->_lockFp = @fopen($this->_lockfile, $open_mode);
                   64931:         }
                   64932: 
                   64933:         if (!is_resource($this->_lockFp)) {
                   64934:             return PEAR::raiseError("could not create Dependency lock file" .
                   64935:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   64936:         }
                   64937: 
                   64938:         if (!(int)flock($this->_lockFp, $mode)) {
                   64939:             switch ($mode) {
                   64940:                 case LOCK_SH: $str = 'shared';    break;
                   64941:                 case LOCK_EX: $str = 'exclusive'; break;
                   64942:                 case LOCK_UN: $str = 'unlock';    break;
                   64943:                 default:      $str = 'unknown';   break;
                   64944:             }
                   64945: 
                   64946:             return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
                   64947:         }
                   64948: 
                   64949:         return true;
                   64950:     }
                   64951: 
                   64952:     /**
                   64953:      * Release usage of dependency DB
                   64954:      * @return true|PEAR_Error
                   64955:      * @access private
                   64956:      */
                   64957:     function _unlock()
                   64958:     {
                   64959:         $ret = $this->_lock(LOCK_UN);
                   64960:         if (is_resource($this->_lockFp)) {
                   64961:             fclose($this->_lockFp);
                   64962:         }
                   64963:         $this->_lockFp = null;
                   64964:         return $ret;
                   64965:     }
                   64966: 
                   64967:     /**
                   64968:      * Load the dependency database from disk, or return the cache
                   64969:      * @return array|PEAR_Error
                   64970:      */
                   64971:     function _getDepDB()
                   64972:     {
                   64973:         if (!$this->hasWriteAccess()) {
                   64974:             return array('_version' => $this->_version);
                   64975:         }
                   64976: 
                   64977:         if (isset($this->_cache)) {
                   64978:             return $this->_cache;
                   64979:         }
                   64980: 
                   64981:         if (!$fp = fopen($this->_depdb, 'r')) {
                   64982:             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
                   64983:             return $err;
                   64984:         }
                   64985: 
                   64986:         $rt = get_magic_quotes_runtime();
                   64987:         set_magic_quotes_runtime(0);
                   64988:         clearstatcache();
                   64989:         fclose($fp);
                   64990:         $data = unserialize(file_get_contents($this->_depdb));
                   64991:         set_magic_quotes_runtime($rt);
                   64992:         $this->_cache = $data;
                   64993:         return $data;
                   64994:     }
                   64995: 
                   64996:     /**
                   64997:      * Write out the dependency database to disk
                   64998:      * @param array the database
                   64999:      * @return true|PEAR_Error
                   65000:      * @access private
                   65001:      */
                   65002:     function _writeDepDB(&$deps)
                   65003:     {
                   65004:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   65005:             return $e;
                   65006:         }
                   65007: 
                   65008:         if (!$fp = fopen($this->_depdb, 'wb')) {
                   65009:             $this->_unlock();
                   65010:             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
                   65011:         }
                   65012: 
                   65013:         $rt = get_magic_quotes_runtime();
                   65014:         set_magic_quotes_runtime(0);
                   65015:         fwrite($fp, serialize($deps));
                   65016:         set_magic_quotes_runtime($rt);
                   65017:         fclose($fp);
                   65018:         $this->_unlock();
                   65019:         $this->_cache = $deps;
                   65020:         return true;
                   65021:     }
                   65022: 
                   65023:     /**
                   65024:      * Register all dependencies from a package in the dependencies database, in essence
                   65025:      * "installing" the package's dependency information
                   65026:      * @param array the database
                   65027:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   65028:      * @access private
                   65029:      */
                   65030:     function _setPackageDeps(&$data, &$pkg)
                   65031:     {
                   65032:         $pkg->setConfig($this->_config);
                   65033:         if ($pkg->getPackagexmlVersion() == '1.0') {
                   65034:             $gen = &$pkg->getDefaultGenerator();
                   65035:             $deps = $gen->dependenciesToV2();
                   65036:         } else {
                   65037:             $deps = $pkg->getDeps(true);
                   65038:         }
                   65039: 
                   65040:         if (!$deps) {
                   65041:             return;
                   65042:         }
                   65043: 
                   65044:         if (!is_array($data)) {
                   65045:             $data = array();
                   65046:         }
                   65047: 
                   65048:         if (!isset($data['dependencies'])) {
                   65049:             $data['dependencies'] = array();
                   65050:         }
                   65051: 
                   65052:         $channel = strtolower($pkg->getChannel());
                   65053:         $package = strtolower($pkg->getPackage());
                   65054: 
                   65055:         if (!isset($data['dependencies'][$channel])) {
                   65056:             $data['dependencies'][$channel] = array();
                   65057:         }
                   65058: 
                   65059:         $data['dependencies'][$channel][$package] = array();
                   65060:         if (isset($deps['required']['package'])) {
                   65061:             if (!isset($deps['required']['package'][0])) {
                   65062:                 $deps['required']['package'] = array($deps['required']['package']);
                   65063:             }
                   65064: 
                   65065:             foreach ($deps['required']['package'] as $dep) {
                   65066:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   65067:             }
                   65068:         }
                   65069: 
                   65070:         if (isset($deps['optional']['package'])) {
                   65071:             if (!isset($deps['optional']['package'][0])) {
                   65072:                 $deps['optional']['package'] = array($deps['optional']['package']);
                   65073:             }
                   65074: 
                   65075:             foreach ($deps['optional']['package'] as $dep) {
                   65076:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   65077:             }
                   65078:         }
                   65079: 
                   65080:         if (isset($deps['required']['subpackage'])) {
                   65081:             if (!isset($deps['required']['subpackage'][0])) {
                   65082:                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
                   65083:             }
                   65084: 
                   65085:             foreach ($deps['required']['subpackage'] as $dep) {
                   65086:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   65087:             }
                   65088:         }
                   65089: 
                   65090:         if (isset($deps['optional']['subpackage'])) {
                   65091:             if (!isset($deps['optional']['subpackage'][0])) {
                   65092:                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
                   65093:             }
                   65094: 
                   65095:             foreach ($deps['optional']['subpackage'] as $dep) {
                   65096:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   65097:             }
                   65098:         }
                   65099: 
                   65100:         if (isset($deps['group'])) {
                   65101:             if (!isset($deps['group'][0])) {
                   65102:                 $deps['group'] = array($deps['group']);
                   65103:             }
                   65104: 
                   65105:             foreach ($deps['group'] as $group) {
                   65106:                 if (isset($group['package'])) {
                   65107:                     if (!isset($group['package'][0])) {
                   65108:                         $group['package'] = array($group['package']);
                   65109:                     }
                   65110: 
                   65111:                     foreach ($group['package'] as $dep) {
                   65112:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   65113:                             $group['attribs']['name']);
                   65114:                     }
                   65115:                 }
                   65116: 
                   65117:                 if (isset($group['subpackage'])) {
                   65118:                     if (!isset($group['subpackage'][0])) {
                   65119:                         $group['subpackage'] = array($group['subpackage']);
                   65120:                     }
                   65121: 
                   65122:                     foreach ($group['subpackage'] as $dep) {
                   65123:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   65124:                             $group['attribs']['name']);
                   65125:                     }
                   65126:                 }
                   65127:             }
                   65128:         }
                   65129: 
                   65130:         if ($data['dependencies'][$channel][$package] == array()) {
                   65131:             unset($data['dependencies'][$channel][$package]);
                   65132:             if (!count($data['dependencies'][$channel])) {
                   65133:                 unset($data['dependencies'][$channel]);
                   65134:             }
                   65135:         }
                   65136:     }
                   65137: 
                   65138:     /**
                   65139:      * @param array the database
                   65140:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   65141:      * @param array the specific dependency
                   65142:      * @param required|optional whether this is a required or an optional dep
                   65143:      * @param string|false dependency group this dependency is from, or false for ordinary dep
                   65144:      */
                   65145:     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
                   65146:     {
                   65147:         $info = array(
                   65148:             'dep'   => $dep,
                   65149:             'type'  => $type,
                   65150:             'group' => $group
                   65151:         );
                   65152: 
                   65153:         $dep  = array_map('strtolower', $dep);
                   65154:         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   65155:         if (!isset($data['dependencies'])) {
                   65156:             $data['dependencies'] = array();
                   65157:         }
                   65158: 
                   65159:         $channel = strtolower($pkg->getChannel());
                   65160:         $package = strtolower($pkg->getPackage());
                   65161: 
                   65162:         if (!isset($data['dependencies'][$channel])) {
                   65163:             $data['dependencies'][$channel] = array();
                   65164:         }
                   65165: 
                   65166:         if (!isset($data['dependencies'][$channel][$package])) {
                   65167:             $data['dependencies'][$channel][$package] = array();
                   65168:         }
                   65169: 
                   65170:         $data['dependencies'][$channel][$package][] = $info;
                   65171:         if (isset($data['packages'][$depchannel][$dep['name']])) {
                   65172:             $found = false;
                   65173:             foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
                   65174:                 if ($p['channel'] == $channel && $p['package'] == $package) {
                   65175:                     $found = true;
                   65176:                     break;
                   65177:                 }
                   65178:             }
                   65179:         } else {
                   65180:             if (!isset($data['packages'])) {
                   65181:                 $data['packages'] = array();
                   65182:             }
                   65183: 
                   65184:             if (!isset($data['packages'][$depchannel])) {
                   65185:                 $data['packages'][$depchannel] = array();
                   65186:             }
                   65187: 
                   65188:             if (!isset($data['packages'][$depchannel][$dep['name']])) {
                   65189:                 $data['packages'][$depchannel][$dep['name']] = array();
                   65190:             }
                   65191: 
                   65192:             $found = false;
                   65193:         }
                   65194: 
                   65195:         if (!$found) {
                   65196:             $data['packages'][$depchannel][$dep['name']][] = array(
                   65197:                 'channel' => $channel,
                   65198:                 'package' => $package
                   65199:             );
                   65200:         }
                   65201:     }
                   65202: }<?php
                   65203: /**
                   65204:  * PEAR_Downloader, the PEAR Installer's download utility class
                   65205:  *
                   65206:  * PHP versions 4 and 5
                   65207:  *
                   65208:  * @category   pear
                   65209:  * @package    PEAR
                   65210:  * @author     Greg Beaver <cellog@php.net>
                   65211:  * @author     Stig Bakken <ssb@php.net>
                   65212:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   65213:  * @author     Martin Jansen <mj@php.net>
                   65214:  * @copyright  1997-2009 The Authors
                   65215:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   65216:  * @version    CVS: $Id: Downloader.php 312909 2011-07-04 19:49:14Z dufuz $
                   65217:  * @link       http://pear.php.net/package/PEAR
                   65218:  * @since      File available since Release 1.3.0
                   65219:  */
                   65220: 
                   65221: /**
                   65222:  * Needed for constants, extending
                   65223:  */
                   65224: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   65225: 
                   65226: define('PEAR_INSTALLER_OK',       1);
                   65227: define('PEAR_INSTALLER_FAILED',   0);
                   65228: define('PEAR_INSTALLER_SKIPPED', -1);
                   65229: define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
                   65230: 
                   65231: /**
                   65232:  * Administration class used to download anything from the internet (PEAR Packages,
                   65233:  * static URLs, xml files)
                   65234:  *
                   65235:  * @category   pear
                   65236:  * @package    PEAR
                   65237:  * @author     Greg Beaver <cellog@php.net>
                   65238:  * @author     Stig Bakken <ssb@php.net>
                   65239:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   65240:  * @author     Martin Jansen <mj@php.net>
                   65241:  * @copyright  1997-2009 The Authors
                   65242:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   65243:  * @version    Release: 1.10.0beta1
                   65244:  * @link       http://pear.php.net/package/PEAR
                   65245:  * @since      Class available since Release 1.3.0
                   65246:  */
                   65247: class PEAR_Downloader extends PEAR_Common
                   65248: {
                   65249:     /**
                   65250:      * @var PEAR_Registry
                   65251:      * @access private
                   65252:      */
                   65253:     var $_registry;
                   65254: 
                   65255:     /**
                   65256:      * Preferred Installation State (snapshot, devel, alpha, beta, stable)
                   65257:      * @var string|null
                   65258:      * @access private
                   65259:      */
                   65260:     var $_preferredState;
                   65261: 
                   65262:     /**
                   65263:      * Options from command-line passed to Install.
                   65264:      *
                   65265:      * Recognized options:<br />
                   65266:      *  - onlyreqdeps   : install all required dependencies as well
                   65267:      *  - alldeps       : install all dependencies, including optional
                   65268:      *  - installroot   : base relative path to install files in
                   65269:      *  - force         : force a download even if warnings would prevent it
                   65270:      *  - nocompress    : download uncompressed tarballs
                   65271:      * @see PEAR_Command_Install
                   65272:      * @access private
                   65273:      * @var array
                   65274:      */
                   65275:     var $_options;
                   65276: 
                   65277:     /**
                   65278:      * Downloaded Packages after a call to download().
                   65279:      *
                   65280:      * Format of each entry:
                   65281:      *
                   65282:      * <code>
                   65283:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   65284:      *    'info' => array() // parsed package.xml
                   65285:      * );
                   65286:      * </code>
                   65287:      * @access private
                   65288:      * @var array
                   65289:      */
                   65290:     var $_downloadedPackages = array();
                   65291: 
                   65292:     /**
                   65293:      * Packages slated for download.
                   65294:      *
                   65295:      * This is used to prevent downloading a package more than once should it be a dependency
                   65296:      * for two packages to be installed.
                   65297:      * Format of each entry:
                   65298:      *
                   65299:      * <pre>
                   65300:      * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
                   65301:      * );
                   65302:      * </pre>
                   65303:      * @access private
                   65304:      * @var array
                   65305:      */
                   65306:     var $_toDownload = array();
                   65307: 
                   65308:     /**
                   65309:      * Array of every package installed, with names lower-cased.
                   65310:      *
                   65311:      * Format:
                   65312:      * <code>
                   65313:      * array('package1' => 0, 'package2' => 1, );
                   65314:      * </code>
                   65315:      * @var array
                   65316:      */
                   65317:     var $_installed = array();
                   65318: 
                   65319:     /**
                   65320:      * @var array
                   65321:      * @access private
                   65322:      */
                   65323:     var $_errorStack = array();
                   65324: 
                   65325:     /**
                   65326:      * @var boolean
                   65327:      * @access private
                   65328:      */
                   65329:     var $_internalDownload = false;
                   65330: 
                   65331:     /**
                   65332:      * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
                   65333:      * @var array
                   65334:      * @access private
                   65335:      */
                   65336:     var $_packageSortTree;
                   65337: 
                   65338:     /**
                   65339:      * Temporary directory, or configuration value where downloads will occur
                   65340:      * @var string
                   65341:      */
                   65342:     var $_downloadDir;
                   65343: 
                   65344:     /**
                   65345:      * @param PEAR_Frontend_*
                   65346:      * @param array
                   65347:      * @param PEAR_Config
                   65348:      */
                   65349:     function PEAR_Downloader(&$ui, $options, &$config)
                   65350:     {
                   65351:         parent::PEAR_Common();
                   65352:         $this->_options = $options;
                   65353:         $this->config = &$config;
                   65354:         $this->_preferredState = $this->config->get('preferred_state');
                   65355:         $this->ui = &$ui;
                   65356:         if (!$this->_preferredState) {
                   65357:             // don't inadvertantly use a non-set preferred_state
                   65358:             $this->_preferredState = null;
                   65359:         }
                   65360: 
                   65361:         if (isset($this->_options['installroot'])) {
                   65362:             $this->config->setInstallRoot($this->_options['installroot']);
                   65363:         }
                   65364:         $this->_registry = &$config->getRegistry();
                   65365: 
                   65366:         if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
                   65367:             $this->_installed = $this->_registry->listAllPackages();
                   65368:             foreach ($this->_installed as $key => $unused) {
                   65369:                 if (!count($unused)) {
                   65370:                     continue;
                   65371:                 }
                   65372:                 $strtolower = create_function('$a','return strtolower($a);');
                   65373:                 array_walk($this->_installed[$key], $strtolower);
                   65374:             }
                   65375:         }
                   65376:     }
                   65377: 
                   65378:     /**
                   65379:      * Attempt to discover a channel's remote capabilities from
                   65380:      * its server name
                   65381:      * @param string
                   65382:      * @return boolean
                   65383:      */
                   65384:     function discover($channel)
                   65385:     {
                   65386:         $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
                   65387:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   65388:         $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
                   65389:         if (!class_exists('System')) {
                   65390:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   65391:         }
                   65392: 
                   65393:         $tmpdir = $this->config->get('temp_dir');
                   65394:         $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
                   65395:         $a   = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   65396:         PEAR::popErrorHandling();
                   65397:         if (PEAR::isError($a)) {
                   65398:             // Attempt to fallback to https automatically.
                   65399:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   65400:             $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
                   65401:             $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   65402:             PEAR::popErrorHandling();
                   65403:             if (PEAR::isError($a)) {
                   65404:                 return false;
                   65405:             }
                   65406:         }
                   65407: 
                   65408:         list($a, $lastmodified) = $a;
                   65409:         if (!class_exists('PEAR_ChannelFile')) {
                   65410:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   65411:         }
                   65412: 
                   65413:         $b = new PEAR_ChannelFile;
                   65414:         if ($b->fromXmlFile($a)) {
                   65415:             unlink($a);
                   65416:             if ($this->config->get('auto_discover')) {
                   65417:                 $this->_registry->addChannel($b, $lastmodified);
                   65418:                 $alias = $b->getName();
                   65419:                 if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
                   65420:                     $alias = $b->getAlias();
                   65421:                 }
                   65422: 
                   65423:                 $this->log(1, 'Auto-discovered channel "' . $channel .
                   65424:                     '", alias "' . $alias . '", adding to registry');
                   65425:             }
                   65426: 
                   65427:             return true;
                   65428:         }
                   65429: 
                   65430:         unlink($a);
                   65431:         return false;
                   65432:     }
                   65433: 
                   65434:     /**
                   65435:      * For simpler unit-testing
                   65436:      * @param PEAR_Downloader
                   65437:      * @return PEAR_Downloader_Package
                   65438:      */
                   65439:     function &newDownloaderPackage(&$t)
                   65440:     {
                   65441:         if (!class_exists('PEAR_Downloader_Package')) {
                   65442:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
                   65443:         }
                   65444:         $a = &new PEAR_Downloader_Package($t);
                   65445:         return $a;
                   65446:     }
                   65447: 
                   65448:     /**
                   65449:      * For simpler unit-testing
                   65450:      * @param PEAR_Config
                   65451:      * @param array
                   65452:      * @param array
                   65453:      * @param int
                   65454:      */
                   65455:     function &getDependency2Object(&$c, $i, $p, $s)
                   65456:     {
                   65457:         if (!class_exists('PEAR_Dependency2')) {
                   65458:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   65459:         }
                   65460:         $z = &new PEAR_Dependency2($c, $i, $p, $s);
                   65461:         return $z;
                   65462:     }
                   65463: 
                   65464:     function &download($params)
                   65465:     {
                   65466:         if (!count($params)) {
                   65467:             $a = array();
                   65468:             return $a;
                   65469:         }
                   65470: 
                   65471:         if (!isset($this->_registry)) {
                   65472:             $this->_registry = &$this->config->getRegistry();
                   65473:         }
                   65474: 
                   65475:         $channelschecked = array();
                   65476:         // convert all parameters into PEAR_Downloader_Package objects
                   65477:         foreach ($params as $i => $param) {
                   65478:             $params[$i] = &$this->newDownloaderPackage($this);
                   65479:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   65480:             $err = $params[$i]->initialize($param);
                   65481:             PEAR::staticPopErrorHandling();
                   65482:             if (!$err) {
                   65483:                 // skip parameters that were missed by preferred_state
                   65484:                 continue;
                   65485:             }
                   65486: 
                   65487:             if (PEAR::isError($err)) {
                   65488:                 if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
                   65489:                     $this->log(0, $err->getMessage());
                   65490:                 }
                   65491: 
                   65492:                 $params[$i] = false;
                   65493:                 if (is_object($param)) {
                   65494:                     $param = $param->getChannel() . '/' . $param->getPackage();
                   65495:                 }
                   65496: 
                   65497:                 if (!isset($this->_options['soft'])) {
                   65498:                     $this->log(2, 'Package "' . $param . '" is not valid');
                   65499:                 }
                   65500: 
                   65501:                 // Message logged above in a specific verbose mode, passing null to not show up on CLI
                   65502:                 $this->pushError(null, PEAR_INSTALLER_SKIPPED);
                   65503:             } else {
                   65504:                 do {
                   65505:                     if ($params[$i] && $params[$i]->getType() == 'local') {
                   65506:                         // bug #7090 skip channel.xml check for local packages
                   65507:                         break;
                   65508:                     }
                   65509: 
                   65510:                     if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
                   65511:                           !isset($this->_options['offline'])
                   65512:                     ) {
                   65513:                         $channelschecked[$params[$i]->getChannel()] = true;
                   65514:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   65515:                         if (!class_exists('System')) {
                   65516:                             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   65517:                         }
                   65518: 
                   65519:                         $curchannel = &$this->_registry->getChannel($params[$i]->getChannel());
                   65520:                         if (PEAR::isError($curchannel)) {
                   65521:                             PEAR::staticPopErrorHandling();
                   65522:                             return $this->raiseError($curchannel);
                   65523:                         }
                   65524: 
                   65525:                         if (PEAR::isError($dir = $this->getDownloadDir())) {
                   65526:                             PEAR::staticPopErrorHandling();
                   65527:                             break;
                   65528:                         }
                   65529: 
                   65530:                         $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
                   65531:                         $url    = 'http://' . $mirror . '/channel.xml';
                   65532:                         $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());
                   65533: 
                   65534:                         PEAR::staticPopErrorHandling();
                   65535:                         if (PEAR::isError($a) || !$a) {
                   65536:                             // Attempt fallback to https automatically
                   65537:                             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   65538:                             $a = $this->downloadHttp('https://' . $mirror .
                   65539:                                 '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());
                   65540: 
                   65541:                             PEAR::staticPopErrorHandling();
                   65542:                             if (PEAR::isError($a) || !$a) {
                   65543:                                 break;
                   65544:                             }
                   65545:                         }
                   65546:                         $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
                   65547:                             'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
                   65548:                             '" to update');
                   65549:                     }
                   65550:                 } while (false);
                   65551: 
                   65552:                 if ($params[$i] && !isset($this->_options['downloadonly'])) {
                   65553:                     if (isset($this->_options['packagingroot'])) {
                   65554:                         $checkdir = $this->_prependPath(
                   65555:                             $this->config->get('php_dir', null, $params[$i]->getChannel()),
                   65556:                             $this->_options['packagingroot']);
                   65557:                     } else {
                   65558:                         $checkdir = $this->config->get('php_dir',
                   65559:                             null, $params[$i]->getChannel());
                   65560:                     }
                   65561: 
                   65562:                     while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
                   65563:                         $checkdir = dirname($checkdir);
                   65564:                     }
                   65565: 
                   65566:                     if ($checkdir == '.') {
                   65567:                         $checkdir = '/';
                   65568:                     }
                   65569: 
                   65570:                     if (!is_writeable($checkdir)) {
                   65571:                         return PEAR::raiseError('Cannot install, php_dir for channel "' .
                   65572:                             $params[$i]->getChannel() . '" is not writeable by the current user');
                   65573:                     }
                   65574:                 }
                   65575:             }
                   65576:         }
                   65577: 
                   65578:         unset($channelschecked);
                   65579:         PEAR_Downloader_Package::removeDuplicates($params);
                   65580:         if (!count($params)) {
                   65581:             $a = array();
                   65582:             return $a;
                   65583:         }
                   65584: 
                   65585:         if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
                   65586:             $reverify = true;
                   65587:             while ($reverify) {
                   65588:                 $reverify = false;
                   65589:                 foreach ($params as $i => $param) {
                   65590:                     //PHP Bug 40768 / PEAR Bug #10944
                   65591:                     //Nested foreaches fail in PHP 5.2.1
                   65592:                     key($params);
                   65593:                     $ret = $params[$i]->detectDependencies($params);
                   65594:                     if (PEAR::isError($ret)) {
                   65595:                         $reverify = true;
                   65596:                         $params[$i] = false;
                   65597:                         PEAR_Downloader_Package::removeDuplicates($params);
                   65598:                         if (!isset($this->_options['soft'])) {
                   65599:                             $this->log(0, $ret->getMessage());
                   65600:                         }
                   65601:                         continue 2;
                   65602:                     }
                   65603:                 }
                   65604:             }
                   65605:         }
                   65606: 
                   65607:         if (isset($this->_options['offline'])) {
                   65608:             $this->log(3, 'Skipping dependency download check, --offline specified');
                   65609:         }
                   65610: 
                   65611:         if (!count($params)) {
                   65612:             $a = array();
                   65613:             return $a;
                   65614:         }
                   65615: 
                   65616:         while (PEAR_Downloader_Package::mergeDependencies($params));
                   65617:         PEAR_Downloader_Package::removeDuplicates($params, true);
                   65618:         $errorparams = array();
                   65619:         if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
                   65620:             if (count($errorparams)) {
                   65621:                 foreach ($errorparams as $param) {
                   65622:                     $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
                   65623:                     $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
                   65624:                 }
                   65625:                 $a = array();
                   65626:                 return $a;
                   65627:             }
                   65628:         }
                   65629: 
                   65630:         PEAR_Downloader_Package::removeInstalled($params);
                   65631:         if (!count($params)) {
                   65632:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   65633:             $a = array();
                   65634:             return $a;
                   65635:         }
                   65636: 
                   65637:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   65638:         $err = $this->analyzeDependencies($params);
                   65639:         PEAR::popErrorHandling();
                   65640:         if (!count($params)) {
                   65641:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   65642:             $a = array();
                   65643:             return $a;
                   65644:         }
                   65645: 
                   65646:         $ret = array();
                   65647:         $newparams = array();
                   65648:         if (isset($this->_options['pretend'])) {
                   65649:             return $params;
                   65650:         }
                   65651: 
                   65652:         $somefailed = false;
                   65653:         foreach ($params as $i => $package) {
                   65654:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   65655:             $pf = &$params[$i]->download();
                   65656:             PEAR::staticPopErrorHandling();
                   65657:             if (PEAR::isError($pf)) {
                   65658:                 if (!isset($this->_options['soft'])) {
                   65659:                     $this->log(1, $pf->getMessage());
                   65660:                     $this->log(0, 'Error: cannot download "' .
                   65661:                         $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
                   65662:                             true) .
                   65663:                         '"');
                   65664:                 }
                   65665:                 $somefailed = true;
                   65666:                 continue;
                   65667:             }
                   65668: 
                   65669:             $newparams[] = &$params[$i];
                   65670:             $ret[] = array(
                   65671:                 'file' => $pf->getArchiveFile(),
                   65672:                 'info' => &$pf,
                   65673:                 'pkg'  => $pf->getPackage()
                   65674:             );
                   65675:         }
                   65676: 
                   65677:         if ($somefailed) {
                   65678:             // remove params that did not download successfully
                   65679:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   65680:             $err = $this->analyzeDependencies($newparams, true);
                   65681:             PEAR::popErrorHandling();
                   65682:             if (!count($newparams)) {
                   65683:                 $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
                   65684:                 $a = array();
                   65685:                 return $a;
                   65686:             }
                   65687:         }
                   65688: 
                   65689:         $this->_downloadedPackages = $ret;
                   65690:         return $newparams;
                   65691:     }
                   65692: 
                   65693:     /**
                   65694:      * @param array all packages to be installed
                   65695:      */
                   65696:     function analyzeDependencies(&$params, $force = false)
                   65697:     {
                   65698:         if (isset($this->_options['downloadonly'])) {
                   65699:             return;
                   65700:         }
                   65701: 
                   65702:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   65703:         $redo  = true;
                   65704:         $reset = $hasfailed = $failed = false;
                   65705:         while ($redo) {
                   65706:             $redo = false;
                   65707:             foreach ($params as $i => $param) {
                   65708:                 $deps = $param->getDeps();
                   65709:                 if (!$deps) {
                   65710:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   65711:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   65712:                     $send = $param->getPackageFile();
                   65713: 
                   65714:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   65715:                     if (PEAR::isError($installcheck)) {
                   65716:                         if (!isset($this->_options['soft'])) {
                   65717:                             $this->log(0, $installcheck->getMessage());
                   65718:                         }
                   65719:                         $hasfailed  = true;
                   65720:                         $params[$i] = false;
                   65721:                         $reset      = true;
                   65722:                         $redo       = true;
                   65723:                         $failed     = false;
                   65724:                         PEAR_Downloader_Package::removeDuplicates($params);
                   65725:                         continue 2;
                   65726:                     }
                   65727:                     continue;
                   65728:                 }
                   65729: 
                   65730:                 if (!$reset && $param->alreadyValidated() && !$force) {
                   65731:                     continue;
                   65732:                 }
                   65733: 
                   65734:                 if (count($deps)) {
                   65735:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   65736:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   65737:                     $send = $param->getPackageFile();
                   65738:                     if ($send === null) {
                   65739:                         $send = $param->getDownloadURL();
                   65740:                     }
                   65741: 
                   65742:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   65743:                     if (PEAR::isError($installcheck)) {
                   65744:                         if (!isset($this->_options['soft'])) {
                   65745:                             $this->log(0, $installcheck->getMessage());
                   65746:                         }
                   65747:                         $hasfailed  = true;
                   65748:                         $params[$i] = false;
                   65749:                         $reset      = true;
                   65750:                         $redo       = true;
                   65751:                         $failed     = false;
                   65752:                         PEAR_Downloader_Package::removeDuplicates($params);
                   65753:                         continue 2;
                   65754:                     }
                   65755: 
                   65756:                     $failed = false;
                   65757:                     if (isset($deps['required']) && is_array($deps['required'])) {
                   65758:                         foreach ($deps['required'] as $type => $dep) {
                   65759:                             // note: Dependency2 will never return a PEAR_Error if ignore-errors
                   65760:                             // is specified, so soft is needed to turn off logging
                   65761:                             if (!isset($dep[0])) {
                   65762:                                 if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
                   65763:                                       true, $params))) {
                   65764:                                     $failed = true;
                   65765:                                     if (!isset($this->_options['soft'])) {
                   65766:                                         $this->log(0, $e->getMessage());
                   65767:                                     }
                   65768:                                 } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65769:                                     if (!isset($this->_options['soft'])) {
                   65770:                                         $this->log(0, $e[0]);
                   65771:                                     }
                   65772:                                 }
                   65773:                             } else {
                   65774:                                 foreach ($dep as $d) {
                   65775:                                     if (PEAR::isError($e =
                   65776:                                           $depchecker->{"validate{$type}Dependency"}($d,
                   65777:                                           true, $params))) {
                   65778:                                         $failed = true;
                   65779:                                         if (!isset($this->_options['soft'])) {
                   65780:                                             $this->log(0, $e->getMessage());
                   65781:                                         }
                   65782:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65783:                                         if (!isset($this->_options['soft'])) {
                   65784:                                             $this->log(0, $e[0]);
                   65785:                                         }
                   65786:                                     }
                   65787:                                 }
                   65788:                             }
                   65789:                         }
                   65790: 
                   65791:                         if (isset($deps['optional']) && is_array($deps['optional'])) {
                   65792:                             foreach ($deps['optional'] as $type => $dep) {
                   65793:                                 if (!isset($dep[0])) {
                   65794:                                     if (PEAR::isError($e =
                   65795:                                           $depchecker->{"validate{$type}Dependency"}($dep,
                   65796:                                           false, $params))) {
                   65797:                                         $failed = true;
                   65798:                                         if (!isset($this->_options['soft'])) {
                   65799:                                             $this->log(0, $e->getMessage());
                   65800:                                         }
                   65801:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65802:                                         if (!isset($this->_options['soft'])) {
                   65803:                                             $this->log(0, $e[0]);
                   65804:                                         }
                   65805:                                     }
                   65806:                                 } else {
                   65807:                                     foreach ($dep as $d) {
                   65808:                                         if (PEAR::isError($e =
                   65809:                                               $depchecker->{"validate{$type}Dependency"}($d,
                   65810:                                               false, $params))) {
                   65811:                                             $failed = true;
                   65812:                                             if (!isset($this->_options['soft'])) {
                   65813:                                                 $this->log(0, $e->getMessage());
                   65814:                                             }
                   65815:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65816:                                             if (!isset($this->_options['soft'])) {
                   65817:                                                 $this->log(0, $e[0]);
                   65818:                                             }
                   65819:                                         }
                   65820:                                     }
                   65821:                                 }
                   65822:                             }
                   65823:                         }
                   65824: 
                   65825:                         $groupname = $param->getGroup();
                   65826:                         if (isset($deps['group']) && $groupname) {
                   65827:                             if (!isset($deps['group'][0])) {
                   65828:                                 $deps['group'] = array($deps['group']);
                   65829:                             }
                   65830: 
                   65831:                             $found = false;
                   65832:                             foreach ($deps['group'] as $group) {
                   65833:                                 if ($group['attribs']['name'] == $groupname) {
                   65834:                                     $found = true;
                   65835:                                     break;
                   65836:                                 }
                   65837:                             }
                   65838: 
                   65839:                             if ($found) {
                   65840:                                 unset($group['attribs']);
                   65841:                                 foreach ($group as $type => $dep) {
                   65842:                                     if (!isset($dep[0])) {
                   65843:                                         if (PEAR::isError($e =
                   65844:                                               $depchecker->{"validate{$type}Dependency"}($dep,
                   65845:                                               false, $params))) {
                   65846:                                             $failed = true;
                   65847:                                             if (!isset($this->_options['soft'])) {
                   65848:                                                 $this->log(0, $e->getMessage());
                   65849:                                             }
                   65850:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65851:                                             if (!isset($this->_options['soft'])) {
                   65852:                                                 $this->log(0, $e[0]);
                   65853:                                             }
                   65854:                                         }
                   65855:                                     } else {
                   65856:                                         foreach ($dep as $d) {
                   65857:                                             if (PEAR::isError($e =
                   65858:                                                   $depchecker->{"validate{$type}Dependency"}($d,
                   65859:                                                   false, $params))) {
                   65860:                                                 $failed = true;
                   65861:                                                 if (!isset($this->_options['soft'])) {
                   65862:                                                     $this->log(0, $e->getMessage());
                   65863:                                                 }
                   65864:                                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65865:                                                 if (!isset($this->_options['soft'])) {
                   65866:                                                     $this->log(0, $e[0]);
                   65867:                                                 }
                   65868:                                             }
                   65869:                                         }
                   65870:                                     }
                   65871:                                 }
                   65872:                             }
                   65873:                         }
                   65874:                     } else {
                   65875:                         foreach ($deps as $dep) {
                   65876:                             if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
                   65877:                                 $failed = true;
                   65878:                                 if (!isset($this->_options['soft'])) {
                   65879:                                     $this->log(0, $e->getMessage());
                   65880:                                 }
                   65881:                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   65882:                                 if (!isset($this->_options['soft'])) {
                   65883:                                     $this->log(0, $e[0]);
                   65884:                                 }
                   65885:                             }
                   65886:                         }
                   65887:                     }
                   65888:                     $params[$i]->setValidated();
                   65889:                 }
                   65890: 
                   65891:                 if ($failed) {
                   65892:                     $hasfailed  = true;
                   65893:                     $params[$i] = false;
                   65894:                     $reset      = true;
                   65895:                     $redo       = true;
                   65896:                     $failed     = false;
                   65897:                     PEAR_Downloader_Package::removeDuplicates($params);
                   65898:                     continue 2;
                   65899:                 }
                   65900:             }
                   65901:         }
                   65902: 
                   65903:         PEAR::staticPopErrorHandling();
                   65904:         if ($hasfailed && (isset($this->_options['ignore-errors']) ||
                   65905:               isset($this->_options['nodeps']))) {
                   65906:             // this is probably not needed, but just in case
                   65907:             if (!isset($this->_options['soft'])) {
                   65908:                 $this->log(0, 'WARNING: dependencies failed');
                   65909:             }
                   65910:         }
                   65911:     }
                   65912: 
                   65913:     /**
                   65914:      * Retrieve the directory that downloads will happen in
                   65915:      * @access private
                   65916:      * @return string
                   65917:      */
                   65918:     function getDownloadDir()
                   65919:     {
                   65920:         if (isset($this->_downloadDir)) {
                   65921:             return $this->_downloadDir;
                   65922:         }
                   65923: 
                   65924:         $downloaddir = $this->config->get('download_dir');
                   65925:         if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
                   65926:             if  (is_dir($downloaddir) && !is_writable($downloaddir)) {
                   65927:                 $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
                   65928:                     '" is not writeable.  Change download_dir config variable to ' .
                   65929:                     'a writeable dir to avoid this warning');
                   65930:             }
                   65931: 
                   65932:             if (!class_exists('System')) {
                   65933:                 require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   65934:             }
                   65935: 
                   65936:             if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
                   65937:                 return $downloaddir;
                   65938:             }
                   65939:             $this->log(3, '+ tmp dir created at ' . $downloaddir);
                   65940:         }
                   65941: 
                   65942:         if (!is_writable($downloaddir)) {
                   65943:             if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
                   65944:                   !is_writable($downloaddir)) {
                   65945:                 return PEAR::raiseError('download directory "' . $downloaddir .
                   65946:                     '" is not writeable.  Change download_dir config variable to ' .
                   65947:                     'a writeable dir');
                   65948:             }
                   65949:         }
                   65950: 
                   65951:         return $this->_downloadDir = $downloaddir;
                   65952:     }
                   65953: 
                   65954:     function setDownloadDir($dir)
                   65955:     {
                   65956:         if (!@is_writable($dir)) {
                   65957:             if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
                   65958:                 return PEAR::raiseError('download directory "' . $dir .
                   65959:                     '" is not writeable.  Change download_dir config variable to ' .
                   65960:                     'a writeable dir');
                   65961:             }
                   65962:         }
                   65963:         $this->_downloadDir = $dir;
                   65964:     }
                   65965: 
                   65966:     function configSet($key, $value, $layer = 'user', $channel = false)
                   65967:     {
                   65968:         $this->config->set($key, $value, $layer, $channel);
                   65969:         $this->_preferredState = $this->config->get('preferred_state', null, $channel);
                   65970:         if (!$this->_preferredState) {
                   65971:             // don't inadvertantly use a non-set preferred_state
                   65972:             $this->_preferredState = null;
                   65973:         }
                   65974:     }
                   65975: 
                   65976:     function setOptions($options)
                   65977:     {
                   65978:         $this->_options = $options;
                   65979:     }
                   65980: 
                   65981:     function getOptions()
                   65982:     {
                   65983:         return $this->_options;
                   65984:     }
                   65985: 
                   65986: 
                   65987:     /**
                   65988:      * @param array output of {@link parsePackageName()}
                   65989:      * @access private
                   65990:      */
                   65991:     function _getPackageDownloadUrl($parr)
                   65992:     {
                   65993:         $curchannel = $this->config->get('default_channel');
                   65994:         $this->configSet('default_channel', $parr['channel']);
                   65995:         // getDownloadURL returns an array.  On error, it only contains information
                   65996:         // on the latest release as array(version, info).  On success it contains
                   65997:         // array(version, info, download url string)
                   65998:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   65999:         if (!$this->_registry->channelExists($parr['channel'])) {
                   66000:             do {
                   66001:                 if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
                   66002:                     break;
                   66003:                 }
                   66004: 
                   66005:                 $this->configSet('default_channel', $curchannel);
                   66006:                 return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
                   66007:             } while (false);
                   66008:         }
                   66009: 
                   66010:         $chan = &$this->_registry->getChannel($parr['channel']);
                   66011:         if (PEAR::isError($chan)) {
                   66012:             return $chan;
                   66013:         }
                   66014: 
                   66015:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   66016:         $version   = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
                   66017:         $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
                   66018:         // package is installed - use the installed release stability level
                   66019:         if (!isset($parr['state']) && $stability !== null) {
                   66020:             $state = $stability['release'];
                   66021:         }
                   66022:         PEAR::staticPopErrorHandling();
                   66023:         $base2 = false;
                   66024: 
                   66025:         $preferred_mirror = $this->config->get('preferred_mirror');
                   66026:         if (!$chan->supportsREST($preferred_mirror) ||
                   66027:               (
                   66028:                !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
                   66029:                &&
                   66030:                !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   66031:               )
                   66032:         ) {
                   66033:             return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   66034:         }
                   66035: 
                   66036:         if ($base2) {
                   66037:             $rest = &$this->config->getREST('1.3', $this->_options);
                   66038:             $base = $base2;
                   66039:         } else {
                   66040:             $rest = &$this->config->getREST('1.0', $this->_options);
                   66041:         }
                   66042: 
                   66043:         $downloadVersion = false;
                   66044:         if (!isset($parr['version']) && !isset($parr['state']) && $version
                   66045:               && !PEAR::isError($version)
                   66046:               && !isset($this->_options['downloadonly'])
                   66047:         ) {
                   66048:             $downloadVersion = $version;
                   66049:         }
                   66050: 
                   66051:         $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
                   66052:         if (PEAR::isError($url)) {
                   66053:             $this->configSet('default_channel', $curchannel);
                   66054:             return $url;
                   66055:         }
                   66056: 
                   66057:         if ($parr['channel'] != $curchannel) {
                   66058:             $this->configSet('default_channel', $curchannel);
                   66059:         }
                   66060: 
                   66061:         if (!is_array($url)) {
                   66062:             return $url;
                   66063:         }
                   66064: 
                   66065:         $url['raw'] = false; // no checking is necessary for REST
                   66066:         if (!is_array($url['info'])) {
                   66067:             return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   66068:                 'this should never happen');
                   66069:         }
                   66070: 
                   66071:         if (!isset($this->_options['force']) &&
                   66072:               !isset($this->_options['downloadonly']) &&
                   66073:               $version &&
                   66074:               !PEAR::isError($version) &&
                   66075:               !isset($parr['group'])
                   66076:         ) {
                   66077:             if (version_compare($version, $url['version'], '=')) {
                   66078:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   66079:                     $parr, true) . ' is already installed and is the same as the ' .
                   66080:                     'released version ' . $url['version'], -976);
                   66081:             }
                   66082: 
                   66083:             if (version_compare($version, $url['version'], '>')) {
                   66084:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   66085:                     $parr, true) . ' is already installed and is newer than detected ' .
                   66086:                     'released version ' . $url['version'], -976);
                   66087:             }
                   66088:         }
                   66089: 
                   66090:         if (isset($url['info']['required']) || $url['compatible']) {
                   66091:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   66092:             $pf = new PEAR_PackageFile_v2;
                   66093:             $pf->setRawChannel($parr['channel']);
                   66094:             if ($url['compatible']) {
                   66095:                 $pf->setRawCompatible($url['compatible']);
                   66096:             }
                   66097:         } else {
                   66098:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   66099:             $pf = new PEAR_PackageFile_v1;
                   66100:         }
                   66101: 
                   66102:         $pf->setRawPackage($url['package']);
                   66103:         $pf->setDeps($url['info']);
                   66104:         if ($url['compatible']) {
                   66105:             $pf->setCompatible($url['compatible']);
                   66106:         }
                   66107: 
                   66108:         $pf->setRawState($url['stability']);
                   66109:         $url['info'] = &$pf;
                   66110:         if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   66111:             $ext = '.tar';
                   66112:         } else {
                   66113:             $ext = '.tgz';
                   66114:         }
                   66115: 
                   66116:         if (is_array($url) && isset($url['url'])) {
                   66117:             $url['url'] .= $ext;
                   66118:         }
                   66119: 
                   66120:         return $url;
                   66121:     }
                   66122: 
                   66123:     /**
                   66124:      * @param array dependency array
                   66125:      * @access private
                   66126:      */
                   66127:     function _getDepPackageDownloadUrl($dep, $parr)
                   66128:     {
                   66129:         $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
                   66130:         $curchannel = $this->config->get('default_channel');
                   66131:         if (isset($dep['uri'])) {
                   66132:             $xsdversion = '2.0';
                   66133:             $chan = &$this->_registry->getChannel('__uri');
                   66134:             if (PEAR::isError($chan)) {
                   66135:                 return $chan;
                   66136:             }
                   66137: 
                   66138:             $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
                   66139:             $this->configSet('default_channel', '__uri');
                   66140:         } else {
                   66141:             if (isset($dep['channel'])) {
                   66142:                 $remotechannel = $dep['channel'];
                   66143:             } else {
                   66144:                 $remotechannel = 'pear.php.net';
                   66145:             }
                   66146: 
                   66147:             if (!$this->_registry->channelExists($remotechannel)) {
                   66148:                 do {
                   66149:                     if ($this->config->get('auto_discover')) {
                   66150:                         if ($this->discover($remotechannel)) {
                   66151:                             break;
                   66152:                         }
                   66153:                     }
                   66154:                     return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
                   66155:                 } while (false);
                   66156:             }
                   66157: 
                   66158:             $chan = &$this->_registry->getChannel($remotechannel);
                   66159:             if (PEAR::isError($chan)) {
                   66160:                 return $chan;
                   66161:             }
                   66162: 
                   66163:             $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
                   66164:             $this->configSet('default_channel', $remotechannel);
                   66165:         }
                   66166: 
                   66167:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   66168:         if (isset($parr['state']) && isset($parr['version'])) {
                   66169:             unset($parr['state']);
                   66170:         }
                   66171: 
                   66172:         if (isset($dep['uri'])) {
                   66173:             $info = &$this->newDownloaderPackage($this);
                   66174:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   66175:             $err = $info->initialize($dep);
                   66176:             PEAR::staticPopErrorHandling();
                   66177:             if (!$err) {
                   66178:                 // skip parameters that were missed by preferred_state
                   66179:                 return PEAR::raiseError('Cannot initialize dependency');
                   66180:             }
                   66181: 
                   66182:             if (PEAR::isError($err)) {
                   66183:                 if (!isset($this->_options['soft'])) {
                   66184:                     $this->log(0, $err->getMessage());
                   66185:                 }
                   66186: 
                   66187:                 if (is_object($info)) {
                   66188:                     $param = $info->getChannel() . '/' . $info->getPackage();
                   66189:                 }
                   66190:                 return PEAR::raiseError('Package "' . $param . '" is not valid');
                   66191:             }
                   66192:             return $info;
                   66193:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
                   66194:               &&
                   66195:                 (
                   66196:                   ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
                   66197:                     ||
                   66198:                   ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
                   66199:                 )
                   66200:         ) {
                   66201:             if ($base2) {
                   66202:                 $base = $base2;
                   66203:                 $rest = &$this->config->getREST('1.3', $this->_options);
                   66204:             } else {
                   66205:                 $rest = &$this->config->getREST('1.0', $this->_options);
                   66206:             }
                   66207: 
                   66208:             $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
                   66209:                     $state, $version, $chan->getName());
                   66210:             if (PEAR::isError($url)) {
                   66211:                 return $url;
                   66212:             }
                   66213: 
                   66214:             if ($parr['channel'] != $curchannel) {
                   66215:                 $this->configSet('default_channel', $curchannel);
                   66216:             }
                   66217: 
                   66218:             if (!is_array($url)) {
                   66219:                 return $url;
                   66220:             }
                   66221: 
                   66222:             $url['raw'] = false; // no checking is necessary for REST
                   66223:             if (!is_array($url['info'])) {
                   66224:                 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   66225:                     'this should never happen');
                   66226:             }
                   66227: 
                   66228:             if (isset($url['info']['required'])) {
                   66229:                 if (!class_exists('PEAR_PackageFile_v2')) {
                   66230:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   66231:                 }
                   66232:                 $pf = new PEAR_PackageFile_v2;
                   66233:                 $pf->setRawChannel($remotechannel);
                   66234:             } else {
                   66235:                 if (!class_exists('PEAR_PackageFile_v1')) {
                   66236:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   66237:                 }
                   66238:                 $pf = new PEAR_PackageFile_v1;
                   66239: 
                   66240:             }
                   66241:             $pf->setRawPackage($url['package']);
                   66242:             $pf->setDeps($url['info']);
                   66243:             if ($url['compatible']) {
                   66244:                 $pf->setCompatible($url['compatible']);
                   66245:             }
                   66246: 
                   66247:             $pf->setRawState($url['stability']);
                   66248:             $url['info'] = &$pf;
                   66249:             if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   66250:                 $ext = '.tar';
                   66251:             } else {
                   66252:                 $ext = '.tgz';
                   66253:             }
                   66254: 
                   66255:             if (is_array($url) && isset($url['url'])) {
                   66256:                 $url['url'] .= $ext;
                   66257:             }
                   66258: 
                   66259:             return $url;
                   66260:         }
                   66261: 
                   66262:         return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   66263:     }
                   66264: 
                   66265:     /**
                   66266:      * @deprecated in favor of _getPackageDownloadUrl
                   66267:      */
                   66268:     function getPackageDownloadUrl($package, $version = null, $channel = false)
                   66269:     {
                   66270:         if ($version) {
                   66271:             $package .= "-$version";
                   66272:         }
                   66273:         if ($this === null || $this->_registry === null) {
                   66274:             $package = "http://pear.php.net/get/$package";
                   66275:         } else {
                   66276:             $chan = $this->_registry->getChannel($channel);
                   66277:             if (PEAR::isError($chan)) {
                   66278:                 return '';
                   66279:             }
                   66280:             $package = "http://" . $chan->getServer() . "/get/$package";
                   66281:         }
                   66282:         if (!extension_loaded("zlib")) {
                   66283:             $package .= '?uncompress=yes';
                   66284:         }
                   66285:         return $package;
                   66286:     }
                   66287: 
                   66288:     /**
                   66289:      * Retrieve a list of downloaded packages after a call to {@link download()}.
                   66290:      *
                   66291:      * Also resets the list of downloaded packages.
                   66292:      * @return array
                   66293:      */
                   66294:     function getDownloadedPackages()
                   66295:     {
                   66296:         $ret = $this->_downloadedPackages;
                   66297:         $this->_downloadedPackages = array();
                   66298:         $this->_toDownload = array();
                   66299:         return $ret;
                   66300:     }
                   66301: 
                   66302:     function _downloadCallback($msg, $params = null)
                   66303:     {
                   66304:         switch ($msg) {
                   66305:             case 'saveas':
                   66306:                 $this->log(1, "downloading $params ...");
                   66307:                 break;
                   66308:             case 'done':
                   66309:                 $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
                   66310:                 break;
                   66311:             case 'bytesread':
                   66312:                 static $bytes;
                   66313:                 if (empty($bytes)) {
                   66314:                     $bytes = 0;
                   66315:                 }
                   66316:                 if (!($bytes % 10240)) {
                   66317:                     $this->log(1, '.', false);
                   66318:                 }
                   66319:                 $bytes += $params;
                   66320:                 break;
                   66321:             case 'start':
                   66322:                 if($params[1] == -1) {
                   66323:                     $length = "Unknown size";
                   66324:                 } else {
                   66325:                     $length = number_format($params[1], 0, '', ',')." bytes";
                   66326:                 }
                   66327:                 $this->log(1, "Starting to download {$params[0]} ($length)");
                   66328:                 break;
                   66329:         }
                   66330:         if (method_exists($this->ui, '_downloadCallback'))
                   66331:             $this->ui->_downloadCallback($msg, $params);
                   66332:     }
                   66333: 
                   66334:     function _prependPath($path, $prepend)
                   66335:     {
                   66336:         if (strlen($prepend) > 0) {
                   66337:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   66338:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   66339:                     $prepend = substr($prepend, 2);
                   66340:                 } elseif ($prepend{0} != '\\') {
                   66341:                     $prepend = "\\$prepend";
                   66342:                 }
                   66343:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   66344:             } else {
                   66345:                 $path = $prepend . $path;
                   66346:             }
                   66347:         }
                   66348:         return $path;
                   66349:     }
                   66350: 
                   66351:     /**
                   66352:      * @param string
                   66353:      * @param integer
                   66354:      */
                   66355:     function pushError($errmsg, $code = -1)
                   66356:     {
                   66357:         array_push($this->_errorStack, array($errmsg, $code));
                   66358:     }
                   66359: 
                   66360:     function getErrorMsgs()
                   66361:     {
                   66362:         $msgs = array();
                   66363:         $errs = $this->_errorStack;
                   66364:         foreach ($errs as $err) {
                   66365:             $msgs[] = $err[0];
                   66366:         }
                   66367:         $this->_errorStack = array();
                   66368:         return $msgs;
                   66369:     }
                   66370: 
                   66371:     /**
                   66372:      * for BC
                   66373:      *
                   66374:      * @deprecated
                   66375:      */
                   66376:     function sortPkgDeps(&$packages, $uninstall = false)
                   66377:     {
                   66378:         $uninstall ?
                   66379:             $this->sortPackagesForUninstall($packages) :
                   66380:             $this->sortPackagesForInstall($packages);
                   66381:     }
                   66382: 
                   66383:     /**
                   66384:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   66385:      *
                   66386:      * This uses the topological sort method from graph theory, and the
                   66387:      * Structures_Graph package to properly sort dependencies for installation.
                   66388:      * @param array an array of downloaded PEAR_Downloader_Packages
                   66389:      * @return array array of array(packagefilename, package.xml contents)
                   66390:      */
                   66391:     function sortPackagesForInstall(&$packages)
                   66392:     {
                   66393:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   66394:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   66395:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Manipulator/TopologicalSorter.php';
                   66396:         $depgraph = new Structures_Graph(true);
                   66397:         $nodes = array();
                   66398:         $reg = &$this->config->getRegistry();
                   66399:         foreach ($packages as $i => $package) {
                   66400:             $pname = $reg->parsedPackageNameToString(
                   66401:                 array(
                   66402:                     'channel' => $package->getChannel(),
                   66403:                     'package' => strtolower($package->getPackage()),
                   66404:                 ));
                   66405:             $nodes[$pname] = new Structures_Graph_Node;
                   66406:             $nodes[$pname]->setData($packages[$i]);
                   66407:             $depgraph->addNode($nodes[$pname]);
                   66408:         }
                   66409: 
                   66410:         $deplinks = array();
                   66411:         foreach ($nodes as $package => $node) {
                   66412:             $pf = &$node->getData();
                   66413:             $pdeps = $pf->getDeps(true);
                   66414:             if (!$pdeps) {
                   66415:                 continue;
                   66416:             }
                   66417: 
                   66418:             if ($pf->getPackagexmlVersion() == '1.0') {
                   66419:                 foreach ($pdeps as $dep) {
                   66420:                     if ($dep['type'] != 'pkg' ||
                   66421:                           (isset($dep['optional']) && $dep['optional'] == 'yes')) {
                   66422:                         continue;
                   66423:                     }
                   66424: 
                   66425:                     $dname = $reg->parsedPackageNameToString(
                   66426:                           array(
                   66427:                               'channel' => 'pear.php.net',
                   66428:                               'package' => strtolower($dep['name']),
                   66429:                           ));
                   66430: 
                   66431:                     if (isset($nodes[$dname])) {
                   66432:                         if (!isset($deplinks[$dname])) {
                   66433:                             $deplinks[$dname] = array();
                   66434:                         }
                   66435: 
                   66436:                         $deplinks[$dname][$package] = 1;
                   66437:                         // dependency is in installed packages
                   66438:                         continue;
                   66439:                     }
                   66440: 
                   66441:                     $dname = $reg->parsedPackageNameToString(
                   66442:                           array(
                   66443:                               'channel' => 'pecl.php.net',
                   66444:                               'package' => strtolower($dep['name']),
                   66445:                           ));
                   66446: 
                   66447:                     if (isset($nodes[$dname])) {
                   66448:                         if (!isset($deplinks[$dname])) {
                   66449:                             $deplinks[$dname] = array();
                   66450:                         }
                   66451: 
                   66452:                         $deplinks[$dname][$package] = 1;
                   66453:                         // dependency is in installed packages
                   66454:                         continue;
                   66455:                     }
                   66456:                 }
                   66457:             } else {
                   66458:                 // the only ordering we care about is:
                   66459:                 // 1) subpackages must be installed before packages that depend on them
                   66460:                 // 2) required deps must be installed before packages that depend on them
                   66461:                 if (isset($pdeps['required']['subpackage'])) {
                   66462:                     $t = $pdeps['required']['subpackage'];
                   66463:                     if (!isset($t[0])) {
                   66464:                         $t = array($t);
                   66465:                     }
                   66466: 
                   66467:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   66468:                 }
                   66469: 
                   66470:                 if (isset($pdeps['group'])) {
                   66471:                     if (!isset($pdeps['group'][0])) {
                   66472:                         $pdeps['group'] = array($pdeps['group']);
                   66473:                     }
                   66474: 
                   66475:                     foreach ($pdeps['group'] as $group) {
                   66476:                         if (isset($group['subpackage'])) {
                   66477:                             $t = $group['subpackage'];
                   66478:                             if (!isset($t[0])) {
                   66479:                                 $t = array($t);
                   66480:                             }
                   66481: 
                   66482:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   66483:                         }
                   66484:                     }
                   66485:                 }
                   66486: 
                   66487:                 if (isset($pdeps['optional']['subpackage'])) {
                   66488:                     $t = $pdeps['optional']['subpackage'];
                   66489:                     if (!isset($t[0])) {
                   66490:                         $t = array($t);
                   66491:                     }
                   66492: 
                   66493:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   66494:                 }
                   66495: 
                   66496:                 if (isset($pdeps['required']['package'])) {
                   66497:                     $t = $pdeps['required']['package'];
                   66498:                     if (!isset($t[0])) {
                   66499:                         $t = array($t);
                   66500:                     }
                   66501: 
                   66502:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   66503:                 }
                   66504: 
                   66505:                 if (isset($pdeps['group'])) {
                   66506:                     if (!isset($pdeps['group'][0])) {
                   66507:                         $pdeps['group'] = array($pdeps['group']);
                   66508:                     }
                   66509: 
                   66510:                     foreach ($pdeps['group'] as $group) {
                   66511:                         if (isset($group['package'])) {
                   66512:                             $t = $group['package'];
                   66513:                             if (!isset($t[0])) {
                   66514:                                 $t = array($t);
                   66515:                             }
                   66516: 
                   66517:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   66518:                         }
                   66519:                     }
                   66520:                 }
                   66521:             }
                   66522:         }
                   66523: 
                   66524:         $this->_detectDepCycle($deplinks);
                   66525:         foreach ($deplinks as $dependent => $parents) {
                   66526:             foreach ($parents as $parent => $unused) {
                   66527:                 $nodes[$dependent]->connectTo($nodes[$parent]);
                   66528:             }
                   66529:         }
                   66530: 
                   66531:         $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph);
                   66532:         $ret = array();
                   66533:         for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
                   66534:             foreach ($installOrder[$i] as $index => $sortedpackage) {
                   66535:                 $data = &$installOrder[$i][$index]->getData();
                   66536:                 $ret[] = &$nodes[$reg->parsedPackageNameToString(
                   66537:                           array(
                   66538:                               'channel' => $data->getChannel(),
                   66539:                               'package' => strtolower($data->getPackage()),
                   66540:                           ))]->getData();
                   66541:             }
                   66542:         }
                   66543: 
                   66544:         $packages = $ret;
                   66545:         return;
                   66546:     }
                   66547: 
                   66548:     /**
                   66549:      * Detect recursive links between dependencies and break the cycles
                   66550:      *
                   66551:      * @param array
                   66552:      * @access private
                   66553:      */
                   66554:     function _detectDepCycle(&$deplinks)
                   66555:     {
                   66556:         do {
                   66557:             $keepgoing = false;
                   66558:             foreach ($deplinks as $dep => $parents) {
                   66559:                 foreach ($parents as $parent => $unused) {
                   66560:                     // reset the parent cycle detector
                   66561:                     $this->_testCycle(null, null, null);
                   66562:                     if ($this->_testCycle($dep, $deplinks, $parent)) {
                   66563:                         $keepgoing = true;
                   66564:                         unset($deplinks[$dep][$parent]);
                   66565:                         if (count($deplinks[$dep]) == 0) {
                   66566:                             unset($deplinks[$dep]);
                   66567:                         }
                   66568: 
                   66569:                         continue 3;
                   66570:                     }
                   66571:                 }
                   66572:             }
                   66573:         } while ($keepgoing);
                   66574:     }
                   66575: 
                   66576:     function _testCycle($test, $deplinks, $dep)
                   66577:     {
                   66578:         static $visited = array();
                   66579:         if ($test === null) {
                   66580:             $visited = array();
                   66581:             return;
                   66582:         }
                   66583: 
                   66584:         // this happens when a parent has a dep cycle on another dependency
                   66585:         // but the child is not part of the cycle
                   66586:         if (isset($visited[$dep])) {
                   66587:             return false;
                   66588:         }
                   66589: 
                   66590:         $visited[$dep] = 1;
                   66591:         if ($test == $dep) {
                   66592:             return true;
                   66593:         }
                   66594: 
                   66595:         if (isset($deplinks[$dep])) {
                   66596:             if (in_array($test, array_keys($deplinks[$dep]), true)) {
                   66597:                 return true;
                   66598:             }
                   66599: 
                   66600:             foreach ($deplinks[$dep] as $parent => $unused) {
                   66601:                 if ($this->_testCycle($test, $deplinks, $parent)) {
                   66602:                     return true;
                   66603:                 }
                   66604:             }
                   66605:         }
                   66606: 
                   66607:         return false;
                   66608:     }
                   66609: 
                   66610:     /**
                   66611:      * Set up the dependency for installation parsing
                   66612:      *
                   66613:      * @param array $t dependency information
                   66614:      * @param PEAR_Registry $reg
                   66615:      * @param array $deplinks list of dependency links already established
                   66616:      * @param array $nodes all existing package nodes
                   66617:      * @param string $package parent package name
                   66618:      * @access private
                   66619:      */
                   66620:     function _setupGraph($t, $reg, &$deplinks, &$nodes, $package)
                   66621:     {
                   66622:         foreach ($t as $dep) {
                   66623:             $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
                   66624:             $dname = $reg->parsedPackageNameToString(
                   66625:                   array(
                   66626:                       'channel' => $depchannel,
                   66627:                       'package' => strtolower($dep['name']),
                   66628:                   ));
                   66629: 
                   66630:             if (isset($nodes[$dname])) {
                   66631:                 if (!isset($deplinks[$dname])) {
                   66632:                     $deplinks[$dname] = array();
                   66633:                 }
                   66634:                 $deplinks[$dname][$package] = 1;
                   66635:             }
                   66636:         }
                   66637:     }
                   66638: 
                   66639:     function _dependsOn($a, $b)
                   66640:     {
                   66641:         return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
                   66642:     }
                   66643: 
                   66644:     function _checkDepTree($channel, $package, $b, $checked = array())
                   66645:     {
                   66646:         $checked[$channel][$package] = true;
                   66647:         if (!isset($this->_depTree[$channel][$package])) {
                   66648:             return false;
                   66649:         }
                   66650: 
                   66651:         if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
                   66652:               [strtolower($b->getPackage())])) {
                   66653:             return true;
                   66654:         }
                   66655: 
                   66656:         foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
                   66657:             foreach ($packages as $pa => $true) {
                   66658:                 if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
                   66659:                     return true;
                   66660:                 }
                   66661:             }
                   66662:         }
                   66663: 
                   66664:         return false;
                   66665:     }
                   66666: 
                   66667:     function _sortInstall($a, $b)
                   66668:     {
                   66669:         if (!$a->getDeps() && !$b->getDeps()) {
                   66670:             return 0; // neither package has dependencies, order is insignificant
                   66671:         }
                   66672:         if ($a->getDeps() && !$b->getDeps()) {
                   66673:             return 1; // $a must be installed after $b because $a has dependencies
                   66674:         }
                   66675:         if (!$a->getDeps() && $b->getDeps()) {
                   66676:             return -1; // $b must be installed after $a because $b has dependencies
                   66677:         }
                   66678:         // both packages have dependencies
                   66679:         if ($this->_dependsOn($a, $b)) {
                   66680:             return 1;
                   66681:         }
                   66682:         if ($this->_dependsOn($b, $a)) {
                   66683:             return -1;
                   66684:         }
                   66685:         return 0;
                   66686:     }
                   66687: 
                   66688:     /**
                   66689:      * Download a file through HTTP.  Considers suggested file name in
                   66690:      * Content-disposition: header and can run a callback function for
                   66691:      * different events.  The callback will be called with two
                   66692:      * parameters: the callback type, and parameters.  The implemented
                   66693:      * callback types are:
                   66694:      *
                   66695:      *  'setup'       called at the very beginning, parameter is a UI object
                   66696:      *                that should be used for all output
                   66697:      *  'message'     the parameter is a string with an informational message
                   66698:      *  'saveas'      may be used to save with a different file name, the
                   66699:      *                parameter is the filename that is about to be used.
                   66700:      *                If a 'saveas' callback returns a non-empty string,
                   66701:      *                that file name will be used as the filename instead.
                   66702:      *                Note that $save_dir will not be affected by this, only
                   66703:      *                the basename of the file.
                   66704:      *  'start'       download is starting, parameter is number of bytes
                   66705:      *                that are expected, or -1 if unknown
                   66706:      *  'bytesread'   parameter is the number of bytes read so far
                   66707:      *  'done'        download is complete, parameter is the total number
                   66708:      *                of bytes read
                   66709:      *  'connfailed'  if the TCP/SSL connection fails, this callback is called
                   66710:      *                with array(host,port,errno,errmsg)
                   66711:      *  'writefailed' if writing to disk fails, this callback is called
                   66712:      *                with array(destfile,errmsg)
                   66713:      *
                   66714:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   66715:      * setting), the proxy will be used.
                   66716:      *
                   66717:      * @param string  $url       the URL to download
                   66718:      * @param object  $ui        PEAR_Frontend_* instance
                   66719:      * @param object  $config    PEAR_Config instance
                   66720:      * @param string  $save_dir  directory to save file in
                   66721:      * @param mixed   $callback  function/method to call for status
                   66722:      *                           updates
                   66723:      * @param false|string|array $lastmodified header values to check against for caching
                   66724:      *                           use false to return the header values from this download
                   66725:      * @param false|array $accept Accept headers to send
                   66726:      * @param false|string $channel Channel to use for retrieving authentication
                   66727:      * @return string|array  Returns the full path of the downloaded file or a PEAR
                   66728:      *                       error on failure.  If the error is caused by
                   66729:      *                       socket-related errors, the error object will
                   66730:      *                       have the fsockopen error code available through
                   66731:      *                       getCode().  If caching is requested, then return the header
                   66732:      *                       values.
                   66733:      *
                   66734:      * @access public
                   66735:      */
                   66736:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
                   66737:                           $accept = false, $channel = false)
                   66738:     {
                   66739:         static $redirect = 0;
                   66740:         // always reset , so we are clean case of error
                   66741:         $wasredirect = $redirect;
                   66742:         $redirect = 0;
                   66743:         if ($callback) {
                   66744:             call_user_func($callback, 'setup', array(&$ui));
                   66745:         }
                   66746: 
                   66747:         $info = parse_url($url);
                   66748:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   66749:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   66750:         }
                   66751: 
                   66752:         if (!isset($info['host'])) {
                   66753:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   66754:         }
                   66755: 
                   66756:         $host = isset($info['host']) ? $info['host'] : null;
                   66757:         $port = isset($info['port']) ? $info['port'] : null;
                   66758:         $path = isset($info['path']) ? $info['path'] : null;
                   66759: 
                   66760:         if (isset($this)) {
                   66761:             $config = &$this->config;
                   66762:         } else {
                   66763:             $config = &PEAR_Config::singleton();
                   66764:         }
                   66765: 
                   66766:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   66767:         if ($config->get('http_proxy') &&
                   66768:               $proxy = parse_url($config->get('http_proxy'))) {
                   66769:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   66770:             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
                   66771:                 $proxy_host = 'ssl://' . $proxy_host;
                   66772:             }
                   66773:             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
                   66774:             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   66775:             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   66776: 
                   66777:             if ($callback) {
                   66778:                 call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
                   66779:             }
                   66780:         }
                   66781: 
                   66782:         if (empty($port)) {
                   66783:             $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
                   66784:         }
                   66785: 
                   66786:         $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   66787: 
                   66788:         if ($proxy_host != '') {
                   66789:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr);
                   66790:             if (!$fp) {
                   66791:                 if ($callback) {
                   66792:                     call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port,
                   66793:                                                                   $errno, $errstr));
                   66794:                 }
                   66795:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno);
                   66796:             }
                   66797: 
                   66798:             if ($lastmodified === false || $lastmodified) {
                   66799:                 $request  = "GET $url HTTP/1.1\r\n";
                   66800:                 $request .= "Host: $host\r\n";
                   66801:             } else {
                   66802:                 $request  = "GET $url HTTP/1.0\r\n";
                   66803:                 $request .= "Host: $host\r\n";
                   66804:             }
                   66805:         } else {
                   66806:             $network_host = $host;
                   66807:             if (isset($info['scheme']) && $info['scheme'] == 'https') {
                   66808:                 $network_host = 'ssl://' . $host;
                   66809:             }
                   66810: 
                   66811:             $fp = @fsockopen($network_host, $port, $errno, $errstr);
                   66812:             if (!$fp) {
                   66813:                 if ($callback) {
                   66814:                     call_user_func($callback, 'connfailed', array($host, $port,
                   66815:                                                                   $errno, $errstr));
                   66816:                 }
                   66817:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   66818:             }
                   66819: 
                   66820:             if ($lastmodified === false || $lastmodified) {
                   66821:                 $request = "GET $path HTTP/1.1\r\n";
                   66822:                 $request .= "Host: $host\r\n";
                   66823:             } else {
                   66824:                 $request = "GET $path HTTP/1.0\r\n";
                   66825:                 $request .= "Host: $host\r\n";
                   66826:             }
                   66827:         }
                   66828: 
                   66829:         $ifmodifiedsince = '';
                   66830:         if (is_array($lastmodified)) {
                   66831:             if (isset($lastmodified['Last-Modified'])) {
                   66832:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   66833:             }
                   66834: 
                   66835:             if (isset($lastmodified['ETag'])) {
                   66836:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   66837:             }
                   66838:         } else {
                   66839:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   66840:         }
                   66841: 
                   66842:         $request .= $ifmodifiedsince .
                   66843:             "User-Agent: PEAR/1.10.0beta1/PHP/" . PHP_VERSION . "\r\n";
                   66844: 
                   66845:         if (isset($this)) { // only pass in authentication for non-static calls
                   66846:             $username = $config->get('username', null, $channel);
                   66847:             $password = $config->get('password', null, $channel);
                   66848:             if ($username && $password) {
                   66849:                 $tmp = base64_encode("$username:$password");
                   66850:                 $request .= "Authorization: Basic $tmp\r\n";
                   66851:             }
                   66852:         }
                   66853: 
                   66854:         if ($proxy_host != '' && $proxy_user != '') {
                   66855:             $request .= 'Proxy-Authorization: Basic ' .
                   66856:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   66857:         }
                   66858: 
                   66859:         if ($accept) {
                   66860:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   66861:         }
                   66862: 
                   66863:         $request .= "Connection: close\r\n";
                   66864:         $request .= "\r\n";
                   66865:         fwrite($fp, $request);
                   66866:         $headers = array();
                   66867:         $reply = 0;
                   66868:         while (trim($line = fgets($fp, 1024))) {
                   66869:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   66870:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   66871:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   66872:                 $reply = (int)$matches[1];
                   66873:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   66874:                     return false;
                   66875:                 }
                   66876: 
                   66877:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   66878:                     return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
                   66879:                 }
                   66880:             }
                   66881:         }
                   66882: 
                   66883:         if ($reply != 200) {
                   66884:             if (!isset($headers['location'])) {
                   66885:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
                   66886:             }
                   66887: 
                   66888:             if ($wasredirect > 4) {
                   66889:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
                   66890:             }
                   66891: 
                   66892:             $redirect = $wasredirect + 1;
                   66893:             return $this->downloadHttp($headers['location'],
                   66894:                     $ui, $save_dir, $callback, $lastmodified, $accept);
                   66895:         }
                   66896: 
                   66897:         if (isset($headers['content-disposition']) &&
                   66898:             preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
                   66899:             $save_as = basename($matches[1]);
                   66900:         } else {
                   66901:             $save_as = basename($url);
                   66902:         }
                   66903: 
                   66904:         if ($callback) {
                   66905:             $tmp = call_user_func($callback, 'saveas', $save_as);
                   66906:             if ($tmp) {
                   66907:                 $save_as = $tmp;
                   66908:             }
                   66909:         }
                   66910: 
                   66911:         $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
                   66912:         if (is_link($dest_file)) {
                   66913:             return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
                   66914:         }
                   66915: 
                   66916:         if (!$wp = @fopen($dest_file, 'wb')) {
                   66917:             fclose($fp);
                   66918:             if ($callback) {
                   66919:                 call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   66920:             }
                   66921:             return PEAR::raiseError("could not open $dest_file for writing");
                   66922:         }
                   66923: 
                   66924:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   66925: 
                   66926:         $bytes = 0;
                   66927:         if ($callback) {
                   66928:             call_user_func($callback, 'start', array(basename($dest_file), $length));
                   66929:         }
                   66930: 
                   66931:         while ($data = fread($fp, 1024)) {
                   66932:             $len    = strlen($data);
                   66933:             $bytes += $len;
                   66934:             if ($callback) {
                   66935:                 call_user_func($callback, 'bytesread', $bytes);
                   66936:             }
                   66937:             if (!@fwrite($wp, $data)) {
                   66938:                 fclose($fp);
                   66939:                 if ($callback) {
                   66940:                     call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   66941:                 }
                   66942:                 return PEAR::raiseError("$dest_file: write failed ($php_errormsg)");
                   66943:             }
                   66944:         }
                   66945: 
                   66946:         fclose($fp);
                   66947:         fclose($wp);
                   66948:         if ($callback) {
                   66949:             call_user_func($callback, 'done', $bytes);
                   66950:         }
                   66951: 
                   66952:         if ($lastmodified === false || $lastmodified) {
                   66953:             if (isset($headers['etag'])) {
                   66954:                 $lastmodified = array('ETag' => $headers['etag']);
                   66955:             }
                   66956: 
                   66957:             if (isset($headers['last-modified'])) {
                   66958:                 if (is_array($lastmodified)) {
                   66959:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   66960:                 } else {
                   66961:                     $lastmodified = $headers['last-modified'];
                   66962:                 }
                   66963:             }
                   66964:             return array($dest_file, $lastmodified, $headers);
                   66965:         }
                   66966:         return $dest_file;
                   66967:     }
                   66968: }<?php
                   66969: /**
                   66970:  * PEAR_Downloader_Package
                   66971:  *
                   66972:  * PHP versions 4 and 5
                   66973:  *
                   66974:  * @category   pear
                   66975:  * @package    PEAR
                   66976:  * @author     Greg Beaver <cellog@php.net>
                   66977:  * @copyright  1997-2009 The Authors
                   66978:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   66979:  * @version    CVS: $Id: Package.php 308688 2011-02-25 23:18:06Z dufuz $
                   66980:  * @link       http://pear.php.net/package/PEAR
                   66981:  * @since      File available since Release 1.4.0a1
                   66982:  */
                   66983: 
                   66984: /**
                   66985:  * Error code when parameter initialization fails because no releases
                   66986:  * exist within preferred_state, but releases do exist
                   66987:  */
                   66988: define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
                   66989: /**
                   66990:  * Error code when parameter initialization fails because no releases
                   66991:  * exist that will work with the existing PHP version
                   66992:  */
                   66993: define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
                   66994: 
                   66995: /**
                   66996:  * Coordinates download parameters and manages their dependencies
                   66997:  * prior to downloading them.
                   66998:  *
                   66999:  * Input can come from three sources:
                   67000:  *
                   67001:  * - local files (archives or package.xml)
                   67002:  * - remote files (downloadable urls)
                   67003:  * - abstract package names
                   67004:  *
                   67005:  * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
                   67006:  * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
                   67007:  * format returned of dependencies is slightly different from that used in package.xml.
                   67008:  *
                   67009:  * This class hides the differences between these elements, and makes automatic
                   67010:  * dependency resolution a piece of cake.  It also manages conflicts when
                   67011:  * two classes depend on incompatible dependencies, or differing versions of the same
                   67012:  * package dependency.  In addition, download will not be attempted if the php version is
                   67013:  * not supported, PEAR installer version is not supported, or non-PECL extensions are not
                   67014:  * installed.
                   67015:  * @category   pear
                   67016:  * @package    PEAR
                   67017:  * @author     Greg Beaver <cellog@php.net>
                   67018:  * @copyright  1997-2009 The Authors
                   67019:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   67020:  * @version    Release: 1.10.0beta1
                   67021:  * @link       http://pear.php.net/package/PEAR
                   67022:  * @since      Class available since Release 1.4.0a1
                   67023:  */
                   67024: class PEAR_Downloader_Package
                   67025: {
                   67026:     /**
                   67027:      * @var PEAR_Downloader
                   67028:      */
                   67029:     var $_downloader;
                   67030:     /**
                   67031:      * @var PEAR_Config
                   67032:      */
                   67033:     var $_config;
                   67034:     /**
                   67035:      * @var PEAR_Registry
                   67036:      */
                   67037:     var $_registry;
                   67038:     /**
                   67039:      * Used to implement packagingroot properly
                   67040:      * @var PEAR_Registry
                   67041:      */
                   67042:     var $_installRegistry;
                   67043:     /**
                   67044:      * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
                   67045:      */
                   67046:     var $_packagefile;
                   67047:     /**
                   67048:      * @var array
                   67049:      */
                   67050:     var $_parsedname;
                   67051:     /**
                   67052:      * @var array
                   67053:      */
                   67054:     var $_downloadURL;
                   67055:     /**
                   67056:      * @var array
                   67057:      */
                   67058:     var $_downloadDeps = array();
                   67059:     /**
                   67060:      * @var boolean
                   67061:      */
                   67062:     var $_valid = false;
                   67063:     /**
                   67064:      * @var boolean
                   67065:      */
                   67066:     var $_analyzed = false;
                   67067:     /**
                   67068:      * if this or a parent package was invoked with Package-state, this is set to the
                   67069:      * state variable.
                   67070:      *
                   67071:      * This allows temporary reassignment of preferred_state for a parent package and all of
                   67072:      * its dependencies.
                   67073:      * @var string|false
                   67074:      */
                   67075:     var $_explicitState = false;
                   67076:     /**
                   67077:      * If this package is invoked with Package#group, this variable will be true
                   67078:      */
                   67079:     var $_explicitGroup = false;
                   67080:     /**
                   67081:      * Package type local|url
                   67082:      * @var string
                   67083:      */
                   67084:     var $_type;
                   67085:     /**
                   67086:      * Contents of package.xml, if downloaded from a remote channel
                   67087:      * @var string|false
                   67088:      * @access private
                   67089:      */
                   67090:     var $_rawpackagefile;
                   67091:     /**
                   67092:      * @var boolean
                   67093:      * @access private
                   67094:      */
                   67095:     var $_validated = false;
                   67096: 
                   67097:     /**
                   67098:      * @param PEAR_Downloader
                   67099:      */
                   67100:     function PEAR_Downloader_Package(&$downloader)
                   67101:     {
                   67102:         $this->_downloader = &$downloader;
                   67103:         $this->_config = &$this->_downloader->config;
                   67104:         $this->_registry = &$this->_config->getRegistry();
                   67105:         $options = $downloader->getOptions();
                   67106:         if (isset($options['packagingroot'])) {
                   67107:             $this->_config->setInstallRoot($options['packagingroot']);
                   67108:             $this->_installRegistry = &$this->_config->getRegistry();
                   67109:             $this->_config->setInstallRoot(false);
                   67110:         } else {
                   67111:             $this->_installRegistry = &$this->_registry;
                   67112:         }
                   67113:         $this->_valid = $this->_analyzed = false;
                   67114:     }
                   67115: 
                   67116:     /**
                   67117:      * Parse the input and determine whether this is a local file, a remote uri, or an
                   67118:      * abstract package name.
                   67119:      *
                   67120:      * This is the heart of the PEAR_Downloader_Package(), and is used in
                   67121:      * {@link PEAR_Downloader::download()}
                   67122:      * @param string
                   67123:      * @return bool|PEAR_Error
                   67124:      */
                   67125:     function initialize($param)
                   67126:     {
                   67127:         $origErr = $this->_fromFile($param);
                   67128:         if ($this->_valid) {
                   67129:             return true;
                   67130:         }
                   67131: 
                   67132:         $options = $this->_downloader->getOptions();
                   67133:         if (isset($options['offline'])) {
                   67134:             if (PEAR::isError($origErr) && !isset($options['soft'])) {
                   67135:                 foreach ($origErr->getUserInfo() as $userInfo) {
                   67136:                     if (isset($userInfo['message'])) {
                   67137:                         $this->_downloader->log(0, $userInfo['message']);
                   67138:                     }
                   67139:                 }
                   67140: 
                   67141:                 $this->_downloader->log(0, $origErr->getMessage());
                   67142:             }
                   67143: 
                   67144:             return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
                   67145:         }
                   67146: 
                   67147:         $err = $this->_fromUrl($param);
                   67148:         if (PEAR::isError($err) || !$this->_valid) {
                   67149:             if ($this->_type == 'url') {
                   67150:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   67151:                     $this->_downloader->log(0, $err->getMessage());
                   67152:                 }
                   67153: 
                   67154:                 return PEAR::raiseError("Invalid or missing remote package file");
                   67155:             }
                   67156: 
                   67157:             $err = $this->_fromString($param);
                   67158:             if (PEAR::isError($err) || !$this->_valid) {
                   67159:                 if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
                   67160:                     return false; // instruct the downloader to silently skip
                   67161:                 }
                   67162: 
                   67163:                 if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
                   67164:                     if (is_array($origErr->getUserInfo())) {
                   67165:                         foreach ($origErr->getUserInfo() as $err) {
                   67166:                             if (is_array($err)) {
                   67167:                                 $err = $err['message'];
                   67168:                             }
                   67169: 
                   67170:                             if (!isset($options['soft'])) {
                   67171:                                 $this->_downloader->log(0, $err);
                   67172:                             }
                   67173:                         }
                   67174:                     }
                   67175: 
                   67176:                     if (!isset($options['soft'])) {
                   67177:                         $this->_downloader->log(0, $origErr->getMessage());
                   67178:                     }
                   67179: 
                   67180:                     if (is_array($param)) {
                   67181:                         $param = $this->_registry->parsedPackageNameToString($param, true);
                   67182:                     }
                   67183: 
                   67184:                     if (!isset($options['soft'])) {
                   67185:                         $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   67186:                     }
                   67187: 
                   67188:                     // Passing no message back - already logged above
                   67189:                     return PEAR::raiseError();
                   67190:                 }
                   67191: 
                   67192:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   67193:                     $this->_downloader->log(0, $err->getMessage());
                   67194:                 }
                   67195: 
                   67196:                 if (is_array($param)) {
                   67197:                     $param = $this->_registry->parsedPackageNameToString($param, true);
                   67198:                 }
                   67199: 
                   67200:                 if (!isset($options['soft'])) {
                   67201:                     $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   67202:                 }
                   67203: 
                   67204:                 // Passing no message back - already logged above
                   67205:                 return PEAR::raiseError();
                   67206:             }
                   67207:         }
                   67208: 
                   67209:         return true;
                   67210:     }
                   67211: 
                   67212:     /**
                   67213:      * Retrieve any non-local packages
                   67214:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
                   67215:      */
                   67216:     function &download()
                   67217:     {
                   67218:         if (isset($this->_packagefile)) {
                   67219:             return $this->_packagefile;
                   67220:         }
                   67221: 
                   67222:         if (isset($this->_downloadURL['url'])) {
                   67223:             $this->_isvalid = false;
                   67224:             $info = $this->getParsedPackage();
                   67225:             foreach ($info as $i => $p) {
                   67226:                 $info[$i] = strtolower($p);
                   67227:             }
                   67228: 
                   67229:             $err = $this->_fromUrl($this->_downloadURL['url'],
                   67230:                 $this->_registry->parsedPackageNameToString($this->_parsedname, true));
                   67231:             $newinfo = $this->getParsedPackage();
                   67232:             foreach ($newinfo as $i => $p) {
                   67233:                 $newinfo[$i] = strtolower($p);
                   67234:             }
                   67235: 
                   67236:             if ($info != $newinfo) {
                   67237:                 do {
                   67238:                     if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
                   67239:                         $info['channel'] = 'pear.php.net';
                   67240:                         if ($info == $newinfo) {
                   67241:                             // skip the channel check if a pecl package says it's a PEAR package
                   67242:                             break;
                   67243:                         }
                   67244:                     }
                   67245:                     if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
                   67246:                         $info['channel'] = 'pecl.php.net';
                   67247:                         if ($info == $newinfo) {
                   67248:                             // skip the channel check if a pecl package says it's a PEAR package
                   67249:                             break;
                   67250:                         }
                   67251:                     }
                   67252: 
                   67253:                     return PEAR::raiseError('CRITICAL ERROR: We are ' .
                   67254:                         $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
                   67255:                         'downloaded claims to be ' .
                   67256:                         $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
                   67257:                 } while (false);
                   67258:             }
                   67259: 
                   67260:             if (PEAR::isError($err) || !$this->_valid) {
                   67261:                 return $err;
                   67262:             }
                   67263:         }
                   67264: 
                   67265:         $this->_type = 'local';
                   67266:         return $this->_packagefile;
                   67267:     }
                   67268: 
                   67269:     function &getPackageFile()
                   67270:     {
                   67271:         return $this->_packagefile;
                   67272:     }
                   67273: 
                   67274:     function &getDownloader()
                   67275:     {
                   67276:         return $this->_downloader;
                   67277:     }
                   67278: 
                   67279:     function getType()
                   67280:     {
                   67281:         return $this->_type;
                   67282:     }
                   67283: 
                   67284:     /**
                   67285:      * Like {@link initialize()}, but operates on a dependency
                   67286:      */
                   67287:     function fromDepURL($dep)
                   67288:     {
                   67289:         $this->_downloadURL = $dep;
                   67290:         if (isset($dep['uri'])) {
                   67291:             $options = $this->_downloader->getOptions();
                   67292:             if (!extension_loaded("zlib") || isset($options['nocompress'])) {
                   67293:                 $ext = '.tar';
                   67294:             } else {
                   67295:                 $ext = '.tgz';
                   67296:             }
                   67297: 
                   67298:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   67299:             $err = $this->_fromUrl($dep['uri'] . $ext);
                   67300:             PEAR::popErrorHandling();
                   67301:             if (PEAR::isError($err)) {
                   67302:                 if (!isset($options['soft'])) {
                   67303:                     $this->_downloader->log(0, $err->getMessage());
                   67304:                 }
                   67305: 
                   67306:                 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
                   67307:                     'cannot download');
                   67308:             }
                   67309:         } else {
                   67310:             $this->_parsedname =
                   67311:                 array(
                   67312:                     'package' => $dep['info']->getPackage(),
                   67313:                     'channel' => $dep['info']->getChannel(),
                   67314:                     'version' => $dep['version']
                   67315:                 );
                   67316:             if (!isset($dep['nodefault'])) {
                   67317:                 $this->_parsedname['group'] = 'default'; // download the default dependency group
                   67318:                 $this->_explicitGroup = false;
                   67319:             }
                   67320: 
                   67321:             $this->_rawpackagefile = $dep['raw'];
                   67322:         }
                   67323:     }
                   67324: 
                   67325:     function detectDependencies($params)
                   67326:     {
                   67327:         $options = $this->_downloader->getOptions();
                   67328:         if (isset($options['downloadonly'])) {
                   67329:             return;
                   67330:         }
                   67331: 
                   67332:         if (isset($options['offline'])) {
                   67333:             $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
                   67334:             return;
                   67335:         }
                   67336: 
                   67337:         $pname = $this->getParsedPackage();
                   67338:         if (!$pname) {
                   67339:             return;
                   67340:         }
                   67341: 
                   67342:         $deps = $this->getDeps();
                   67343:         if (!$deps) {
                   67344:             return;
                   67345:         }
                   67346: 
                   67347:         if (isset($deps['required'])) { // package.xml 2.0
                   67348:             return $this->_detect2($deps, $pname, $options, $params);
                   67349:         }
                   67350: 
                   67351:         return $this->_detect1($deps, $pname, $options, $params);
                   67352:     }
                   67353: 
                   67354:     function setValidated()
                   67355:     {
                   67356:         $this->_validated = true;
                   67357:     }
                   67358: 
                   67359:     function alreadyValidated()
                   67360:     {
                   67361:         return $this->_validated;
                   67362:     }
                   67363: 
                   67364:     /**
                   67365:      * Remove packages to be downloaded that are already installed
                   67366:      * @param array of PEAR_Downloader_Package objects
                   67367:      * @static
                   67368:      */
                   67369:     function removeInstalled(&$params)
                   67370:     {
                   67371:         if (!isset($params[0])) {
                   67372:             return;
                   67373:         }
                   67374: 
                   67375:         $options = $params[0]->_downloader->getOptions();
                   67376:         if (!isset($options['downloadonly'])) {
                   67377:             foreach ($params as $i => $param) {
                   67378:                 $package = $param->getPackage();
                   67379:                 $channel = $param->getChannel();
                   67380:                 // remove self if already installed with this version
                   67381:                 // this does not need any pecl magic - we only remove exact matches
                   67382:                 if ($param->_installRegistry->packageExists($package, $channel)) {
                   67383:                     $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
                   67384:                     if (version_compare($packageVersion, $param->getVersion(), '==')) {
                   67385:                         if (!isset($options['force'])) {
                   67386:                             $info = $param->getParsedPackage();
                   67387:                             unset($info['version']);
                   67388:                             unset($info['state']);
                   67389:                             if (!isset($options['soft'])) {
                   67390:                                 $param->_downloader->log(1, 'Skipping package "' .
                   67391:                                     $param->getShortName() .
                   67392:                                     '", already installed as version ' . $packageVersion);
                   67393:                             }
                   67394:                             $params[$i] = false;
                   67395:                         }
                   67396:                     } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
                   67397:                           !isset($options['soft'])) {
                   67398:                         $info = $param->getParsedPackage();
                   67399:                         $param->_downloader->log(1, 'Skipping package "' .
                   67400:                             $param->getShortName() .
                   67401:                             '", already installed as version ' . $packageVersion);
                   67402:                         $params[$i] = false;
                   67403:                     }
                   67404:                 }
                   67405:             }
                   67406:         }
                   67407: 
                   67408:         PEAR_Downloader_Package::removeDuplicates($params);
                   67409:     }
                   67410: 
                   67411:     function _detect2($deps, $pname, $options, $params)
                   67412:     {
                   67413:         $this->_downloadDeps = array();
                   67414:         $groupnotfound = false;
                   67415:         foreach (array('package', 'subpackage') as $packagetype) {
                   67416:             // get required dependency group
                   67417:             if (isset($deps['required'][$packagetype])) {
                   67418:                 if (isset($deps['required'][$packagetype][0])) {
                   67419:                     foreach ($deps['required'][$packagetype] as $dep) {
                   67420:                         if (isset($dep['conflicts'])) {
                   67421:                             // skip any package that this package conflicts with
                   67422:                             continue;
                   67423:                         }
                   67424:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   67425:                         if (is_array($ret)) {
                   67426:                             $this->_downloadDeps[] = $ret;
                   67427:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   67428:                             $this->_downloader->log(0, $ret->getMessage());
                   67429:                         }
                   67430:                     }
                   67431:                 } else {
                   67432:                     $dep = $deps['required'][$packagetype];
                   67433:                     if (!isset($dep['conflicts'])) {
                   67434:                         // skip any package that this package conflicts with
                   67435:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   67436:                         if (is_array($ret)) {
                   67437:                             $this->_downloadDeps[] = $ret;
                   67438:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   67439:                             $this->_downloader->log(0, $ret->getMessage());
                   67440:                         }
                   67441:                     }
                   67442:                 }
                   67443:             }
                   67444: 
                   67445:             // get optional dependency group, if any
                   67446:             if (isset($deps['optional'][$packagetype])) {
                   67447:                 $skipnames = array();
                   67448:                 if (!isset($deps['optional'][$packagetype][0])) {
                   67449:                     $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
                   67450:                 }
                   67451: 
                   67452:                 foreach ($deps['optional'][$packagetype] as $dep) {
                   67453:                     $skip = false;
                   67454:                     if (!isset($options['alldeps'])) {
                   67455:                         $dep['package'] = $dep['name'];
                   67456:                         if (!isset($options['soft'])) {
                   67457:                             $this->_downloader->log(3, 'Notice: package "' .
                   67458:                               $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
                   67459:                                     true) . '" optional dependency "' .
                   67460:                                 $this->_registry->parsedPackageNameToString(array('package' =>
                   67461:                                     $dep['name'], 'channel' => 'pear.php.net'), true) .
                   67462:                                 '" will not be automatically downloaded');
                   67463:                         }
                   67464:                         $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
                   67465:                         $skip = true;
                   67466:                         unset($dep['package']);
                   67467:                     }
                   67468: 
                   67469:                     $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
                   67470:                     if (PEAR::isError($ret) && !isset($options['soft'])) {
                   67471:                         $this->_downloader->log(0, $ret->getMessage());
                   67472:                     }
                   67473: 
                   67474:                     if (!$ret) {
                   67475:                         $dep['package'] = $dep['name'];
                   67476:                         $skip = count($skipnames) ?
                   67477:                             $skipnames[count($skipnames) - 1] : '';
                   67478:                         if ($skip ==
                   67479:                               $this->_registry->parsedPackageNameToString($dep, true)) {
                   67480:                             array_pop($skipnames);
                   67481:                         }
                   67482:                     }
                   67483: 
                   67484:                     if (!$skip && is_array($ret)) {
                   67485:                         $this->_downloadDeps[] = $ret;
                   67486:                     }
                   67487:                 }
                   67488: 
                   67489:                 if (count($skipnames)) {
                   67490:                     if (!isset($options['soft'])) {
                   67491:                         $this->_downloader->log(1, 'Did not download optional dependencies: ' .
                   67492:                             implode(', ', $skipnames) .
                   67493:                             ', use --alldeps to download automatically');
                   67494:                     }
                   67495:                 }
                   67496:             }
                   67497: 
                   67498:             // get requested dependency group, if any
                   67499:             $groupname = $this->getGroup();
                   67500:             $explicit  = $this->_explicitGroup;
                   67501:             if (!$groupname) {
                   67502:                 if (!$this->canDefault()) {
                   67503:                     continue;
                   67504:                 }
                   67505: 
                   67506:                 $groupname = 'default'; // try the default dependency group
                   67507:             }
                   67508: 
                   67509:             if ($groupnotfound) {
                   67510:                 continue;
                   67511:             }
                   67512: 
                   67513:             if (isset($deps['group'])) {
                   67514:                 if (isset($deps['group']['attribs'])) {
                   67515:                     if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
                   67516:                         $group = $deps['group'];
                   67517:                     } elseif ($explicit) {
                   67518:                         if (!isset($options['soft'])) {
                   67519:                             $this->_downloader->log(0, 'Warning: package "' .
                   67520:                                 $this->_registry->parsedPackageNameToString($pname, true) .
                   67521:                                 '" has no dependency ' . 'group named "' . $groupname . '"');
                   67522:                         }
                   67523: 
                   67524:                         $groupnotfound = true;
                   67525:                         continue;
                   67526:                     }
                   67527:                 } else {
                   67528:                     $found = false;
                   67529:                     foreach ($deps['group'] as $group) {
                   67530:                         if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
                   67531:                             $found = true;
                   67532:                             break;
                   67533:                         }
                   67534:                     }
                   67535: 
                   67536:                     if (!$found) {
                   67537:                         if ($explicit) {
                   67538:                             if (!isset($options['soft'])) {
                   67539:                                 $this->_downloader->log(0, 'Warning: package "' .
                   67540:                                     $this->_registry->parsedPackageNameToString($pname, true) .
                   67541:                                     '" has no dependency ' . 'group named "' . $groupname . '"');
                   67542:                             }
                   67543:                         }
                   67544: 
                   67545:                         $groupnotfound = true;
                   67546:                         continue;
                   67547:                     }
                   67548:                 }
                   67549:             }
                   67550: 
                   67551:             if (isset($group) && isset($group[$packagetype])) {
                   67552:                 if (isset($group[$packagetype][0])) {
                   67553:                     foreach ($group[$packagetype] as $dep) {
                   67554:                         $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
                   67555:                             $group['attribs']['name'] . '"', $params);
                   67556:                         if (is_array($ret)) {
                   67557:                             $this->_downloadDeps[] = $ret;
                   67558:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   67559:                             $this->_downloader->log(0, $ret->getMessage());
                   67560:                         }
                   67561:                     }
                   67562:                 } else {
                   67563:                     $ret = $this->_detect2Dep($group[$packagetype], $pname,
                   67564:                         'dependency group "' .
                   67565:                         $group['attribs']['name'] . '"', $params);
                   67566:                     if (is_array($ret)) {
                   67567:                         $this->_downloadDeps[] = $ret;
                   67568:                     } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   67569:                         $this->_downloader->log(0, $ret->getMessage());
                   67570:                     }
                   67571:                 }
                   67572:             }
                   67573:         }
                   67574:     }
                   67575: 
                   67576:     function _detect2Dep($dep, $pname, $group, $params)
                   67577:     {
                   67578:         if (isset($dep['conflicts'])) {
                   67579:             return true;
                   67580:         }
                   67581: 
                   67582:         $options = $this->_downloader->getOptions();
                   67583:         if (isset($dep['uri'])) {
                   67584:             return array('uri' => $dep['uri'], 'dep' => $dep);;
                   67585:         }
                   67586: 
                   67587:         $testdep = $dep;
                   67588:         $testdep['package'] = $dep['name'];
                   67589:         if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
                   67590:             $dep['package'] = $dep['name'];
                   67591:             if (!isset($options['soft'])) {
                   67592:                 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
                   67593:                     ' dependency "' .
                   67594:                     $this->_registry->parsedPackageNameToString($dep, true) .
                   67595:                     '", will be installed');
                   67596:             }
                   67597:             return false;
                   67598:         }
                   67599: 
                   67600:         $options = $this->_downloader->getOptions();
                   67601:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   67602:         if ($this->_explicitState) {
                   67603:             $pname['state'] = $this->_explicitState;
                   67604:         }
                   67605: 
                   67606:         $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   67607:         if (PEAR::isError($url)) {
                   67608:             PEAR::popErrorHandling();
                   67609:             return $url;
                   67610:         }
                   67611: 
                   67612:         $dep['package'] = $dep['name'];
                   67613:         $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
                   67614:             !isset($options['alldeps']), true);
                   67615:         PEAR::popErrorHandling();
                   67616:         if (PEAR::isError($ret)) {
                   67617:             if (!isset($options['soft'])) {
                   67618:                 $this->_downloader->log(0, $ret->getMessage());
                   67619:             }
                   67620: 
                   67621:             return false;
                   67622:         }
                   67623: 
                   67624:         // check to see if a dep is already installed and is the same or newer
                   67625:         if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
                   67626:             $oper = 'has';
                   67627:         } else {
                   67628:             $oper = 'gt';
                   67629:         }
                   67630: 
                   67631:         // do not try to move this before getDepPackageDownloadURL
                   67632:         // we can't determine whether upgrade is necessary until we know what
                   67633:         // version would be downloaded
                   67634:         if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
                   67635:             $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
                   67636:             $dep['package'] = $dep['name'];
                   67637:             if (!isset($options['soft'])) {
                   67638:                 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   67639:                     ' dependency "' .
                   67640:                 $this->_registry->parsedPackageNameToString($dep, true) .
                   67641:                     '" version ' . $url['version'] . ', already installed as version ' .
                   67642:                     $version);
                   67643:             }
                   67644: 
                   67645:             return false;
                   67646:         }
                   67647: 
                   67648:         if (isset($dep['nodefault'])) {
                   67649:             $ret['nodefault'] = true;
                   67650:         }
                   67651: 
                   67652:         return $ret;
                   67653:     }
                   67654: 
                   67655:     function _detect1($deps, $pname, $options, $params)
                   67656:     {
                   67657:         $this->_downloadDeps = array();
                   67658:         $skipnames = array();
                   67659:         foreach ($deps as $dep) {
                   67660:             $nodownload = false;
                   67661:             if (isset ($dep['type']) && $dep['type'] === 'pkg') {
                   67662:                 $dep['channel'] = 'pear.php.net';
                   67663:                 $dep['package'] = $dep['name'];
                   67664:                 switch ($dep['rel']) {
                   67665:                     case 'not' :
                   67666:                         continue 2;
                   67667:                     case 'ge' :
                   67668:                     case 'eq' :
                   67669:                     case 'gt' :
                   67670:                     case 'has' :
                   67671:                         $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   67672:                             'required' :
                   67673:                             'optional';
                   67674:                         if (PEAR_Downloader_Package::willDownload($dep, $params)) {
                   67675:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   67676:                                 . ' dependency "' .
                   67677:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   67678:                                 '", will be installed');
                   67679:                             continue 2;
                   67680:                         }
                   67681:                         $fakedp = new PEAR_PackageFile_v1;
                   67682:                         $fakedp->setPackage($dep['name']);
                   67683:                         // skip internet check if we are not upgrading (bug #5810)
                   67684:                         if (!isset($options['upgrade']) && $this->isInstalled(
                   67685:                               $fakedp, $dep['rel'])) {
                   67686:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   67687:                                 . ' dependency "' .
                   67688:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   67689:                                 '", is already installed');
                   67690:                             continue 2;
                   67691:                         }
                   67692:                 }
                   67693: 
                   67694:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   67695:                 if ($this->_explicitState) {
                   67696:                     $pname['state'] = $this->_explicitState;
                   67697:                 }
                   67698: 
                   67699:                 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   67700:                 $chan = 'pear.php.net';
                   67701:                 if (PEAR::isError($url)) {
                   67702:                     // check to see if this is a pecl package that has jumped
                   67703:                     // from pear.php.net to pecl.php.net channel
                   67704:                     if (!class_exists('PEAR_Dependency2')) {
                   67705:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   67706:                     }
                   67707: 
                   67708:                     $newdep = PEAR_Dependency2::normalizeDep($dep);
                   67709:                     $newdep = $newdep[0];
                   67710:                     $newdep['channel'] = 'pecl.php.net';
                   67711:                     $chan = 'pecl.php.net';
                   67712:                     $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
                   67713:                     $obj = &$this->_installRegistry->getPackage($dep['name']);
                   67714:                     if (PEAR::isError($url)) {
                   67715:                         PEAR::popErrorHandling();
                   67716:                         if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
                   67717:                             $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   67718:                                 'required' :
                   67719:                                 'optional';
                   67720:                             $dep['package'] = $dep['name'];
                   67721:                             if (!isset($options['soft'])) {
                   67722:                                 $this->_downloader->log(3, $this->getShortName() .
                   67723:                                     ': Skipping ' . $group . ' dependency "' .
                   67724:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   67725:                                     '", already installed as version ' . $obj->getVersion());
                   67726:                             }
                   67727:                             $skip = count($skipnames) ?
                   67728:                                 $skipnames[count($skipnames) - 1] : '';
                   67729:                             if ($skip ==
                   67730:                                   $this->_registry->parsedPackageNameToString($dep, true)) {
                   67731:                                 array_pop($skipnames);
                   67732:                             }
                   67733:                             continue;
                   67734:                         } else {
                   67735:                             if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   67736:                                 $this->_downloader->log(2, $this->getShortName() .
                   67737:                                     ': Skipping optional dependency "' .
                   67738:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   67739:                                     '", no releases exist');
                   67740:                                 continue;
                   67741:                             } else {
                   67742:                                 return $url;
                   67743:                             }
                   67744:                         }
                   67745:                     }
                   67746:                 }
                   67747: 
                   67748:                 PEAR::popErrorHandling();
                   67749:                 if (!isset($options['alldeps'])) {
                   67750:                     if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   67751:                         if (!isset($options['soft'])) {
                   67752:                             $this->_downloader->log(3, 'Notice: package "' .
                   67753:                                 $this->getShortName() .
                   67754:                                 '" optional dependency "' .
                   67755:                                 $this->_registry->parsedPackageNameToString(
                   67756:                                     array('channel' => $chan, 'package' =>
                   67757:                                     $dep['name']), true) .
                   67758:                                 '" will not be automatically downloaded');
                   67759:                         }
                   67760:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   67761:                                 array('channel' => $chan, 'package' =>
                   67762:                                 $dep['name']), true);
                   67763:                         $nodownload = true;
                   67764:                     }
                   67765:                 }
                   67766: 
                   67767:                 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
                   67768:                     if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   67769:                         if (!isset($options['soft'])) {
                   67770:                             $this->_downloader->log(3, 'Notice: package "' .
                   67771:                                 $this->getShortName() .
                   67772:                                 '" required dependency "' .
                   67773:                                 $this->_registry->parsedPackageNameToString(
                   67774:                                     array('channel' => $chan, 'package' =>
                   67775:                                     $dep['name']), true) .
                   67776:                                 '" will not be automatically downloaded');
                   67777:                         }
                   67778:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   67779:                                 array('channel' => $chan, 'package' =>
                   67780:                                 $dep['name']), true);
                   67781:                         $nodownload = true;
                   67782:                     }
                   67783:                 }
                   67784: 
                   67785:                 // check to see if a dep is already installed
                   67786:                 // do not try to move this before getDepPackageDownloadURL
                   67787:                 // we can't determine whether upgrade is necessary until we know what
                   67788:                 // version would be downloaded
                   67789:                 if (!isset($options['force']) && $this->isInstalled(
                   67790:                         $url, $dep['rel'])) {
                   67791:                     $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   67792:                         'required' :
                   67793:                         'optional';
                   67794:                     $dep['package'] = $dep['name'];
                   67795:                     if (isset($newdep)) {
                   67796:                         $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
                   67797:                     } else {
                   67798:                         $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
                   67799:                     }
                   67800: 
                   67801:                     $dep['version'] = $url['version'];
                   67802:                     if (!isset($options['soft'])) {
                   67803:                         $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   67804:                             ' dependency "' .
                   67805:                             $this->_registry->parsedPackageNameToString($dep, true) .
                   67806:                             '", already installed as version ' . $version);
                   67807:                     }
                   67808: 
                   67809:                     $skip = count($skipnames) ?
                   67810:                         $skipnames[count($skipnames) - 1] : '';
                   67811:                     if ($skip ==
                   67812:                           $this->_registry->parsedPackageNameToString($dep, true)) {
                   67813:                         array_pop($skipnames);
                   67814:                     }
                   67815: 
                   67816:                     continue;
                   67817:                 }
                   67818: 
                   67819:                 if ($nodownload) {
                   67820:                     continue;
                   67821:                 }
                   67822: 
                   67823:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   67824:                 if (isset($newdep)) {
                   67825:                     $dep = $newdep;
                   67826:                 }
                   67827: 
                   67828:                 $dep['package'] = $dep['name'];
                   67829:                 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
                   67830:                     isset($dep['optional']) && $dep['optional'] == 'yes' &&
                   67831:                     !isset($options['alldeps']), true);
                   67832:                 PEAR::popErrorHandling();
                   67833:                 if (PEAR::isError($ret)) {
                   67834:                     if (!isset($options['soft'])) {
                   67835:                         $this->_downloader->log(0, $ret->getMessage());
                   67836:                     }
                   67837:                     continue;
                   67838:                 }
                   67839: 
                   67840:                 $this->_downloadDeps[] = $ret;
                   67841:             }
                   67842:         }
                   67843: 
                   67844:         if (count($skipnames)) {
                   67845:             if (!isset($options['soft'])) {
                   67846:                 $this->_downloader->log(1, 'Did not download dependencies: ' .
                   67847:                     implode(', ', $skipnames) .
                   67848:                     ', use --alldeps or --onlyreqdeps to download automatically');
                   67849:             }
                   67850:         }
                   67851:     }
                   67852: 
                   67853:     function setDownloadURL($pkg)
                   67854:     {
                   67855:         $this->_downloadURL = $pkg;
                   67856:     }
                   67857: 
                   67858:     /**
                   67859:      * Set the package.xml object for this downloaded package
                   67860:      *
                   67861:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
                   67862:      */
                   67863:     function setPackageFile(&$pkg)
                   67864:     {
                   67865:         $this->_packagefile = &$pkg;
                   67866:     }
                   67867: 
                   67868:     function getShortName()
                   67869:     {
                   67870:         return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
                   67871:             'package' => $this->getPackage()), true);
                   67872:     }
                   67873: 
                   67874:     function getParsedPackage()
                   67875:     {
                   67876:         if (isset($this->_packagefile) || isset($this->_parsedname)) {
                   67877:             return array('channel' => $this->getChannel(),
                   67878:                 'package' => $this->getPackage(),
                   67879:                 'version' => $this->getVersion());
                   67880:         }
                   67881: 
                   67882:         return false;
                   67883:     }
                   67884: 
                   67885:     function getDownloadURL()
                   67886:     {
                   67887:         return $this->_downloadURL;
                   67888:     }
                   67889: 
                   67890:     function canDefault()
                   67891:     {
                   67892:         if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
                   67893:             return false;
                   67894:         }
                   67895: 
                   67896:         return true;
                   67897:     }
                   67898: 
                   67899:     function getPackage()
                   67900:     {
                   67901:         if (isset($this->_packagefile)) {
                   67902:             return $this->_packagefile->getPackage();
                   67903:         } elseif (isset($this->_downloadURL['info'])) {
                   67904:             return $this->_downloadURL['info']->getPackage();
                   67905:         }
                   67906: 
                   67907:         return false;
                   67908:     }
                   67909: 
                   67910:     /**
                   67911:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   67912:      */
                   67913:     function isSubpackage(&$pf)
                   67914:     {
                   67915:         if (isset($this->_packagefile)) {
                   67916:             return $this->_packagefile->isSubpackage($pf);
                   67917:         } elseif (isset($this->_downloadURL['info'])) {
                   67918:             return $this->_downloadURL['info']->isSubpackage($pf);
                   67919:         }
                   67920: 
                   67921:         return false;
                   67922:     }
                   67923: 
                   67924:     function getPackageType()
                   67925:     {
                   67926:         if (isset($this->_packagefile)) {
                   67927:             return $this->_packagefile->getPackageType();
                   67928:         } elseif (isset($this->_downloadURL['info'])) {
                   67929:             return $this->_downloadURL['info']->getPackageType();
                   67930:         }
                   67931: 
                   67932:         return false;
                   67933:     }
                   67934: 
                   67935:     function isBundle()
                   67936:     {
                   67937:         if (isset($this->_packagefile)) {
                   67938:             return $this->_packagefile->getPackageType() == 'bundle';
                   67939:         }
                   67940: 
                   67941:         return false;
                   67942:     }
                   67943: 
                   67944:     function getPackageXmlVersion()
                   67945:     {
                   67946:         if (isset($this->_packagefile)) {
                   67947:             return $this->_packagefile->getPackagexmlVersion();
                   67948:         } elseif (isset($this->_downloadURL['info'])) {
                   67949:             return $this->_downloadURL['info']->getPackagexmlVersion();
                   67950:         }
                   67951: 
                   67952:         return '1.0';
                   67953:     }
                   67954: 
                   67955:     function getChannel()
                   67956:     {
                   67957:         if (isset($this->_packagefile)) {
                   67958:             return $this->_packagefile->getChannel();
                   67959:         } elseif (isset($this->_downloadURL['info'])) {
                   67960:             return $this->_downloadURL['info']->getChannel();
                   67961:         }
                   67962: 
                   67963:         return false;
                   67964:     }
                   67965: 
                   67966:     function getURI()
                   67967:     {
                   67968:         if (isset($this->_packagefile)) {
                   67969:             return $this->_packagefile->getURI();
                   67970:         } elseif (isset($this->_downloadURL['info'])) {
                   67971:             return $this->_downloadURL['info']->getURI();
                   67972:         }
                   67973: 
                   67974:         return false;
                   67975:     }
                   67976: 
                   67977:     function getVersion()
                   67978:     {
                   67979:         if (isset($this->_packagefile)) {
                   67980:             return $this->_packagefile->getVersion();
                   67981:         } elseif (isset($this->_downloadURL['version'])) {
                   67982:             return $this->_downloadURL['version'];
                   67983:         }
                   67984: 
                   67985:         return false;
                   67986:     }
                   67987: 
                   67988:     function isCompatible($pf)
                   67989:     {
                   67990:         if (isset($this->_packagefile)) {
                   67991:             return $this->_packagefile->isCompatible($pf);
                   67992:         } elseif (isset($this->_downloadURL['info'])) {
                   67993:             return $this->_downloadURL['info']->isCompatible($pf);
                   67994:         }
                   67995: 
                   67996:         return true;
                   67997:     }
                   67998: 
                   67999:     function setGroup($group)
                   68000:     {
                   68001:         $this->_parsedname['group'] = $group;
                   68002:     }
                   68003: 
                   68004:     function getGroup()
                   68005:     {
                   68006:         if (isset($this->_parsedname['group'])) {
                   68007:             return $this->_parsedname['group'];
                   68008:         }
                   68009: 
                   68010:         return '';
                   68011:     }
                   68012: 
                   68013:     function isExtension($name)
                   68014:     {
                   68015:         if (isset($this->_packagefile)) {
                   68016:             return $this->_packagefile->isExtension($name);
                   68017:         } elseif (isset($this->_downloadURL['info'])) {
                   68018:             if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
                   68019:                 return $this->_downloadURL['info']->getProvidesExtension() == $name;
                   68020:             }
                   68021: 
                   68022:             return false;
                   68023:         }
                   68024: 
                   68025:         return false;
                   68026:     }
                   68027: 
                   68028:     function getDeps()
                   68029:     {
                   68030:         if (isset($this->_packagefile)) {
                   68031:             $ver = $this->_packagefile->getPackagexmlVersion();
                   68032:             if (version_compare($ver, '2.0', '>=')) {
                   68033:                 return $this->_packagefile->getDeps(true);
                   68034:             }
                   68035: 
                   68036:             return $this->_packagefile->getDeps();
                   68037:         } elseif (isset($this->_downloadURL['info'])) {
                   68038:             $ver = $this->_downloadURL['info']->getPackagexmlVersion();
                   68039:             if (version_compare($ver, '2.0', '>=')) {
                   68040:                 return $this->_downloadURL['info']->getDeps(true);
                   68041:             }
                   68042: 
                   68043:             return $this->_downloadURL['info']->getDeps();
                   68044:         }
                   68045: 
                   68046:         return array();
                   68047:     }
                   68048: 
                   68049:     /**
                   68050:      * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
                   68051:      *                     returned from getDepDownloadURL()
                   68052:      */
                   68053:     function isEqual($param)
                   68054:     {
                   68055:         if (is_object($param)) {
                   68056:             $channel = $param->getChannel();
                   68057:             $package = $param->getPackage();
                   68058:             if ($param->getURI()) {
                   68059:                 $param = array(
                   68060:                     'channel' => $param->getChannel(),
                   68061:                     'package' => $param->getPackage(),
                   68062:                     'version' => $param->getVersion(),
                   68063:                     'uri' => $param->getURI(),
                   68064:                 );
                   68065:             } else {
                   68066:                 $param = array(
                   68067:                     'channel' => $param->getChannel(),
                   68068:                     'package' => $param->getPackage(),
                   68069:                     'version' => $param->getVersion(),
                   68070:                 );
                   68071:             }
                   68072:         } else {
                   68073:             if (isset($param['uri'])) {
                   68074:                 if ($this->getChannel() != '__uri') {
                   68075:                     return false;
                   68076:                 }
                   68077:                 return $param['uri'] == $this->getURI();
                   68078:             }
                   68079: 
                   68080:             $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
                   68081:             $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
                   68082:             if (isset($param['rel'])) {
                   68083:                 if (!class_exists('PEAR_Dependency2')) {
                   68084:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   68085:                 }
                   68086: 
                   68087:                 $newdep = PEAR_Dependency2::normalizeDep($param);
                   68088:                 $newdep = $newdep[0];
                   68089:             } elseif (isset($param['min'])) {
                   68090:                 $newdep = $param;
                   68091:             }
                   68092:         }
                   68093: 
                   68094:         if (isset($newdep)) {
                   68095:             if (!isset($newdep['min'])) {
                   68096:                 $newdep['min'] = '0';
                   68097:             }
                   68098: 
                   68099:             if (!isset($newdep['max'])) {
                   68100:                 $newdep['max'] = '100000000000000000000';
                   68101:             }
                   68102: 
                   68103:             // use magic to support pecl packages suddenly jumping to the pecl channel
                   68104:             // we need to support both dependency possibilities
                   68105:             if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
                   68106:                 if ($package == $this->getPackage()) {
                   68107:                     $channel = 'pecl.php.net';
                   68108:                 }
                   68109:             }
                   68110:             if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   68111:                 if ($package == $this->getPackage()) {
                   68112:                     $channel = 'pear.php.net';
                   68113:                 }
                   68114:             }
                   68115: 
                   68116:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   68117:                 $channel == $this->getChannel() &&
                   68118:                 version_compare($newdep['min'], $this->getVersion(), '<=') &&
                   68119:                 version_compare($newdep['max'], $this->getVersion(), '>='));
                   68120:         }
                   68121: 
                   68122:         // use magic to support pecl packages suddenly jumping to the pecl channel
                   68123:         if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   68124:             if (strtolower($package) == strtolower($this->getPackage())) {
                   68125:                 $channel = 'pear.php.net';
                   68126:             }
                   68127:         }
                   68128: 
                   68129:         if (isset($param['version'])) {
                   68130:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   68131:                 $channel == $this->getChannel() &&
                   68132:                 $param['version'] == $this->getVersion());
                   68133:         }
                   68134: 
                   68135:         return strtolower($package) == strtolower($this->getPackage()) &&
                   68136:             $channel == $this->getChannel();
                   68137:     }
                   68138: 
                   68139:     function isInstalled($dep, $oper = '==')
                   68140:     {
                   68141:         if (!$dep) {
                   68142:             return false;
                   68143:         }
                   68144: 
                   68145:         if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
                   68146:             return false;
                   68147:         }
                   68148: 
                   68149:         if (is_object($dep)) {
                   68150:             $package = $dep->getPackage();
                   68151:             $channel = $dep->getChannel();
                   68152:             if ($dep->getURI()) {
                   68153:                 $dep = array(
                   68154:                     'uri' => $dep->getURI(),
                   68155:                     'version' => $dep->getVersion(),
                   68156:                 );
                   68157:             } else {
                   68158:                 $dep = array(
                   68159:                     'version' => $dep->getVersion(),
                   68160:                 );
                   68161:             }
                   68162:         } else {
                   68163:             if (isset($dep['uri'])) {
                   68164:                 $channel = '__uri';
                   68165:                 $package = $dep['dep']['name'];
                   68166:             } else {
                   68167:                 $channel = $dep['info']->getChannel();
                   68168:                 $package = $dep['info']->getPackage();
                   68169:             }
                   68170:         }
                   68171: 
                   68172:         $options = $this->_downloader->getOptions();
                   68173:         $test    = $this->_installRegistry->packageExists($package, $channel);
                   68174:         if (!$test && $channel == 'pecl.php.net') {
                   68175:             // do magic to allow upgrading from old pecl packages to new ones
                   68176:             $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
                   68177:             $channel = 'pear.php.net';
                   68178:         }
                   68179: 
                   68180:         if ($test) {
                   68181:             if (isset($dep['uri'])) {
                   68182:                 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
                   68183:                     return true;
                   68184:                 }
                   68185:             }
                   68186: 
                   68187:             if (isset($options['upgrade'])) {
                   68188:                 $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
                   68189:                 if (version_compare($packageVersion, $dep['version'], '>=')) {
                   68190:                     return true;
                   68191:                 }
                   68192: 
                   68193:                 return false;
                   68194:             }
                   68195: 
                   68196:             return true;
                   68197:         }
                   68198: 
                   68199:         return false;
                   68200:     }
                   68201: 
                   68202:     /**
                   68203:      * Detect duplicate package names with differing versions
                   68204:      *
                   68205:      * If a user requests to install Date 1.4.6 and Date 1.4.7,
                   68206:      * for instance, this is a logic error.  This method
                   68207:      * detects this situation.
                   68208:      *
                   68209:      * @param array $params array of PEAR_Downloader_Package objects
                   68210:      * @param array $errorparams empty array
                   68211:      * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
                   68212:      */
                   68213:     function detectStupidDuplicates($params, &$errorparams)
                   68214:     {
                   68215:         $existing = array();
                   68216:         foreach ($params as $i => $param) {
                   68217:             $package = $param->getPackage();
                   68218:             $channel = $param->getChannel();
                   68219:             $group   = $param->getGroup();
                   68220:             if (!isset($existing[$channel . '/' . $package])) {
                   68221:                 $existing[$channel . '/' . $package] = array();
                   68222:             }
                   68223: 
                   68224:             if (!isset($existing[$channel . '/' . $package][$group])) {
                   68225:                 $existing[$channel . '/' . $package][$group] = array();
                   68226:             }
                   68227: 
                   68228:             $existing[$channel . '/' . $package][$group][] = $i;
                   68229:         }
                   68230: 
                   68231:         $indices = array();
                   68232:         foreach ($existing as $package => $groups) {
                   68233:             foreach ($groups as $group => $dupes) {
                   68234:                 if (count($dupes) > 1) {
                   68235:                     $indices = $indices + $dupes;
                   68236:                 }
                   68237:             }
                   68238:         }
                   68239: 
                   68240:         $indices = array_unique($indices);
                   68241:         foreach ($indices as $index) {
                   68242:             $errorparams[] = $params[$index];
                   68243:         }
                   68244: 
                   68245:         return count($errorparams);
                   68246:     }
                   68247: 
                   68248:     /**
                   68249:      * @param array
                   68250:      * @param bool ignore install groups - for final removal of dupe packages
                   68251:      * @static
                   68252:      */
                   68253:     function removeDuplicates(&$params, $ignoreGroups = false)
                   68254:     {
                   68255:         $pnames = array();
                   68256:         foreach ($params as $i => $param) {
                   68257:             if (!$param) {
                   68258:                 continue;
                   68259:             }
                   68260: 
                   68261:             if ($param->getPackage()) {
                   68262:                 $group = $ignoreGroups ? '' : $param->getGroup();
                   68263:                 $pnames[$i] = $param->getChannel() . '/' .
                   68264:                     $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
                   68265:             }
                   68266:         }
                   68267: 
                   68268:         $pnames = array_unique($pnames);
                   68269:         $unset  = array_diff(array_keys($params), array_keys($pnames));
                   68270:         $testp  = array_flip($pnames);
                   68271:         foreach ($params as $i => $param) {
                   68272:             if (!$param) {
                   68273:                 $unset[] = $i;
                   68274:                 continue;
                   68275:             }
                   68276: 
                   68277:             if (!is_a($param, 'PEAR_Downloader_Package')) {
                   68278:                 $unset[] = $i;
                   68279:                 continue;
                   68280:             }
                   68281: 
                   68282:             $group = $ignoreGroups ? '' : $param->getGroup();
                   68283:             if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
                   68284:                   $param->getVersion() . '#' . $group])) {
                   68285:                 $unset[] = $i;
                   68286:             }
                   68287:         }
                   68288: 
                   68289:         foreach ($unset as $i) {
                   68290:             unset($params[$i]);
                   68291:         }
                   68292: 
                   68293:         $ret = array();
                   68294:         foreach ($params as $i => $param) {
                   68295:             $ret[] = &$params[$i];
                   68296:         }
                   68297: 
                   68298:         $params = array();
                   68299:         foreach ($ret as $i => $param) {
                   68300:             $params[] = &$ret[$i];
                   68301:         }
                   68302:     }
                   68303: 
                   68304:     function explicitState()
                   68305:     {
                   68306:         return $this->_explicitState;
                   68307:     }
                   68308: 
                   68309:     function setExplicitState($s)
                   68310:     {
                   68311:         $this->_explicitState = $s;
                   68312:     }
                   68313: 
                   68314:     /**
                   68315:      * @static
                   68316:      */
                   68317:     function mergeDependencies(&$params)
                   68318:     {
                   68319:         $bundles = $newparams = array();
                   68320:         foreach ($params as $i => $param) {
                   68321:             if (!$param->isBundle()) {
                   68322:                 continue;
                   68323:             }
                   68324: 
                   68325:             $bundles[] = $i;
                   68326:             $pf = &$param->getPackageFile();
                   68327:             $newdeps = array();
                   68328:             $contents = $pf->getBundledPackages();
                   68329:             if (!is_array($contents)) {
                   68330:                 $contents = array($contents);
                   68331:             }
                   68332: 
                   68333:             foreach ($contents as $file) {
                   68334:                 $filecontents = $pf->getFileContents($file);
                   68335:                 $dl = &$param->getDownloader();
                   68336:                 $options = $dl->getOptions();
                   68337:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   68338:                     return $dir;
                   68339:                 }
                   68340: 
                   68341:                 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
                   68342:                 if (!$fp) {
                   68343:                     continue;
                   68344:                 }
                   68345: 
                   68346:                 // FIXME do symlink check
                   68347: 
                   68348:                 fwrite($fp, $filecontents, strlen($filecontents));
                   68349:                 fclose($fp);
                   68350:                 if ($s = $params[$i]->explicitState()) {
                   68351:                     $obj->setExplicitState($s);
                   68352:                 }
                   68353: 
                   68354:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   68355:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68356:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   68357:                     PEAR::popErrorHandling();
                   68358:                     return $dir;
                   68359:                 }
                   68360: 
                   68361:                 $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file);
                   68362:                 PEAR::popErrorHandling();
                   68363:                 if (PEAR::isError($e)) {
                   68364:                     if (!isset($options['soft'])) {
                   68365:                         $dl->log(0, $e->getMessage());
                   68366:                     }
                   68367:                     continue;
                   68368:                 }
                   68369: 
                   68370:                 $j = &$obj;
                   68371:                 if (!PEAR_Downloader_Package::willDownload($j,
                   68372:                       array_merge($params, $newparams)) && !$param->isInstalled($j)) {
                   68373:                     $newparams[] = &$j;
                   68374:                 }
                   68375:             }
                   68376:         }
                   68377: 
                   68378:         foreach ($bundles as $i) {
                   68379:             unset($params[$i]); // remove bundles - only their contents matter for installation
                   68380:         }
                   68381: 
                   68382:         PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
                   68383:         if (count($newparams)) { // add in bundled packages for install
                   68384:             foreach ($newparams as $i => $unused) {
                   68385:                 $params[] = &$newparams[$i];
                   68386:             }
                   68387:             $newparams = array();
                   68388:         }
                   68389: 
                   68390:         foreach ($params as $i => $param) {
                   68391:             $newdeps = array();
                   68392:             foreach ($param->_downloadDeps as $dep) {
                   68393:                 $merge = array_merge($params, $newparams);
                   68394:                 if (!PEAR_Downloader_Package::willDownload($dep, $merge)
                   68395:                     && !$param->isInstalled($dep)
                   68396:                 ) {
                   68397:                     $newdeps[] = $dep;
                   68398:                 } else {
                   68399:                     //var_dump($dep);
                   68400:                     // detect versioning conflicts here
                   68401:                 }
                   68402:             }
                   68403: 
                   68404:             // convert the dependencies into PEAR_Downloader_Package objects for the next time around
                   68405:             $params[$i]->_downloadDeps = array();
                   68406:             foreach ($newdeps as $dep) {
                   68407:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   68408:                 if ($s = $params[$i]->explicitState()) {
                   68409:                     $obj->setExplicitState($s);
                   68410:                 }
                   68411: 
                   68412:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68413:                 $e = $obj->fromDepURL($dep);
                   68414:                 PEAR::popErrorHandling();
                   68415:                 if (PEAR::isError($e)) {
                   68416:                     if (!isset($options['soft'])) {
                   68417:                         $obj->_downloader->log(0, $e->getMessage());
                   68418:                     }
                   68419:                     continue;
                   68420:                 }
                   68421: 
                   68422:                 $e = $obj->detectDependencies($params);
                   68423:                 if (PEAR::isError($e)) {
                   68424:                     if (!isset($options['soft'])) {
                   68425:                         $obj->_downloader->log(0, $e->getMessage());
                   68426:                     }
                   68427:                 }
                   68428: 
                   68429:                 $j = &$obj;
                   68430:                 $newparams[] = &$j;
                   68431:             }
                   68432:         }
                   68433: 
                   68434:         if (count($newparams)) {
                   68435:             foreach ($newparams as $i => $unused) {
                   68436:                 $params[] = &$newparams[$i];
                   68437:             }
                   68438:             return true;
                   68439:         }
                   68440: 
                   68441:         return false;
                   68442:     }
                   68443: 
                   68444: 
                   68445:     /**
                   68446:      * @static
                   68447:      */
                   68448:     function willDownload($param, $params)
                   68449:     {
                   68450:         if (!is_array($params)) {
                   68451:             return false;
                   68452:         }
                   68453: 
                   68454:         foreach ($params as $obj) {
                   68455:             if ($obj->isEqual($param)) {
                   68456:                 return true;
                   68457:             }
                   68458:         }
                   68459: 
                   68460:         return false;
                   68461:     }
                   68462: 
                   68463:     /**
                   68464:      * For simpler unit-testing
                   68465:      * @param PEAR_Config
                   68466:      * @param int
                   68467:      * @param string
                   68468:      */
                   68469:     function &getPackagefileObject(&$c, $d)
                   68470:     {
                   68471:         $a = &new PEAR_PackageFile($c, $d);
                   68472:         return $a;
                   68473:     }
                   68474: 
                   68475:     /**
                   68476:      * This will retrieve from a local file if possible, and parse out
                   68477:      * a group name as well.  The original parameter will be modified to reflect this.
                   68478:      * @param string|array can be a parsed package name as well
                   68479:      * @access private
                   68480:      */
                   68481:     function _fromFile(&$param)
                   68482:     {
                   68483:         $saveparam = $param;
                   68484:         if (is_string($param)) {
                   68485:             if (!@file_exists($param)) {
                   68486:                 $test = explode('#', $param);
                   68487:                 $group = array_pop($test);
                   68488:                 if (@file_exists(implode('#', $test))) {
                   68489:                     $this->setGroup($group);
                   68490:                     $param = implode('#', $test);
                   68491:                     $this->_explicitGroup = true;
                   68492:                 }
                   68493:             }
                   68494: 
                   68495:             if (@is_file($param)) {
                   68496:                 $this->_type = 'local';
                   68497:                 $options = $this->_downloader->getOptions();
                   68498:                 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
                   68499:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68500:                 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
                   68501:                 PEAR::popErrorHandling();
                   68502:                 if (PEAR::isError($pf)) {
                   68503:                     $this->_valid = false;
                   68504:                     $param = $saveparam;
                   68505:                     return $pf;
                   68506:                 }
                   68507:                 $this->_packagefile = &$pf;
                   68508:                 if (!$this->getGroup()) {
                   68509:                     $this->setGroup('default'); // install the default dependency group
                   68510:                 }
                   68511:                 return $this->_valid = true;
                   68512:             }
                   68513:         }
                   68514:         $param = $saveparam;
                   68515:         return $this->_valid = false;
                   68516:     }
                   68517: 
                   68518:     function _fromUrl($param, $saveparam = '')
                   68519:     {
                   68520:         if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
                   68521:             $options = $this->_downloader->getOptions();
                   68522:             $this->_type = 'url';
                   68523:             $callback = $this->_downloader->ui ?
                   68524:                 array(&$this->_downloader, '_downloadCallback') : null;
                   68525:             $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
                   68526:             if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
                   68527:                 $this->_downloader->popErrorHandling();
                   68528:                 return $dir;
                   68529:             }
                   68530: 
                   68531:             $this->_downloader->log(3, 'Downloading "' . $param . '"');
                   68532:             $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
                   68533:                 $dir, $callback, null, false, $this->getChannel());
                   68534:             $this->_downloader->popErrorHandling();
                   68535:             if (PEAR::isError($file)) {
                   68536:                 if (!empty($saveparam)) {
                   68537:                     $saveparam = ", cannot download \"$saveparam\"";
                   68538:                 }
                   68539:                 $err = PEAR::raiseError('Could not download from "' . $param .
                   68540:                     '"' . $saveparam . ' (' . $file->getMessage() . ')');
                   68541:                     return $err;
                   68542:             }
                   68543: 
                   68544:             if ($this->_rawpackagefile) {
                   68545:                 require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
                   68546:                 $tar = &new Archive_Tar($file);
                   68547:                 $packagexml = $tar->extractInString('package2.xml');
                   68548:                 if (!$packagexml) {
                   68549:                     $packagexml = $tar->extractInString('package.xml');
                   68550:                 }
                   68551: 
                   68552:                 if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
                   68553:                       str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
                   68554:                     if ($this->getChannel() != 'pear.php.net') {
                   68555:                         return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
                   68556:                             'not match value returned from xml-rpc');
                   68557:                     }
                   68558: 
                   68559:                     // be more lax for the existing PEAR packages that have not-ok
                   68560:                     // characters in their package.xml
                   68561:                     $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
                   68562:                         $this->getPackage() . '" package has invalid characters in its ' .
                   68563:                         'package.xml.  The next version of PEAR may not be able to install ' .
                   68564:                         'this package for security reasons.  Please open a bug report at ' .
                   68565:                         'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
                   68566:                 }
                   68567:             }
                   68568: 
                   68569:             // whew, download worked!
                   68570:             $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
                   68571: 
                   68572:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68573:             $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
                   68574:             PEAR::popErrorHandling();
                   68575:             if (PEAR::isError($pf)) {
                   68576:                 if (is_array($pf->getUserInfo())) {
                   68577:                     foreach ($pf->getUserInfo() as $err) {
                   68578:                         if (is_array($err)) {
                   68579:                             $err = $err['message'];
                   68580:                         }
                   68581: 
                   68582:                         if (!isset($options['soft'])) {
                   68583:                             $this->_downloader->log(0, "Validation Error: $err");
                   68584:                         }
                   68585:                     }
                   68586:                 }
                   68587: 
                   68588:                 if (!isset($options['soft'])) {
                   68589:                     $this->_downloader->log(0, $pf->getMessage());
                   68590:                 }
                   68591: 
                   68592:                 ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
                   68593:                 /// At least stop all deps of this package from being installed
                   68594:                 $out = $saveparam ? $saveparam : $param;
                   68595:                 $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
                   68596:                 $this->_valid = false;
                   68597:                 return $err;
                   68598:             }
                   68599: 
                   68600:             $this->_packagefile = &$pf;
                   68601:             $this->setGroup('default'); // install the default dependency group
                   68602:             return $this->_valid = true;
                   68603:         }
                   68604: 
                   68605:         return $this->_valid = false;
                   68606:     }
                   68607: 
                   68608:     /**
                   68609:      *
                   68610:      * @param string|array pass in an array of format
                   68611:      *                     array(
                   68612:      *                      'package' => 'pname',
                   68613:      *                     ['channel' => 'channame',]
                   68614:      *                     ['version' => 'version',]
                   68615:      *                     ['state' => 'state',])
                   68616:      *                     or a string of format [channame/]pname[-version|-state]
                   68617:      */
                   68618:     function _fromString($param)
                   68619:     {
                   68620:         $options = $this->_downloader->getOptions();
                   68621:         $channel = $this->_config->get('default_channel');
                   68622:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68623:         $pname = $this->_registry->parsePackageName($param, $channel);
                   68624:         PEAR::popErrorHandling();
                   68625:         if (PEAR::isError($pname)) {
                   68626:             if ($pname->getCode() == 'invalid') {
                   68627:                 $this->_valid = false;
                   68628:                 return false;
                   68629:             }
                   68630: 
                   68631:             if ($pname->getCode() == 'channel') {
                   68632:                 $parsed = $pname->getUserInfo();
                   68633:                 if ($this->_downloader->discover($parsed['channel'])) {
                   68634:                     if ($this->_config->get('auto_discover')) {
                   68635:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   68636:                         $pname = $this->_registry->parsePackageName($param, $channel);
                   68637:                         PEAR::popErrorHandling();
                   68638:                     } else {
                   68639:                         if (!isset($options['soft'])) {
                   68640:                             $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
                   68641:                                 '" is not initialized, use ' .
                   68642:                                 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
                   68643:                                 'or pear config-set auto_discover 1');
                   68644:                         }
                   68645:                     }
                   68646:                 }
                   68647: 
                   68648:                 if (PEAR::isError($pname)) {
                   68649:                     if (!isset($options['soft'])) {
                   68650:                         $this->_downloader->log(0, $pname->getMessage());
                   68651:                     }
                   68652: 
                   68653:                     if (is_array($param)) {
                   68654:                         $param = $this->_registry->parsedPackageNameToString($param);
                   68655:                     }
                   68656: 
                   68657:                     $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   68658:                     $this->_valid = false;
                   68659:                     return $err;
                   68660:                 }
                   68661:             } else {
                   68662:                 if (!isset($options['soft'])) {
                   68663:                     $this->_downloader->log(0, $pname->getMessage());
                   68664:                 }
                   68665: 
                   68666:                 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   68667:                 $this->_valid = false;
                   68668:                 return $err;
                   68669:             }
                   68670:         }
                   68671: 
                   68672:         if (!isset($this->_type)) {
                   68673:             $this->_type = 'rest';
                   68674:         }
                   68675: 
                   68676:         $this->_parsedname    = $pname;
                   68677:         $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
                   68678:         $this->_explicitGroup = isset($pname['group']) ? true : false;
                   68679: 
                   68680:         $info = $this->_downloader->_getPackageDownloadUrl($pname);
                   68681:         if (PEAR::isError($info)) {
                   68682:             if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
                   68683:                 // try pecl
                   68684:                 $pname['channel'] = 'pecl.php.net';
                   68685:                 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
                   68686:                     if (!PEAR::isError($test)) {
                   68687:                         $info = PEAR::raiseError($info->getMessage() . ' - package ' .
                   68688:                             $this->_registry->parsedPackageNameToString($pname, true) .
                   68689:                             ' can be installed with "pecl install ' . $pname['package'] .
                   68690:                             '"');
                   68691:                     } else {
                   68692:                         $pname['channel'] = 'pear.php.net';
                   68693:                     }
                   68694:                 } else {
                   68695:                     $pname['channel'] = 'pear.php.net';
                   68696:                 }
                   68697:             }
                   68698: 
                   68699:             return $info;
                   68700:         }
                   68701: 
                   68702:         $this->_rawpackagefile = $info['raw'];
                   68703:         $ret = $this->_analyzeDownloadURL($info, $param, $pname);
                   68704:         if (PEAR::isError($ret)) {
                   68705:             return $ret;
                   68706:         }
                   68707: 
                   68708:         if ($ret) {
                   68709:             $this->_downloadURL = $ret;
                   68710:             return $this->_valid = (bool) $ret;
                   68711:         }
                   68712:     }
                   68713: 
                   68714:     /**
                   68715:      * @param array output of package.getDownloadURL
                   68716:      * @param string|array|object information for detecting packages to be downloaded, and
                   68717:      *                            for errors
                   68718:      * @param array name information of the package
                   68719:      * @param array|null packages to be downloaded
                   68720:      * @param bool is this an optional dependency?
                   68721:      * @param bool is this any kind of dependency?
                   68722:      * @access private
                   68723:      */
                   68724:     function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
                   68725:                                  $isdependency = false)
                   68726:     {
                   68727:         if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
                   68728:             return false;
                   68729:         }
                   68730: 
                   68731:         if ($info === false) {
                   68732:             $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
                   68733: 
                   68734:             // no releases exist
                   68735:             return PEAR::raiseError('No releases for package "' .
                   68736:                 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
                   68737:         }
                   68738: 
                   68739:         if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
                   68740:             $err = false;
                   68741:             if ($pname['channel'] == 'pecl.php.net') {
                   68742:                 if ($info['info']->getChannel() != 'pear.php.net') {
                   68743:                     $err = true;
                   68744:                 }
                   68745:             } elseif ($info['info']->getChannel() == 'pecl.php.net') {
                   68746:                 if ($pname['channel'] != 'pear.php.net') {
                   68747:                     $err = true;
                   68748:                 }
                   68749:             } else {
                   68750:                 $err = true;
                   68751:             }
                   68752: 
                   68753:             if ($err) {
                   68754:                 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
                   68755:                     '" retrieved another channel\'s name for download! ("' .
                   68756:                     $info['info']->getChannel() . '")');
                   68757:             }
                   68758:         }
                   68759: 
                   68760:         $preferred_state = $this->_config->get('preferred_state');
                   68761:         if (!isset($info['url'])) {
                   68762:             $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
                   68763:             'version', $info['info']->getChannel());
                   68764:             if ($this->isInstalled($info)) {
                   68765:                 if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
                   68766:                     // ignore bogus errors of "failed to download dependency"
                   68767:                     // if it is already installed and the one that would be
                   68768:                     // downloaded is older or the same version (Bug #7219)
                   68769:                     return false;
                   68770:                 }
                   68771:             }
                   68772: 
                   68773:             if ($info['version'] === $package_version) {
                   68774:                 if (!isset($options['soft'])) {
                   68775:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   68776:                         '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
                   68777:                         ' (' . $package_version . ') is the same as the locally installed one.');
                   68778:                 }
                   68779: 
                   68780:                 return false;
                   68781:             }
                   68782: 
                   68783:             if (version_compare($info['version'], $package_version, '<=')) {
                   68784:                 if (!isset($options['soft'])) {
                   68785:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   68786:                         '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
                   68787:                         ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
                   68788:                 }
                   68789: 
                   68790:                 return false;
                   68791:             }
                   68792: 
                   68793:             $instead =  ', will instead download version ' . $info['version'] .
                   68794:                         ', stability "' . $info['info']->getState() . '"';
                   68795:             // releases exist, but we failed to get any
                   68796:             if (isset($this->_downloader->_options['force'])) {
                   68797:                 if (isset($pname['version'])) {
                   68798:                     $vs = ', version "' . $pname['version'] . '"';
                   68799:                 } elseif (isset($pname['state'])) {
                   68800:                     $vs = ', stability "' . $pname['state'] . '"';
                   68801:                 } elseif ($param == 'dependency') {
                   68802:                     if (!class_exists('PEAR_Common')) {
                   68803:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   68804:                     }
                   68805: 
                   68806:                     if (!in_array($info['info']->getState(),
                   68807:                           PEAR_Common::betterStates($preferred_state, true))) {
                   68808:                         if ($optional) {
                   68809:                             // don't spit out confusing error message
                   68810:                             return $this->_downloader->_getPackageDownloadUrl(
                   68811:                                 array('package' => $pname['package'],
                   68812:                                       'channel' => $pname['channel'],
                   68813:                                       'version' => $info['version']));
                   68814:                         }
                   68815:                         $vs = ' within preferred state "' . $preferred_state .
                   68816:                             '"';
                   68817:                     } else {
                   68818:                         if (!class_exists('PEAR_Dependency2')) {
                   68819:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   68820:                         }
                   68821: 
                   68822:                         if ($optional) {
                   68823:                             // don't spit out confusing error message
                   68824:                             return $this->_downloader->_getPackageDownloadUrl(
                   68825:                                 array('package' => $pname['package'],
                   68826:                                       'channel' => $pname['channel'],
                   68827:                                       'version' => $info['version']));
                   68828:                         }
                   68829:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   68830:                         $instead = '';
                   68831:                     }
                   68832:                 } else {
                   68833:                     $vs = ' within preferred state "' . $preferred_state . '"';
                   68834:                 }
                   68835: 
                   68836:                 if (!isset($options['soft'])) {
                   68837:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   68838:                         '/' . $pname['package'] . $vs . $instead);
                   68839:                 }
                   68840: 
                   68841:                 // download the latest release
                   68842:                 return $this->_downloader->_getPackageDownloadUrl(
                   68843:                     array('package' => $pname['package'],
                   68844:                           'channel' => $pname['channel'],
                   68845:                           'version' => $info['version']));
                   68846:             } else {
                   68847:                 if (isset($info['php']) && $info['php']) {
                   68848:                     $err = PEAR::raiseError('Failed to download ' .
                   68849:                         $this->_registry->parsedPackageNameToString(
                   68850:                             array('channel' => $pname['channel'],
                   68851:                                   'package' => $pname['package']),
                   68852:                                 true) .
                   68853:                         ', latest release is version ' . $info['php']['v'] .
                   68854:                         ', but it requires PHP version "' .
                   68855:                         $info['php']['m'] . '", use "' .
                   68856:                         $this->_registry->parsedPackageNameToString(
                   68857:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   68858:                             'version' => $info['php']['v'])) . '" to install',
                   68859:                             PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
                   68860:                     return $err;
                   68861:                 }
                   68862: 
                   68863:                 // construct helpful error message
                   68864:                 if (isset($pname['version'])) {
                   68865:                     $vs = ', version "' . $pname['version'] . '"';
                   68866:                 } elseif (isset($pname['state'])) {
                   68867:                     $vs = ', stability "' . $pname['state'] . '"';
                   68868:                 } elseif ($param == 'dependency') {
                   68869:                     if (!class_exists('PEAR_Common')) {
                   68870:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   68871:                     }
                   68872: 
                   68873:                     if (!in_array($info['info']->getState(),
                   68874:                           PEAR_Common::betterStates($preferred_state, true))) {
                   68875:                         if ($optional) {
                   68876:                             // don't spit out confusing error message, and don't die on
                   68877:                             // optional dep failure!
                   68878:                             return $this->_downloader->_getPackageDownloadUrl(
                   68879:                                 array('package' => $pname['package'],
                   68880:                                       'channel' => $pname['channel'],
                   68881:                                       'version' => $info['version']));
                   68882:                         }
                   68883:                         $vs = ' within preferred state "' . $preferred_state . '"';
                   68884:                     } else {
                   68885:                         if (!class_exists('PEAR_Dependency2')) {
                   68886:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   68887:                         }
                   68888: 
                   68889:                         if ($optional) {
                   68890:                             // don't spit out confusing error message, and don't die on
                   68891:                             // optional dep failure!
                   68892:                             return $this->_downloader->_getPackageDownloadUrl(
                   68893:                                 array('package' => $pname['package'],
                   68894:                                       'channel' => $pname['channel'],
                   68895:                                       'version' => $info['version']));
                   68896:                         }
                   68897:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   68898:                     }
                   68899:                 } else {
                   68900:                     $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
                   68901:                 }
                   68902: 
                   68903:                 $options = $this->_downloader->getOptions();
                   68904:                 // this is only set by the "download-all" command
                   68905:                 if (isset($options['ignorepreferred_state'])) {
                   68906:                     $err = PEAR::raiseError(
                   68907:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   68908:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   68909:                                 true)
                   68910:                          . $vs .
                   68911:                         ', latest release is version ' . $info['version'] .
                   68912:                         ', stability "' . $info['info']->getState() . '", use "' .
                   68913:                         $this->_registry->parsedPackageNameToString(
                   68914:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   68915:                             'version' => $info['version'])) . '" to install',
                   68916:                             PEAR_DOWNLOADER_PACKAGE_STATE);
                   68917:                     return $err;
                   68918:                 }
                   68919: 
                   68920:                 // Checks if the user has a package installed already and checks the release against
                   68921:                 // the state against the installed package, this allows upgrades for packages
                   68922:                 // with lower stability than the preferred_state
                   68923:                 $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
                   68924:                 if (!$this->isInstalled($info)
                   68925:                     || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
                   68926:                 ) {
                   68927:                     $err = PEAR::raiseError(
                   68928:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   68929:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   68930:                                 true)
                   68931:                          . $vs .
                   68932:                         ', latest release is version ' . $info['version'] .
                   68933:                         ', stability "' . $info['info']->getState() . '", use "' .
                   68934:                         $this->_registry->parsedPackageNameToString(
                   68935:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   68936:                             'version' => $info['version'])) . '" to install');
                   68937:                     return $err;
                   68938:                 }
                   68939:             }
                   68940:         }
                   68941: 
                   68942:         if (isset($info['deprecated']) && $info['deprecated']) {
                   68943:             $this->_downloader->log(0,
                   68944:                 'WARNING: "' .
                   68945:                     $this->_registry->parsedPackageNameToString(
                   68946:                             array('channel' => $info['info']->getChannel(),
                   68947:                                   'package' => $info['info']->getPackage()), true) .
                   68948:                 '" is deprecated in favor of "' .
                   68949:                     $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
                   68950:                 '"');
                   68951:         }
                   68952: 
                   68953:         return $info;
                   68954:     }
                   68955: }<?php
                   68956: /**
                   68957:  * Error Stack Implementation
                   68958:  * 
                   68959:  * This is an incredibly simple implementation of a very complex error handling
                   68960:  * facility.  It contains the ability
                   68961:  * to track multiple errors from multiple packages simultaneously.  In addition,
                   68962:  * it can track errors of many levels, save data along with the error, context
                   68963:  * information such as the exact file, line number, class and function that
                   68964:  * generated the error, and if necessary, it can raise a traditional PEAR_Error.
                   68965:  * It has built-in support for PEAR::Log, to log errors as they occur
                   68966:  * 
                   68967:  * Since version 0.2alpha, it is also possible to selectively ignore errors,
                   68968:  * through the use of an error callback, see {@link pushCallback()}
                   68969:  * 
                   68970:  * Since version 0.3alpha, it is possible to specify the exception class
                   68971:  * returned from {@link push()}
                   68972:  *
                   68973:  * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
                   68974:  * still be done quite handily in an error callback or by manipulating the returned array
                   68975:  * @category   Debugging
                   68976:  * @package    PEAR_ErrorStack
                   68977:  * @author     Greg Beaver <cellog@php.net>
                   68978:  * @copyright  2004-2008 Greg Beaver
                   68979:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   68980:  * @version    CVS: $Id: ErrorStack.php 276383 2009-02-24 23:39:37Z dufuz $
                   68981:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   68982:  */
                   68983: 
                   68984: /**
                   68985:  * Singleton storage
                   68986:  * 
                   68987:  * Format:
                   68988:  * <pre>
                   68989:  * array(
                   68990:  *  'package1' => PEAR_ErrorStack object,
                   68991:  *  'package2' => PEAR_ErrorStack object,
                   68992:  *  ...
                   68993:  * )
                   68994:  * </pre>
                   68995:  * @access private
                   68996:  * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
                   68997:  */
                   68998: $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
                   68999: 
                   69000: /**
                   69001:  * Global error callback (default)
                   69002:  * 
                   69003:  * This is only used if set to non-false.  * is the default callback for
                   69004:  * all packages, whereas specific packages may set a default callback
                   69005:  * for all instances, regardless of whether they are a singleton or not.
                   69006:  *
                   69007:  * To exclude non-singletons, only set the local callback for the singleton
                   69008:  * @see PEAR_ErrorStack::setDefaultCallback()
                   69009:  * @access private
                   69010:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
                   69011:  */
                   69012: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
                   69013:     '*' => false,
                   69014: );
                   69015: 
                   69016: /**
                   69017:  * Global Log object (default)
                   69018:  * 
                   69019:  * This is only used if set to non-false.  Use to set a default log object for
                   69020:  * all stacks, regardless of instantiation order or location
                   69021:  * @see PEAR_ErrorStack::setDefaultLogger()
                   69022:  * @access private
                   69023:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   69024:  */
                   69025: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
                   69026: 
                   69027: /**
                   69028:  * Global Overriding Callback
                   69029:  * 
                   69030:  * This callback will override any error callbacks that specific loggers have set.
                   69031:  * Use with EXTREME caution
                   69032:  * @see PEAR_ErrorStack::staticPushCallback()
                   69033:  * @access private
                   69034:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   69035:  */
                   69036: $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   69037: 
                   69038: /**#@+
                   69039:  * One of four possible return values from the error Callback
                   69040:  * @see PEAR_ErrorStack::_errorCallback()
                   69041:  */
                   69042: /**
                   69043:  * If this is returned, then the error will be both pushed onto the stack
                   69044:  * and logged.
                   69045:  */
                   69046: define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
                   69047: /**
                   69048:  * If this is returned, then the error will only be pushed onto the stack,
                   69049:  * and not logged.
                   69050:  */
                   69051: define('PEAR_ERRORSTACK_PUSH', 2);
                   69052: /**
                   69053:  * If this is returned, then the error will only be logged, but not pushed
                   69054:  * onto the error stack.
                   69055:  */
                   69056: define('PEAR_ERRORSTACK_LOG', 3);
                   69057: /**
                   69058:  * If this is returned, then the error is completely ignored.
                   69059:  */
                   69060: define('PEAR_ERRORSTACK_IGNORE', 4);
                   69061: /**
                   69062:  * If this is returned, then the error is logged and die() is called.
                   69063:  */
                   69064: define('PEAR_ERRORSTACK_DIE', 5);
                   69065: /**#@-*/
                   69066: 
                   69067: /**
                   69068:  * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
                   69069:  * the singleton method.
                   69070:  */
                   69071: define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
                   69072: 
                   69073: /**
                   69074:  * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
                   69075:  * that has no __toString() method
                   69076:  */
                   69077: define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
                   69078: /**
                   69079:  * Error Stack Implementation
                   69080:  *
                   69081:  * Usage:
                   69082:  * <code>
                   69083:  * // global error stack
                   69084:  * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
                   69085:  * // local error stack
                   69086:  * $local_stack = new PEAR_ErrorStack('MyPackage');
                   69087:  * </code>
                   69088:  * @author     Greg Beaver <cellog@php.net>
                   69089:  * @version    1.10.0beta1
                   69090:  * @package    PEAR_ErrorStack
                   69091:  * @category   Debugging
                   69092:  * @copyright  2004-2008 Greg Beaver
                   69093:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   69094:  * @version    CVS: $Id: ErrorStack.php 276383 2009-02-24 23:39:37Z dufuz $
                   69095:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   69096:  */
                   69097: class PEAR_ErrorStack {
                   69098:     /**
                   69099:      * Errors are stored in the order that they are pushed on the stack.
                   69100:      * @since 0.4alpha Errors are no longer organized by error level.
                   69101:      * This renders pop() nearly unusable, and levels could be more easily
                   69102:      * handled in a callback anyway
                   69103:      * @var array
                   69104:      * @access private
                   69105:      */
                   69106:     var $_errors = array();
                   69107: 
                   69108:     /**
                   69109:      * Storage of errors by level.
                   69110:      *
                   69111:      * Allows easy retrieval and deletion of only errors from a particular level
                   69112:      * @since PEAR 1.4.0dev
                   69113:      * @var array
                   69114:      * @access private
                   69115:      */
                   69116:     var $_errorsByLevel = array();
                   69117: 
                   69118:     /**
                   69119:      * Package name this error stack represents
                   69120:      * @var string
                   69121:      * @access protected
                   69122:      */
                   69123:     var $_package;
                   69124:     
                   69125:     /**
                   69126:      * Determines whether a PEAR_Error is thrown upon every error addition
                   69127:      * @var boolean
                   69128:      * @access private
                   69129:      */
                   69130:     var $_compat = false;
                   69131:     
                   69132:     /**
                   69133:      * If set to a valid callback, this will be used to generate the error
                   69134:      * message from the error code, otherwise the message passed in will be
                   69135:      * used
                   69136:      * @var false|string|array
                   69137:      * @access private
                   69138:      */
                   69139:     var $_msgCallback = false;
                   69140:     
                   69141:     /**
                   69142:      * If set to a valid callback, this will be used to generate the error
                   69143:      * context for an error.  For PHP-related errors, this will be a file
                   69144:      * and line number as retrieved from debug_backtrace(), but can be
                   69145:      * customized for other purposes.  The error might actually be in a separate
                   69146:      * configuration file, or in a database query.
                   69147:      * @var false|string|array
                   69148:      * @access protected
                   69149:      */
                   69150:     var $_contextCallback = false;
                   69151:     
                   69152:     /**
                   69153:      * If set to a valid callback, this will be called every time an error
                   69154:      * is pushed onto the stack.  The return value will be used to determine
                   69155:      * whether to allow an error to be pushed or logged.
                   69156:      * 
                   69157:      * The return value must be one an PEAR_ERRORSTACK_* constant
                   69158:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   69159:      * @var false|string|array
                   69160:      * @access protected
                   69161:      */
                   69162:     var $_errorCallback = array();
                   69163:     
                   69164:     /**
                   69165:      * PEAR::Log object for logging errors
                   69166:      * @var false|Log
                   69167:      * @access protected
                   69168:      */
                   69169:     var $_logger = false;
                   69170:     
                   69171:     /**
                   69172:      * Error messages - designed to be overridden
                   69173:      * @var array
                   69174:      * @abstract
                   69175:      */
                   69176:     var $_errorMsgs = array();
                   69177:     
                   69178:     /**
                   69179:      * Set up a new error stack
                   69180:      * 
                   69181:      * @param string   $package name of the package this error stack represents
                   69182:      * @param callback $msgCallback callback used for error message generation
                   69183:      * @param callback $contextCallback callback used for context generation,
                   69184:      *                 defaults to {@link getFileLine()}
                   69185:      * @param boolean  $throwPEAR_Error
                   69186:      */
                   69187:     function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
                   69188:                          $throwPEAR_Error = false)
                   69189:     {
                   69190:         $this->_package = $package;
                   69191:         $this->setMessageCallback($msgCallback);
                   69192:         $this->setContextCallback($contextCallback);
                   69193:         $this->_compat = $throwPEAR_Error;
                   69194:     }
                   69195:     
                   69196:     /**
                   69197:      * Return a single error stack for this package.
                   69198:      * 
                   69199:      * Note that all parameters are ignored if the stack for package $package
                   69200:      * has already been instantiated
                   69201:      * @param string   $package name of the package this error stack represents
                   69202:      * @param callback $msgCallback callback used for error message generation
                   69203:      * @param callback $contextCallback callback used for context generation,
                   69204:      *                 defaults to {@link getFileLine()}
                   69205:      * @param boolean  $throwPEAR_Error
                   69206:      * @param string   $stackClass class to instantiate
                   69207:      * @static
                   69208:      * @return PEAR_ErrorStack
                   69209:      */
                   69210:     function &singleton($package, $msgCallback = false, $contextCallback = false,
                   69211:                          $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
                   69212:     {
                   69213:         if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   69214:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   69215:         }
                   69216:         if (!class_exists($stackClass)) {
                   69217:             if (function_exists('debug_backtrace')) {
                   69218:                 $trace = debug_backtrace();
                   69219:             }
                   69220:             PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
                   69221:                 'exception', array('stackclass' => $stackClass),
                   69222:                 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
                   69223:                 false, $trace);
                   69224:         }
                   69225:         $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
                   69226:             new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
                   69227: 
                   69228:         return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   69229:     }
                   69230: 
                   69231:     /**
                   69232:      * Internal error handler for PEAR_ErrorStack class
                   69233:      * 
                   69234:      * Dies if the error is an exception (and would have died anyway)
                   69235:      * @access private
                   69236:      */
                   69237:     function _handleError($err)
                   69238:     {
                   69239:         if ($err['level'] == 'exception') {
                   69240:             $message = $err['message'];
                   69241:             if (isset($_SERVER['REQUEST_URI'])) {
                   69242:                 echo '<br />';
                   69243:             } else {
                   69244:                 echo "\n";
                   69245:             }
                   69246:             var_dump($err['context']);
                   69247:             die($message);
                   69248:         }
                   69249:     }
                   69250:     
                   69251:     /**
                   69252:      * Set up a PEAR::Log object for all error stacks that don't have one
                   69253:      * @param Log $log 
                   69254:      * @static
                   69255:      */
                   69256:     function setDefaultLogger(&$log)
                   69257:     {
                   69258:         if (is_object($log) && method_exists($log, 'log') ) {
                   69259:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   69260:         } elseif (is_callable($log)) {
                   69261:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   69262:        }
                   69263:     }
                   69264:     
                   69265:     /**
                   69266:      * Set up a PEAR::Log object for this error stack
                   69267:      * @param Log $log 
                   69268:      */
                   69269:     function setLogger(&$log)
                   69270:     {
                   69271:         if (is_object($log) && method_exists($log, 'log') ) {
                   69272:             $this->_logger = &$log;
                   69273:         } elseif (is_callable($log)) {
                   69274:             $this->_logger = &$log;
                   69275:         }
                   69276:     }
                   69277:     
                   69278:     /**
                   69279:      * Set an error code => error message mapping callback
                   69280:      * 
                   69281:      * This method sets the callback that can be used to generate error
                   69282:      * messages for any instance
                   69283:      * @param array|string Callback function/method
                   69284:      */
                   69285:     function setMessageCallback($msgCallback)
                   69286:     {
                   69287:         if (!$msgCallback) {
                   69288:             $this->_msgCallback = array(&$this, 'getErrorMessage');
                   69289:         } else {
                   69290:             if (is_callable($msgCallback)) {
                   69291:                 $this->_msgCallback = $msgCallback;
                   69292:             }
                   69293:         }
                   69294:     }
                   69295:     
                   69296:     /**
                   69297:      * Get an error code => error message mapping callback
                   69298:      * 
                   69299:      * This method returns the current callback that can be used to generate error
                   69300:      * messages
                   69301:      * @return array|string|false Callback function/method or false if none
                   69302:      */
                   69303:     function getMessageCallback()
                   69304:     {
                   69305:         return $this->_msgCallback;
                   69306:     }
                   69307:     
                   69308:     /**
                   69309:      * Sets a default callback to be used by all error stacks
                   69310:      * 
                   69311:      * This method sets the callback that can be used to generate error
                   69312:      * messages for a singleton
                   69313:      * @param array|string Callback function/method
                   69314:      * @param string Package name, or false for all packages
                   69315:      * @static
                   69316:      */
                   69317:     function setDefaultCallback($callback = false, $package = false)
                   69318:     {
                   69319:         if (!is_callable($callback)) {
                   69320:             $callback = false;
                   69321:         }
                   69322:         $package = $package ? $package : '*';
                   69323:         $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
                   69324:     }
                   69325:     
                   69326:     /**
                   69327:      * Set a callback that generates context information (location of error) for an error stack
                   69328:      * 
                   69329:      * This method sets the callback that can be used to generate context
                   69330:      * information for an error.  Passing in NULL will disable context generation
                   69331:      * and remove the expensive call to debug_backtrace()
                   69332:      * @param array|string|null Callback function/method
                   69333:      */
                   69334:     function setContextCallback($contextCallback)
                   69335:     {
                   69336:         if ($contextCallback === null) {
                   69337:             return $this->_contextCallback = false;
                   69338:         }
                   69339:         if (!$contextCallback) {
                   69340:             $this->_contextCallback = array(&$this, 'getFileLine');
                   69341:         } else {
                   69342:             if (is_callable($contextCallback)) {
                   69343:                 $this->_contextCallback = $contextCallback;
                   69344:             }
                   69345:         }
                   69346:     }
                   69347:     
                   69348:     /**
                   69349:      * Set an error Callback
                   69350:      * If set to a valid callback, this will be called every time an error
                   69351:      * is pushed onto the stack.  The return value will be used to determine
                   69352:      * whether to allow an error to be pushed or logged.
                   69353:      * 
                   69354:      * The return value must be one of the ERRORSTACK_* constants.
                   69355:      * 
                   69356:      * This functionality can be used to emulate PEAR's pushErrorHandling, and
                   69357:      * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
                   69358:      * the error stack or logging
                   69359:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   69360:      * @see popCallback()
                   69361:      * @param string|array $cb
                   69362:      */
                   69363:     function pushCallback($cb)
                   69364:     {
                   69365:         array_push($this->_errorCallback, $cb);
                   69366:     }
                   69367:     
                   69368:     /**
                   69369:      * Remove a callback from the error callback stack
                   69370:      * @see pushCallback()
                   69371:      * @return array|string|false
                   69372:      */
                   69373:     function popCallback()
                   69374:     {
                   69375:         if (!count($this->_errorCallback)) {
                   69376:             return false;
                   69377:         }
                   69378:         return array_pop($this->_errorCallback);
                   69379:     }
                   69380:     
                   69381:     /**
                   69382:      * Set a temporary overriding error callback for every package error stack
                   69383:      *
                   69384:      * Use this to temporarily disable all existing callbacks (can be used
                   69385:      * to emulate the @ operator, for instance)
                   69386:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   69387:      * @see staticPopCallback(), pushCallback()
                   69388:      * @param string|array $cb
                   69389:      * @static
                   69390:      */
                   69391:     function staticPushCallback($cb)
                   69392:     {
                   69393:         array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
                   69394:     }
                   69395:     
                   69396:     /**
                   69397:      * Remove a temporary overriding error callback
                   69398:      * @see staticPushCallback()
                   69399:      * @return array|string|false
                   69400:      * @static
                   69401:      */
                   69402:     function staticPopCallback()
                   69403:     {
                   69404:         $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
                   69405:         if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
                   69406:             $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   69407:         }
                   69408:         return $ret;
                   69409:     }
                   69410:     
                   69411:     /**
                   69412:      * Add an error to the stack
                   69413:      * 
                   69414:      * If the message generator exists, it is called with 2 parameters.
                   69415:      *  - the current Error Stack object
                   69416:      *  - an array that is in the same format as an error.  Available indices
                   69417:      *    are 'code', 'package', 'time', 'params', 'level', and 'context'
                   69418:      * 
                   69419:      * Next, if the error should contain context information, this is
                   69420:      * handled by the context grabbing method.
                   69421:      * Finally, the error is pushed onto the proper error stack
                   69422:      * @param int    $code      Package-specific error code
                   69423:      * @param string $level     Error level.  This is NOT spell-checked
                   69424:      * @param array  $params    associative array of error parameters
                   69425:      * @param string $msg       Error message, or a portion of it if the message
                   69426:      *                          is to be generated
                   69427:      * @param array  $repackage If this error re-packages an error pushed by
                   69428:      *                          another package, place the array returned from
                   69429:      *                          {@link pop()} in this parameter
                   69430:      * @param array  $backtrace Protected parameter: use this to pass in the
                   69431:      *                          {@link debug_backtrace()} that should be used
                   69432:      *                          to find error context
                   69433:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   69434:      * thrown.  If a PEAR_Error is returned, the userinfo
                   69435:      * property is set to the following array:
                   69436:      * 
                   69437:      * <code>
                   69438:      * array(
                   69439:      *    'code' => $code,
                   69440:      *    'params' => $params,
                   69441:      *    'package' => $this->_package,
                   69442:      *    'level' => $level,
                   69443:      *    'time' => time(),
                   69444:      *    'context' => $context,
                   69445:      *    'message' => $msg,
                   69446:      * //['repackage' => $err] repackaged error array/Exception class
                   69447:      * );
                   69448:      * </code>
                   69449:      * 
                   69450:      * Normally, the previous array is returned.
                   69451:      */
                   69452:     function push($code, $level = 'error', $params = array(), $msg = false,
                   69453:                   $repackage = false, $backtrace = false)
                   69454:     {
                   69455:         $context = false;
                   69456:         // grab error context
                   69457:         if ($this->_contextCallback) {
                   69458:             if (!$backtrace) {
                   69459:                 $backtrace = debug_backtrace();
                   69460:             }
                   69461:             $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
                   69462:         }
                   69463:         
                   69464:         // save error
                   69465:         $time = explode(' ', microtime());
                   69466:         $time = $time[1] + $time[0];
                   69467:         $err = array(
                   69468:                 'code' => $code,
                   69469:                 'params' => $params,
                   69470:                 'package' => $this->_package,
                   69471:                 'level' => $level,
                   69472:                 'time' => $time,
                   69473:                 'context' => $context,
                   69474:                 'message' => $msg,
                   69475:                );
                   69476: 
                   69477:         if ($repackage) {
                   69478:             $err['repackage'] = $repackage;
                   69479:         }
                   69480: 
                   69481:         // set up the error message, if necessary
                   69482:         if ($this->_msgCallback) {
                   69483:             $msg = call_user_func_array($this->_msgCallback,
                   69484:                                         array(&$this, $err));
                   69485:             $err['message'] = $msg;
                   69486:         }        
                   69487:         $push = $log = true;
                   69488:         $die = false;
                   69489:         // try the overriding callback first
                   69490:         $callback = $this->staticPopCallback();
                   69491:         if ($callback) {
                   69492:             $this->staticPushCallback($callback);
                   69493:         }
                   69494:         if (!is_callable($callback)) {
                   69495:             // try the local callback next
                   69496:             $callback = $this->popCallback();
                   69497:             if (is_callable($callback)) {
                   69498:                 $this->pushCallback($callback);
                   69499:             } else {
                   69500:                 // try the default callback
                   69501:                 $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                   69502:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                   69503:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
                   69504:             }
                   69505:         }
                   69506:         if (is_callable($callback)) {
                   69507:             switch(call_user_func($callback, $err)){
                   69508:                case PEAR_ERRORSTACK_IGNORE: 
                   69509:                        return $err;
                   69510:                        break;
                   69511:                case PEAR_ERRORSTACK_PUSH: 
                   69512:                        $log = false;
                   69513:                        break;
                   69514:                case PEAR_ERRORSTACK_LOG: 
                   69515:                        $push = false;
                   69516:                        break;
                   69517:                case PEAR_ERRORSTACK_DIE: 
                   69518:                        $die = true;
                   69519:                        break;
                   69520:                 // anything else returned has the same effect as pushandlog
                   69521:             }
                   69522:         }
                   69523:         if ($push) {
                   69524:             array_unshift($this->_errors, $err);
                   69525:             if (!isset($this->_errorsByLevel[$err['level']])) {
                   69526:                 $this->_errorsByLevel[$err['level']] = array();
                   69527:             }
                   69528:             $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
                   69529:         }
                   69530:         if ($log) {
                   69531:             if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                   69532:                 $this->_log($err);
                   69533:             }
                   69534:         }
                   69535:         if ($die) {
                   69536:             die();
                   69537:         }
                   69538:         if ($this->_compat && $push) {
                   69539:             return $this->raiseError($msg, $code, null, null, $err);
                   69540:         }
                   69541:         return $err;
                   69542:     }
                   69543:     
                   69544:     /**
                   69545:      * Static version of {@link push()}
                   69546:      * 
                   69547:      * @param string $package   Package name this error belongs to
                   69548:      * @param int    $code      Package-specific error code
                   69549:      * @param string $level     Error level.  This is NOT spell-checked
                   69550:      * @param array  $params    associative array of error parameters
                   69551:      * @param string $msg       Error message, or a portion of it if the message
                   69552:      *                          is to be generated
                   69553:      * @param array  $repackage If this error re-packages an error pushed by
                   69554:      *                          another package, place the array returned from
                   69555:      *                          {@link pop()} in this parameter
                   69556:      * @param array  $backtrace Protected parameter: use this to pass in the
                   69557:      *                          {@link debug_backtrace()} that should be used
                   69558:      *                          to find error context
                   69559:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   69560:      *                          thrown.  see docs for {@link push()}
                   69561:      * @static
                   69562:      */
                   69563:     function staticPush($package, $code, $level = 'error', $params = array(),
                   69564:                         $msg = false, $repackage = false, $backtrace = false)
                   69565:     {
                   69566:         $s = &PEAR_ErrorStack::singleton($package);
                   69567:         if ($s->_contextCallback) {
                   69568:             if (!$backtrace) {
                   69569:                 if (function_exists('debug_backtrace')) {
                   69570:                     $backtrace = debug_backtrace();
                   69571:                 }
                   69572:             }
                   69573:         }
                   69574:         return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
                   69575:     }
                   69576:     
                   69577:     /**
                   69578:      * Log an error using PEAR::Log
                   69579:      * @param array $err Error array
                   69580:      * @param array $levels Error level => Log constant map
                   69581:      * @access protected
                   69582:      */
                   69583:     function _log($err)
                   69584:     {
                   69585:         if ($this->_logger) {
                   69586:             $logger = &$this->_logger;
                   69587:         } else {
                   69588:             $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
                   69589:         }
                   69590:         if (is_a($logger, 'Log')) {
                   69591:             $levels = array(
                   69592:                 'exception' => PEAR_LOG_CRIT,
                   69593:                 'alert' => PEAR_LOG_ALERT,
                   69594:                 'critical' => PEAR_LOG_CRIT,
                   69595:                 'error' => PEAR_LOG_ERR,
                   69596:                 'warning' => PEAR_LOG_WARNING,
                   69597:                 'notice' => PEAR_LOG_NOTICE,
                   69598:                 'info' => PEAR_LOG_INFO,
                   69599:                 'debug' => PEAR_LOG_DEBUG);
                   69600:             if (isset($levels[$err['level']])) {
                   69601:                 $level = $levels[$err['level']];
                   69602:             } else {
                   69603:                 $level = PEAR_LOG_INFO;
                   69604:             }
                   69605:             $logger->log($err['message'], $level, $err);
                   69606:         } else { // support non-standard logs
                   69607:             call_user_func($logger, $err);
                   69608:         }
                   69609:     }
                   69610: 
                   69611:     
                   69612:     /**
                   69613:      * Pop an error off of the error stack
                   69614:      * 
                   69615:      * @return false|array
                   69616:      * @since 0.4alpha it is no longer possible to specify a specific error
                   69617:      * level to return - the last error pushed will be returned, instead
                   69618:      */
                   69619:     function pop()
                   69620:     {
                   69621:         $err = @array_shift($this->_errors);
                   69622:         if (!is_null($err)) {
                   69623:             @array_pop($this->_errorsByLevel[$err['level']]);
                   69624:             if (!count($this->_errorsByLevel[$err['level']])) {
                   69625:                 unset($this->_errorsByLevel[$err['level']]);
                   69626:             }
                   69627:         }
                   69628:         return $err;
                   69629:     }
                   69630: 
                   69631:     /**
                   69632:      * Pop an error off of the error stack, static method
                   69633:      *
                   69634:      * @param string package name
                   69635:      * @return boolean
                   69636:      * @since PEAR1.5.0a1
                   69637:      */
                   69638:     function staticPop($package)
                   69639:     {
                   69640:         if ($package) {
                   69641:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   69642:                 return false;
                   69643:             }
                   69644:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
                   69645:         }
                   69646:     }
                   69647: 
                   69648:     /**
                   69649:      * Determine whether there are any errors on the stack
                   69650:      * @param string|array Level name.  Use to determine if any errors
                   69651:      * of level (string), or levels (array) have been pushed
                   69652:      * @return boolean
                   69653:      */
                   69654:     function hasErrors($level = false)
                   69655:     {
                   69656:         if ($level) {
                   69657:             return isset($this->_errorsByLevel[$level]);
                   69658:         }
                   69659:         return count($this->_errors);
                   69660:     }
                   69661:     
                   69662:     /**
                   69663:      * Retrieve all errors since last purge
                   69664:      * 
                   69665:      * @param boolean set in order to empty the error stack
                   69666:      * @param string level name, to return only errors of a particular severity
                   69667:      * @return array
                   69668:      */
                   69669:     function getErrors($purge = false, $level = false)
                   69670:     {
                   69671:         if (!$purge) {
                   69672:             if ($level) {
                   69673:                 if (!isset($this->_errorsByLevel[$level])) {
                   69674:                     return array();
                   69675:                 } else {
                   69676:                     return $this->_errorsByLevel[$level];
                   69677:                 }
                   69678:             } else {
                   69679:                 return $this->_errors;
                   69680:             }
                   69681:         }
                   69682:         if ($level) {
                   69683:             $ret = $this->_errorsByLevel[$level];
                   69684:             foreach ($this->_errorsByLevel[$level] as $i => $unused) {
                   69685:                 // entries are references to the $_errors array
                   69686:                 $this->_errorsByLevel[$level][$i] = false;
                   69687:             }
                   69688:             // array_filter removes all entries === false
                   69689:             $this->_errors = array_filter($this->_errors);
                   69690:             unset($this->_errorsByLevel[$level]);
                   69691:             return $ret;
                   69692:         }
                   69693:         $ret = $this->_errors;
                   69694:         $this->_errors = array();
                   69695:         $this->_errorsByLevel = array();
                   69696:         return $ret;
                   69697:     }
                   69698:     
                   69699:     /**
                   69700:      * Determine whether there are any errors on a single error stack, or on any error stack
                   69701:      *
                   69702:      * The optional parameter can be used to test the existence of any errors without the need of
                   69703:      * singleton instantiation
                   69704:      * @param string|false Package name to check for errors
                   69705:      * @param string Level name to check for a particular severity
                   69706:      * @return boolean
                   69707:      * @static
                   69708:      */
                   69709:     function staticHasErrors($package = false, $level = false)
                   69710:     {
                   69711:         if ($package) {
                   69712:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   69713:                 return false;
                   69714:             }
                   69715:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
                   69716:         }
                   69717:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   69718:             if ($obj->hasErrors($level)) {
                   69719:                 return true;
                   69720:             }
                   69721:         }
                   69722:         return false;
                   69723:     }
                   69724:     
                   69725:     /**
                   69726:      * Get a list of all errors since last purge, organized by package
                   69727:      * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
                   69728:      * @param boolean $purge Set to purge the error stack of existing errors
                   69729:      * @param string  $level Set to a level name in order to retrieve only errors of a particular level
                   69730:      * @param boolean $merge Set to return a flat array, not organized by package
                   69731:      * @param array   $sortfunc Function used to sort a merged array - default
                   69732:      *        sorts by time, and should be good for most cases
                   69733:      * @static
                   69734:      * @return array 
                   69735:      */
                   69736:     function staticGetErrors($purge = false, $level = false, $merge = false,
                   69737:                              $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
                   69738:     {
                   69739:         $ret = array();
                   69740:         if (!is_callable($sortfunc)) {
                   69741:             $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
                   69742:         }
                   69743:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   69744:             $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
                   69745:             if ($test) {
                   69746:                 if ($merge) {
                   69747:                     $ret = array_merge($ret, $test);
                   69748:                 } else {
                   69749:                     $ret[$package] = $test;
                   69750:                 }
                   69751:             }
                   69752:         }
                   69753:         if ($merge) {
                   69754:             usort($ret, $sortfunc);
                   69755:         }
                   69756:         return $ret;
                   69757:     }
                   69758:     
                   69759:     /**
                   69760:      * Error sorting function, sorts by time
                   69761:      * @access private
                   69762:      */
                   69763:     function _sortErrors($a, $b)
                   69764:     {
                   69765:         if ($a['time'] == $b['time']) {
                   69766:             return 0;
                   69767:         }
                   69768:         if ($a['time'] < $b['time']) {
                   69769:             return 1;
                   69770:         }
                   69771:         return -1;
                   69772:     }
                   69773: 
                   69774:     /**
                   69775:      * Standard file/line number/function/class context callback
                   69776:      *
                   69777:      * This function uses a backtrace generated from {@link debug_backtrace()}
                   69778:      * and so will not work at all in PHP < 4.3.0.  The frame should
                   69779:      * reference the frame that contains the source of the error.
                   69780:      * @return array|false either array('file' => file, 'line' => line,
                   69781:      *         'function' => function name, 'class' => class name) or
                   69782:      *         if this doesn't work, then false
                   69783:      * @param unused
                   69784:      * @param integer backtrace frame.
                   69785:      * @param array Results of debug_backtrace()
                   69786:      * @static
                   69787:      */
                   69788:     function getFileLine($code, $params, $backtrace = null)
                   69789:     {
                   69790:         if ($backtrace === null) {
                   69791:             return false;
                   69792:         }
                   69793:         $frame = 0;
                   69794:         $functionframe = 1;
                   69795:         if (!isset($backtrace[1])) {
                   69796:             $functionframe = 0;
                   69797:         } else {
                   69798:             while (isset($backtrace[$functionframe]['function']) &&
                   69799:                   $backtrace[$functionframe]['function'] == 'eval' &&
                   69800:                   isset($backtrace[$functionframe + 1])) {
                   69801:                 $functionframe++;
                   69802:             }
                   69803:         }
                   69804:         if (isset($backtrace[$frame])) {
                   69805:             if (!isset($backtrace[$frame]['file'])) {
                   69806:                 $frame++;
                   69807:             }
                   69808:             $funcbacktrace = $backtrace[$functionframe];
                   69809:             $filebacktrace = $backtrace[$frame];
                   69810:             $ret = array('file' => $filebacktrace['file'],
                   69811:                          'line' => $filebacktrace['line']);
                   69812:             // rearrange for eval'd code or create function errors
                   69813:             if (strpos($filebacktrace['file'], '(') && 
                   69814:                  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
                   69815:                   $matches)) {
                   69816:                 $ret['file'] = $matches[1];
                   69817:                 $ret['line'] = $matches[2] + 0;
                   69818:             }
                   69819:             if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
                   69820:                 if ($funcbacktrace['function'] != 'eval') {
                   69821:                     if ($funcbacktrace['function'] == '__lambda_func') {
                   69822:                         $ret['function'] = 'create_function() code';
                   69823:                     } else {
                   69824:                         $ret['function'] = $funcbacktrace['function'];
                   69825:                     }
                   69826:                 }
                   69827:             }
                   69828:             if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
                   69829:                 $ret['class'] = $funcbacktrace['class'];
                   69830:             }
                   69831:             return $ret;
                   69832:         }
                   69833:         return false;
                   69834:     }
                   69835:     
                   69836:     /**
                   69837:      * Standard error message generation callback
                   69838:      * 
                   69839:      * This method may also be called by a custom error message generator
                   69840:      * to fill in template values from the params array, simply
                   69841:      * set the third parameter to the error message template string to use
                   69842:      * 
                   69843:      * The special variable %__msg% is reserved: use it only to specify
                   69844:      * where a message passed in by the user should be placed in the template,
                   69845:      * like so:
                   69846:      * 
                   69847:      * Error message: %msg% - internal error
                   69848:      * 
                   69849:      * If the message passed like so:
                   69850:      * 
                   69851:      * <code>
                   69852:      * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
                   69853:      * </code>
                   69854:      * 
                   69855:      * The returned error message will be "Error message: server error 500 -
                   69856:      * internal error"
                   69857:      * @param PEAR_ErrorStack
                   69858:      * @param array
                   69859:      * @param string|false Pre-generated error message template
                   69860:      * @static
                   69861:      * @return string
                   69862:      */
                   69863:     function getErrorMessage(&$stack, $err, $template = false)
                   69864:     {
                   69865:         if ($template) {
                   69866:             $mainmsg = $template;
                   69867:         } else {
                   69868:             $mainmsg = $stack->getErrorMessageTemplate($err['code']);
                   69869:         }
                   69870:         $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
                   69871:         if (is_array($err['params']) && count($err['params'])) {
                   69872:             foreach ($err['params'] as $name => $val) {
                   69873:                 if (is_array($val)) {
                   69874:                     // @ is needed in case $val is a multi-dimensional array
                   69875:                     $val = @implode(', ', $val);
                   69876:                 }
                   69877:                 if (is_object($val)) {
                   69878:                     if (method_exists($val, '__toString')) {
                   69879:                         $val = $val->__toString();
                   69880:                     } else {
                   69881:                         PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
                   69882:                             'warning', array('obj' => get_class($val)),
                   69883:                             'object %obj% passed into getErrorMessage, but has no __toString() method');
                   69884:                         $val = 'Object';
                   69885:                     }
                   69886:                 }
                   69887:                 $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
                   69888:             }
                   69889:         }
                   69890:         return $mainmsg;
                   69891:     }
                   69892:     
                   69893:     /**
                   69894:      * Standard Error Message Template generator from code
                   69895:      * @return string
                   69896:      */
                   69897:     function getErrorMessageTemplate($code)
                   69898:     {
                   69899:         if (!isset($this->_errorMsgs[$code])) {
                   69900:             return '%__msg%';
                   69901:         }
                   69902:         return $this->_errorMsgs[$code];
                   69903:     }
                   69904:     
                   69905:     /**
                   69906:      * Set the Error Message Template array
                   69907:      * 
                   69908:      * The array format must be:
                   69909:      * <pre>
                   69910:      * array(error code => 'message template',...)
                   69911:      * </pre>
                   69912:      * 
                   69913:      * Error message parameters passed into {@link push()} will be used as input
                   69914:      * for the error message.  If the template is 'message %foo% was %bar%', and the
                   69915:      * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
                   69916:      * be 'message one was six'
                   69917:      * @return string
                   69918:      */
                   69919:     function setErrorMessageTemplate($template)
                   69920:     {
                   69921:         $this->_errorMsgs = $template;
                   69922:     }
                   69923:     
                   69924:     
                   69925:     /**
                   69926:      * emulate PEAR::raiseError()
                   69927:      * 
                   69928:      * @return PEAR_Error
                   69929:      */
                   69930:     function raiseError()
                   69931:     {
                   69932:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   69933:         $args = func_get_args();
                   69934:         return call_user_func_array(array('PEAR', 'raiseError'), $args);
                   69935:     }
                   69936: }
                   69937: $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
                   69938: $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
                   69939: ?>
                   69940: <?php
                   69941: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   69942: /**
                   69943:  * PEAR_Exception
                   69944:  *
                   69945:  * PHP versions 4 and 5
                   69946:  *
                   69947:  * @category   pear
                   69948:  * @package    PEAR_Exception
                   69949:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   69950:  * @author     Hans Lellelid <hans@velum.net>
                   69951:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   69952:  * @author     Greg Beaver <cellog@php.net>
                   69953:  * @copyright  1997-2009 The Authors
                   69954:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   69955:  * @version    CVS: $Id: Exception.php 309057 2011-03-09 23:34:29Z dufuz $
                   69956:  * @link       http://pear.php.net/package/PEAR_Exception
                   69957:  * @since      File available since Release 1.0.0
                   69958:  */
                   69959: 
                   69960: 
                   69961: /**
                   69962:  * Base PEAR_Exception Class
                   69963:  *
                   69964:  * 1) Features:
                   69965:  *
                   69966:  * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
                   69967:  * - Definable triggers, shot when exceptions occur
                   69968:  * - Pretty and informative error messages
                   69969:  * - Added more context info available (like class, method or cause)
                   69970:  * - cause can be a PEAR_Exception or an array of mixed
                   69971:  *   PEAR_Exceptions/PEAR_ErrorStack warnings
                   69972:  * - callbacks for specific exception classes and their children
                   69973:  *
                   69974:  * 2) Ideas:
                   69975:  *
                   69976:  * - Maybe a way to define a 'template' for the output
                   69977:  *
                   69978:  * 3) Inherited properties from PHP Exception Class:
                   69979:  *
                   69980:  * protected $message
                   69981:  * protected $code
                   69982:  * protected $line
                   69983:  * protected $file
                   69984:  * private   $trace
                   69985:  *
                   69986:  * 4) Inherited methods from PHP Exception Class:
                   69987:  *
                   69988:  * __clone
                   69989:  * __construct
                   69990:  * getMessage
                   69991:  * getCode
                   69992:  * getFile
                   69993:  * getLine
                   69994:  * getTraceSafe
                   69995:  * getTraceSafeAsString
                   69996:  * __toString
                   69997:  *
                   69998:  * 5) Usage example
                   69999:  *
                   70000:  * <code>
                   70001:  *  require_once 'PEAR/Exception.php';
                   70002:  *
                   70003:  *  class Test {
                   70004:  *     function foo() {
                   70005:  *         throw new PEAR_Exception('Error Message', ERROR_CODE);
                   70006:  *     }
                   70007:  *  }
                   70008:  *
                   70009:  *  function myLogger($pear_exception) {
                   70010:  *     echo $pear_exception->getMessage();
                   70011:  *  }
                   70012:  *  // each time a exception is thrown the 'myLogger' will be called
                   70013:  *  // (its use is completely optional)
                   70014:  *  PEAR_Exception::addObserver('myLogger');
                   70015:  *  $test = new Test;
                   70016:  *  try {
                   70017:  *     $test->foo();
                   70018:  *  } catch (PEAR_Exception $e) {
                   70019:  *     print $e;
                   70020:  *  }
                   70021:  * </code>
                   70022:  *
                   70023:  * @category   pear
                   70024:  * @package    PEAR_Exception
                   70025:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   70026:  * @author     Hans Lellelid <hans@velum.net>
                   70027:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   70028:  * @author     Greg Beaver <cellog@php.net>
                   70029:  * @copyright  1997-2009 The Authors
                   70030:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   70031:  * @version    Release: 1.10.0beta1
                   70032:  * @link       http://pear.php.net/package/PEAR_Exception
                   70033:  * @since      Class available since Release 1.0.0
                   70034:  *
                   70035:  */
                   70036: class PEAR_Exception extends Exception
                   70037: {
                   70038:     const OBSERVER_PRINT = -2;
                   70039:     const OBSERVER_TRIGGER = -4;
                   70040:     const OBSERVER_DIE = -8;
                   70041:     protected $cause;
                   70042:     private static $_observers = array();
                   70043:     private static $_uniqueid = 0;
                   70044:     private $_trace;
                   70045: 
                   70046:     /**
                   70047:      * Supported signatures:
                   70048:      *  - PEAR_Exception(string $message);
                   70049:      *  - PEAR_Exception(string $message, int $code);
                   70050:      *  - PEAR_Exception(string $message, Exception $cause);
                   70051:      *  - PEAR_Exception(string $message, Exception $cause, int $code);
                   70052:      *  - PEAR_Exception(string $message, PEAR_Error $cause);
                   70053:      *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
                   70054:      *  - PEAR_Exception(string $message, array $causes);
                   70055:      *  - PEAR_Exception(string $message, array $causes, int $code);
                   70056:      * @param string exception message
                   70057:      * @param int|Exception|PEAR_Error|array|null exception cause
                   70058:      * @param int|null exception code or null
                   70059:      */
                   70060:     public function __construct($message, $p2 = null, $p3 = null)
                   70061:     {
                   70062:         if (is_int($p2)) {
                   70063:             $code = $p2;
                   70064:             $this->cause = null;
                   70065:         } elseif (is_object($p2) || is_array($p2)) {
                   70066:             // using is_object allows both Exception and PEAR_Error
                   70067:             if (is_object($p2) && !($p2 instanceof Exception)) {
                   70068:                 if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
                   70069:                     throw new PEAR_Exception('exception cause must be Exception, ' .
                   70070:                         'array, or PEAR_Error');
                   70071:                 }
                   70072:             }
                   70073:             $code = $p3;
                   70074:             if (is_array($p2) && isset($p2['message'])) {
                   70075:                 // fix potential problem of passing in a single warning
                   70076:                 $p2 = array($p2);
                   70077:             }
                   70078:             $this->cause = $p2;
                   70079:         } else {
                   70080:             $code = null;
                   70081:             $this->cause = null;
                   70082:         }
                   70083:         parent::__construct($message, $code);
                   70084:         $this->signal();
                   70085:     }
                   70086: 
                   70087:     /**
                   70088:      * @param mixed $callback  - A valid php callback, see php func is_callable()
                   70089:      *                         - A PEAR_Exception::OBSERVER_* constant
                   70090:      *                         - An array(const PEAR_Exception::OBSERVER_*,
                   70091:      *                           mixed $options)
                   70092:      * @param string $label    The name of the observer. Use this if you want
                   70093:      *                         to remove it later with removeObserver()
                   70094:      */
                   70095:     public static function addObserver($callback, $label = 'default')
                   70096:     {
                   70097:         self::$_observers[$label] = $callback;
                   70098:     }
                   70099: 
                   70100:     public static function removeObserver($label = 'default')
                   70101:     {
                   70102:         unset(self::$_observers[$label]);
                   70103:     }
                   70104: 
                   70105:     /**
                   70106:      * @return int unique identifier for an observer
                   70107:      */
                   70108:     public static function getUniqueId()
                   70109:     {
                   70110:         return self::$_uniqueid++;
                   70111:     }
                   70112: 
                   70113:     private function signal()
                   70114:     {
                   70115:         foreach (self::$_observers as $func) {
                   70116:             if (is_callable($func)) {
                   70117:                 call_user_func($func, $this);
                   70118:                 continue;
                   70119:             }
                   70120:             settype($func, 'array');
                   70121:             switch ($func[0]) {
                   70122:                 case self::OBSERVER_PRINT :
                   70123:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   70124:                     printf($f, $this->getMessage());
                   70125:                     break;
                   70126:                 case self::OBSERVER_TRIGGER :
                   70127:                     $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
                   70128:                     trigger_error($this->getMessage(), $f);
                   70129:                     break;
                   70130:                 case self::OBSERVER_DIE :
                   70131:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   70132:                     die(printf($f, $this->getMessage()));
                   70133:                     break;
                   70134:                 default:
                   70135:                     trigger_error('invalid observer type', E_USER_WARNING);
                   70136:             }
                   70137:         }
                   70138:     }
                   70139: 
                   70140:     /**
                   70141:      * Return specific error information that can be used for more detailed
                   70142:      * error messages or translation.
                   70143:      *
                   70144:      * This method may be overridden in child exception classes in order
                   70145:      * to add functionality not present in PEAR_Exception and is a placeholder
                   70146:      * to define API
                   70147:      *
                   70148:      * The returned array must be an associative array of parameter => value like so:
                   70149:      * <pre>
                   70150:      * array('name' => $name, 'context' => array(...))
                   70151:      * </pre>
                   70152:      * @return array
                   70153:      */
                   70154:     public function getErrorData()
                   70155:     {
                   70156:         return array();
                   70157:     }
                   70158: 
                   70159:     /**
                   70160:      * Returns the exception that caused this exception to be thrown
                   70161:      * @access public
                   70162:      * @return Exception|array The context of the exception
                   70163:      */
                   70164:     public function getCause()
                   70165:     {
                   70166:         return $this->cause;
                   70167:     }
                   70168: 
                   70169:     /**
                   70170:      * Function must be public to call on caused exceptions
                   70171:      * @param array
                   70172:      */
                   70173:     public function getCauseMessage(&$causes)
                   70174:     {
                   70175:         $trace = $this->getTraceSafe();
                   70176:         $cause = array('class'   => get_class($this),
                   70177:                        'message' => $this->message,
                   70178:                        'file' => 'unknown',
                   70179:                        'line' => 'unknown');
                   70180:         if (isset($trace[0])) {
                   70181:             if (isset($trace[0]['file'])) {
                   70182:                 $cause['file'] = $trace[0]['file'];
                   70183:                 $cause['line'] = $trace[0]['line'];
                   70184:             }
                   70185:         }
                   70186:         $causes[] = $cause;
                   70187:         if ($this->cause instanceof PEAR_Exception) {
                   70188:             $this->cause->getCauseMessage($causes);
                   70189:         } elseif ($this->cause instanceof Exception) {
                   70190:             $causes[] = array('class'   => get_class($this->cause),
                   70191:                               'message' => $this->cause->getMessage(),
                   70192:                               'file' => $this->cause->getFile(),
                   70193:                               'line' => $this->cause->getLine());
                   70194:         } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
                   70195:             $causes[] = array('class' => get_class($this->cause),
                   70196:                               'message' => $this->cause->getMessage(),
                   70197:                               'file' => 'unknown',
                   70198:                               'line' => 'unknown');
                   70199:         } elseif (is_array($this->cause)) {
                   70200:             foreach ($this->cause as $cause) {
                   70201:                 if ($cause instanceof PEAR_Exception) {
                   70202:                     $cause->getCauseMessage($causes);
                   70203:                 } elseif ($cause instanceof Exception) {
                   70204:                     $causes[] = array('class'   => get_class($cause),
                   70205:                                    'message' => $cause->getMessage(),
                   70206:                                    'file' => $cause->getFile(),
                   70207:                                    'line' => $cause->getLine());
                   70208:                 } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
                   70209:                     $causes[] = array('class' => get_class($cause),
                   70210:                                       'message' => $cause->getMessage(),
                   70211:                                       'file' => 'unknown',
                   70212:                                       'line' => 'unknown');
                   70213:                 } elseif (is_array($cause) && isset($cause['message'])) {
                   70214:                     // PEAR_ErrorStack warning
                   70215:                     $causes[] = array(
                   70216:                         'class' => $cause['package'],
                   70217:                         'message' => $cause['message'],
                   70218:                         'file' => isset($cause['context']['file']) ?
                   70219:                                             $cause['context']['file'] :
                   70220:                                             'unknown',
                   70221:                         'line' => isset($cause['context']['line']) ?
                   70222:                                             $cause['context']['line'] :
                   70223:                                             'unknown',
                   70224:                     );
                   70225:                 }
                   70226:             }
                   70227:         }
                   70228:     }
                   70229: 
                   70230:     public function getTraceSafe()
                   70231:     {
                   70232:         if (!isset($this->_trace)) {
                   70233:             $this->_trace = $this->getTrace();
                   70234:             if (empty($this->_trace)) {
                   70235:                 $backtrace = debug_backtrace();
                   70236:                 $this->_trace = array($backtrace[count($backtrace)-1]);
                   70237:             }
                   70238:         }
                   70239:         return $this->_trace;
                   70240:     }
                   70241: 
                   70242:     public function getErrorClass()
                   70243:     {
                   70244:         $trace = $this->getTraceSafe();
                   70245:         return $trace[0]['class'];
                   70246:     }
                   70247: 
                   70248:     public function getErrorMethod()
                   70249:     {
                   70250:         $trace = $this->getTraceSafe();
                   70251:         return $trace[0]['function'];
                   70252:     }
                   70253: 
                   70254:     public function __toString()
                   70255:     {
                   70256:         if (isset($_SERVER['REQUEST_URI'])) {
                   70257:             return $this->toHtml();
                   70258:         }
                   70259:         return $this->toText();
                   70260:     }
                   70261: 
                   70262:     public function toHtml()
                   70263:     {
                   70264:         $trace = $this->getTraceSafe();
                   70265:         $causes = array();
                   70266:         $this->getCauseMessage($causes);
                   70267:         $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
                   70268:         foreach ($causes as $i => $cause) {
                   70269:             $html .= '<tr><td colspan="3" style="background: #ff9999">'
                   70270:                . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
                   70271:                . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
                   70272:                . 'on line <b>' . $cause['line'] . '</b>'
                   70273:                . "</td></tr>\n";
                   70274:         }
                   70275:         $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
                   70276:                . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
                   70277:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
                   70278:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
                   70279: 
                   70280:         foreach ($trace as $k => $v) {
                   70281:             $html .= '<tr><td style="text-align: center;">' . $k . '</td>'
                   70282:                    . '<td>';
                   70283:             if (!empty($v['class'])) {
                   70284:                 $html .= $v['class'] . $v['type'];
                   70285:             }
                   70286:             $html .= $v['function'];
                   70287:             $args = array();
                   70288:             if (!empty($v['args'])) {
                   70289:                 foreach ($v['args'] as $arg) {
                   70290:                     if (is_null($arg)) $args[] = 'null';
                   70291:                     elseif (is_array($arg)) $args[] = 'Array';
                   70292:                     elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
                   70293:                     elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
                   70294:                     elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
                   70295:                     else {
                   70296:                         $arg = (string)$arg;
                   70297:                         $str = htmlspecialchars(substr($arg, 0, 16));
                   70298:                         if (strlen($arg) > 16) $str .= '&hellip;';
                   70299:                         $args[] = "'" . $str . "'";
                   70300:                     }
                   70301:                 }
                   70302:             }
                   70303:             $html .= '(' . implode(', ',$args) . ')'
                   70304:                    . '</td>'
                   70305:                    . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
                   70306:                    . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
                   70307:                    . '</td></tr>' . "\n";
                   70308:         }
                   70309:         $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
                   70310:                . '<td>{main}</td>'
                   70311:                . '<td>&nbsp;</td></tr>' . "\n"
                   70312:                . '</table>';
                   70313:         return $html;
                   70314:     }
                   70315: 
                   70316:     public function toText()
                   70317:     {
                   70318:         $causes = array();
                   70319:         $this->getCauseMessage($causes);
                   70320:         $causeMsg = '';
                   70321:         foreach ($causes as $i => $cause) {
                   70322:             $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
                   70323:                    . $cause['message'] . ' in ' . $cause['file']
                   70324:                    . ' on line ' . $cause['line'] . "\n";
                   70325:         }
                   70326:         return $causeMsg . $this->getTraceAsString();
                   70327:     }
                   70328: }<?php
                   70329: /**
                   70330:  * PEAR_Frontend, the singleton-based frontend for user input/output
                   70331:  *
                   70332:  * PHP versions 4 and 5
                   70333:  *
                   70334:  * @category   pear
                   70335:  * @package    PEAR
                   70336:  * @author     Greg Beaver <cellog@php.net>
                   70337:  * @copyright  1997-2009 The Authors
                   70338:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   70339:  * @version    CVS: $Id: Frontend.php 276383 2009-02-24 23:39:37Z dufuz $
                   70340:  * @link       http://pear.php.net/package/PEAR
                   70341:  * @since      File available since Release 1.4.0a1
                   70342:  */
                   70343: 
                   70344: /**
                   70345:  * Include error handling
                   70346:  */
                   70347: //require_once 'PEAR.php';
                   70348: 
                   70349: /**
                   70350:  * Which user interface class is being used.
                   70351:  * @var string class name
                   70352:  */
                   70353: $GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
                   70354: 
                   70355: /**
                   70356:  * Instance of $_PEAR_Command_uiclass.
                   70357:  * @var object
                   70358:  */
                   70359: $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
                   70360: 
                   70361: /**
                   70362:  * Singleton-based frontend for PEAR user input/output
                   70363:  *
                   70364:  * @category   pear
                   70365:  * @package    PEAR
                   70366:  * @author     Greg Beaver <cellog@php.net>
                   70367:  * @copyright  1997-2009 The Authors
                   70368:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   70369:  * @version    Release: 1.10.0beta1
                   70370:  * @link       http://pear.php.net/package/PEAR
                   70371:  * @since      Class available since Release 1.4.0a1
                   70372:  */
                   70373: class PEAR_Frontend extends PEAR
                   70374: {
                   70375:     /**
                   70376:      * Retrieve the frontend object
                   70377:      * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
                   70378:      * @static
                   70379:      */
                   70380:     function &singleton($type = null)
                   70381:     {
                   70382:         if ($type === null) {
                   70383:             if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
                   70384:                 $a = false;
                   70385:                 return $a;
                   70386:             }
                   70387:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   70388:         }
                   70389: 
                   70390:         $a = PEAR_Frontend::setFrontendClass($type);
                   70391:         return $a;
                   70392:     }
                   70393: 
                   70394:     /**
                   70395:      * Set the frontend class that will be used by calls to {@link singleton()}
                   70396:      *
                   70397:      * Frontends are expected to conform to the PEAR naming standard of
                   70398:      * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
                   70399:      * @param string $uiclass full class name
                   70400:      * @return PEAR_Frontend
                   70401:      * @static
                   70402:      */
                   70403:     function &setFrontendClass($uiclass)
                   70404:     {
                   70405:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   70406:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
                   70407:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   70408:         }
                   70409: 
                   70410:         if (!class_exists($uiclass)) {
                   70411:             $file = 'phar://install-pear-nozlib.phar/' . str_replace('_', '/', $uiclass) . '.php';
                   70412:             if (PEAR_Frontend::isIncludeable($file)) {
                   70413:                 include_once $file;
                   70414:             }
                   70415:         }
                   70416: 
                   70417:         if (class_exists($uiclass)) {
                   70418:             $obj = &new $uiclass;
                   70419:             // quick test to see if this class implements a few of the most
                   70420:             // important frontend methods
                   70421:             if (is_a($obj, 'PEAR_Frontend')) {
                   70422:                 $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
                   70423:                 $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
                   70424:                 return $obj;
                   70425:             }
                   70426: 
                   70427:             $err = PEAR::raiseError("not a frontend class: $uiclass");
                   70428:             return $err;
                   70429:         }
                   70430: 
                   70431:         $err = PEAR::raiseError("no such class: $uiclass");
                   70432:         return $err;
                   70433:     }
                   70434: 
                   70435:     /**
                   70436:      * Set the frontend class that will be used by calls to {@link singleton()}
                   70437:      *
                   70438:      * Frontends are expected to be a descendant of PEAR_Frontend
                   70439:      * @param PEAR_Frontend
                   70440:      * @return PEAR_Frontend
                   70441:      * @static
                   70442:      */
                   70443:     function &setFrontendObject($uiobject)
                   70444:     {
                   70445:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   70446:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
                   70447:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   70448:         }
                   70449: 
                   70450:         if (!is_a($uiobject, 'PEAR_Frontend')) {
                   70451:             $err = PEAR::raiseError('not a valid frontend class: (' .
                   70452:                 get_class($uiobject) . ')');
                   70453:             return $err;
                   70454:         }
                   70455: 
                   70456:         $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
                   70457:         $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
                   70458:         return $uiobject;
                   70459:     }
                   70460: 
                   70461:     /**
                   70462:      * @param string $path relative or absolute include path
                   70463:      * @return boolean
                   70464:      * @static
                   70465:      */
                   70466:     function isIncludeable($path)
                   70467:     {
                   70468:         if (file_exists($path) && is_readable($path)) {
                   70469:             return true;
                   70470:         }
                   70471: 
                   70472:         $fp = @fopen($path, 'r', true);
                   70473:         if ($fp) {
                   70474:             fclose($fp);
                   70475:             return true;
                   70476:         }
                   70477: 
                   70478:         return false;
                   70479:     }
                   70480: 
                   70481:     /**
                   70482:      * @param PEAR_Config
                   70483:      */
                   70484:     function setConfig(&$config)
                   70485:     {
                   70486:     }
                   70487: 
                   70488:     /**
                   70489:      * This can be overridden to allow session-based temporary file management
                   70490:      *
                   70491:      * By default, all files are deleted at the end of a session.  The web installer
                   70492:      * needs to be able to sustain a list over many sessions in order to support
                   70493:      * user interaction with install scripts
                   70494:      */
                   70495:     function addTempFile($file)
                   70496:     {
                   70497:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   70498:     }
                   70499: 
                   70500:     /**
                   70501:      * Log an action
                   70502:      *
                   70503:      * @param string $msg the message to log
                   70504:      * @param boolean $append_crlf
                   70505:      * @return boolean true
                   70506:      * @abstract
                   70507:      */
                   70508:     function log($msg, $append_crlf = true)
                   70509:     {
                   70510:     }
                   70511: 
                   70512:     /**
                   70513:      * Run a post-installation script
                   70514:      *
                   70515:      * @param array $scripts array of post-install scripts
                   70516:      * @abstract
                   70517:      */
                   70518:     function runPostinstallScripts(&$scripts)
                   70519:     {
                   70520:     }
                   70521: 
                   70522:     /**
                   70523:      * Display human-friendly output formatted depending on the
                   70524:      * $command parameter.
                   70525:      *
                   70526:      * This should be able to handle basic output data with no command
                   70527:      * @param mixed  $data    data structure containing the information to display
                   70528:      * @param string $command command from which this method was called
                   70529:      * @abstract
                   70530:      */
                   70531:     function outputData($data, $command = '_default')
                   70532:     {
                   70533:     }
                   70534: 
                   70535:     /**
                   70536:      * Display a modal form dialog and return the given input
                   70537:      *
                   70538:      * A frontend that requires multiple requests to retrieve and process
                   70539:      * data must take these needs into account, and implement the request
                   70540:      * handling code.
                   70541:      * @param string $command  command from which this method was called
                   70542:      * @param array  $prompts  associative array. keys are the input field names
                   70543:      *                         and values are the description
                   70544:      * @param array  $types    array of input field types (text, password,
                   70545:      *                         etc.) keys have to be the same like in $prompts
                   70546:      * @param array  $defaults array of default values. again keys have
                   70547:      *                         to be the same like in $prompts.  Do not depend
                   70548:      *                         on a default value being set.
                   70549:      * @return array input sent by the user
                   70550:      * @abstract
                   70551:      */
                   70552:     function userDialog($command, $prompts, $types = array(), $defaults = array())
                   70553:     {
                   70554:     }
                   70555: }<?php
                   70556: /**
                   70557:  * PEAR_Frontend_CLI
                   70558:  *
                   70559:  * PHP versions 4 and 5
                   70560:  *
                   70561:  * @category   pear
                   70562:  * @package    PEAR
                   70563:  * @author     Stig Bakken <ssb@php.net>
                   70564:  * @author     Greg Beaver <cellog@php.net>
                   70565:  * @copyright  1997-2009 The Authors
                   70566:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   70567:  * @version    CVS: $Id: CLI.php 305390 2010-11-15 23:46:43Z dufuz $
                   70568:  * @link       http://pear.php.net/package/PEAR
                   70569:  * @since      File available since Release 0.1
                   70570:  */
                   70571: /**
                   70572:  * base class
                   70573:  */
                   70574: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
                   70575: 
                   70576: /**
                   70577:  * Command-line Frontend for the PEAR Installer
                   70578:  * @category   pear
                   70579:  * @package    PEAR
                   70580:  * @author     Stig Bakken <ssb@php.net>
                   70581:  * @author     Greg Beaver <cellog@php.net>
                   70582:  * @copyright  1997-2009 The Authors
                   70583:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   70584:  * @version    Release: 1.10.0beta1
                   70585:  * @link       http://pear.php.net/package/PEAR
                   70586:  * @since      Class available since Release 0.1
                   70587:  */
                   70588: class PEAR_Frontend_CLI extends PEAR_Frontend
                   70589: {
                   70590:     /**
                   70591:      * What type of user interface this frontend is for.
                   70592:      * @var string
                   70593:      * @access public
                   70594:      */
                   70595:     var $type = 'CLI';
                   70596:     var $lp = ''; // line prefix
                   70597: 
                   70598:     var $params = array();
                   70599:     var $term = array(
                   70600:         'bold'   => '',
                   70601:         'normal' => '',
                   70602:     );
                   70603: 
                   70604:     function PEAR_Frontend_CLI()
                   70605:     {
                   70606:         parent::PEAR();
                   70607:         $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
                   70608:         if (function_exists('posix_isatty') && !posix_isatty(1)) {
                   70609:             // output is being redirected to a file or through a pipe
                   70610:         } elseif ($term) {
                   70611:             if (preg_match('/^(xterm|vt220|linux)/', $term)) {
                   70612:                 $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
                   70613:                 $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
                   70614:             } elseif (preg_match('/^vt100/', $term)) {
                   70615:                 $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
                   70616:                 $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
                   70617:             }
                   70618:         } elseif (OS_WINDOWS) {
                   70619:             // XXX add ANSI codes here
                   70620:         }
                   70621:     }
                   70622: 
                   70623:     /**
                   70624:      * @param object PEAR_Error object
                   70625:      */
                   70626:     function displayError($e)
                   70627:     {
                   70628:         return $this->_displayLine($e->getMessage());
                   70629:     }
                   70630: 
                   70631:     /**
                   70632:      * @param object PEAR_Error object
                   70633:      */
                   70634:     function displayFatalError($eobj)
                   70635:     {
                   70636:         $this->displayError($eobj);
                   70637:         if (class_exists('PEAR_Config')) {
                   70638:             $config = &PEAR_Config::singleton();
                   70639:             if ($config->get('verbose') > 5) {
                   70640:                 if (function_exists('debug_print_backtrace')) {
                   70641:                     debug_print_backtrace();
                   70642:                     exit(1);
                   70643:                 }
                   70644: 
                   70645:                 $raised = false;
                   70646:                 foreach (debug_backtrace() as $i => $frame) {
                   70647:                     if (!$raised) {
                   70648:                         if (isset($frame['class'])
                   70649:                             && strtolower($frame['class']) == 'pear'
                   70650:                             && strtolower($frame['function']) == 'raiseerror'
                   70651:                         ) {
                   70652:                             $raised = true;
                   70653:                         } else {
                   70654:                             continue;
                   70655:                         }
                   70656:                     }
                   70657: 
                   70658:                     $frame['class']    = !isset($frame['class'])    ? '' : $frame['class'];
                   70659:                     $frame['type']     = !isset($frame['type'])     ? '' : $frame['type'];
                   70660:                     $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
                   70661:                     $frame['line']     = !isset($frame['line'])     ? '' : $frame['line'];
                   70662:                     $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
                   70663:                 }
                   70664:             }
                   70665:         }
                   70666: 
                   70667:         exit(1);
                   70668:     }
                   70669: 
                   70670:     /**
                   70671:      * Instruct the runInstallScript method to skip a paramgroup that matches the
                   70672:      * id value passed in.
                   70673:      *
                   70674:      * This method is useful for dynamically configuring which sections of a post-install script
                   70675:      * will be run based on the user's setup, which is very useful for making flexible
                   70676:      * post-install scripts without losing the cross-Frontend ability to retrieve user input
                   70677:      * @param string
                   70678:      */
                   70679:     function skipParamgroup($id)
                   70680:     {
                   70681:         $this->_skipSections[$id] = true;
                   70682:     }
                   70683: 
                   70684:     function runPostinstallScripts(&$scripts)
                   70685:     {
                   70686:         foreach ($scripts as $i => $script) {
                   70687:             $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
                   70688:         }
                   70689:     }
                   70690: 
                   70691:     /**
                   70692:      * @param array $xml contents of postinstallscript tag
                   70693:      * @param object $script post-installation script
                   70694:      * @param string install|upgrade
                   70695:      */
                   70696:     function runInstallScript($xml, &$script)
                   70697:     {
                   70698:         $this->_skipSections = array();
                   70699:         if (!is_array($xml) || !isset($xml['paramgroup'])) {
                   70700:             $script->run(array(), '_default');
                   70701:             return;
                   70702:         }
                   70703: 
                   70704:         $completedPhases = array();
                   70705:         if (!isset($xml['paramgroup'][0])) {
                   70706:             $xml['paramgroup'] = array($xml['paramgroup']);
                   70707:         }
                   70708: 
                   70709:         foreach ($xml['paramgroup'] as $group) {
                   70710:             if (isset($this->_skipSections[$group['id']])) {
                   70711:                 // the post-install script chose to skip this section dynamically
                   70712:                 continue;
                   70713:             }
                   70714: 
                   70715:             if (isset($group['name'])) {
                   70716:                 $paramname = explode('::', $group['name']);
                   70717:                 if ($lastgroup['id'] != $paramname[0]) {
                   70718:                     continue;
                   70719:                 }
                   70720: 
                   70721:                 $group['name'] = $paramname[1];
                   70722:                 if (!isset($answers)) {
                   70723:                     return;
                   70724:                 }
                   70725: 
                   70726:                 if (isset($answers[$group['name']])) {
                   70727:                     switch ($group['conditiontype']) {
                   70728:                         case '=' :
                   70729:                             if ($answers[$group['name']] != $group['value']) {
                   70730:                                 continue 2;
                   70731:                             }
                   70732:                         break;
                   70733:                         case '!=' :
                   70734:                             if ($answers[$group['name']] == $group['value']) {
                   70735:                                 continue 2;
                   70736:                             }
                   70737:                         break;
                   70738:                         case 'preg_match' :
                   70739:                             if (!@preg_match('/' . $group['value'] . '/',
                   70740:                                   $answers[$group['name']])) {
                   70741:                                 continue 2;
                   70742:                             }
                   70743:                         break;
                   70744:                         default :
                   70745:                         return;
                   70746:                     }
                   70747:                 }
                   70748:             }
                   70749: 
                   70750:             $lastgroup = $group;
                   70751:             if (isset($group['instructions'])) {
                   70752:                 $this->_display($group['instructions']);
                   70753:             }
                   70754: 
                   70755:             if (!isset($group['param'][0])) {
                   70756:                 $group['param'] = array($group['param']);
                   70757:             }
                   70758: 
                   70759:             if (isset($group['param'])) {
                   70760:                 if (method_exists($script, 'postProcessPrompts')) {
                   70761:                     $prompts = $script->postProcessPrompts($group['param'], $group['id']);
                   70762:                     if (!is_array($prompts) || count($prompts) != count($group['param'])) {
                   70763:                         $this->outputData('postinstall', 'Error: post-install script did not ' .
                   70764:                             'return proper post-processed prompts');
                   70765:                         $prompts = $group['param'];
                   70766:                     } else {
                   70767:                         foreach ($prompts as $i => $var) {
                   70768:                             if (!is_array($var) || !isset($var['prompt']) ||
                   70769:                                   !isset($var['name']) ||
                   70770:                                   ($var['name'] != $group['param'][$i]['name']) ||
                   70771:                                   ($var['type'] != $group['param'][$i]['type'])
                   70772:                             ) {
                   70773:                                 $this->outputData('postinstall', 'Error: post-install script ' .
                   70774:                                     'modified the variables or prompts, severe security risk. ' .
                   70775:                                     'Will instead use the defaults from the package.xml');
                   70776:                                 $prompts = $group['param'];
                   70777:                             }
                   70778:                         }
                   70779:                     }
                   70780: 
                   70781:                     $answers = $this->confirmDialog($prompts);
                   70782:                 } else {
                   70783:                     $answers = $this->confirmDialog($group['param']);
                   70784:                 }
                   70785:             }
                   70786: 
                   70787:             if ((isset($answers) && $answers) || !isset($group['param'])) {
                   70788:                 if (!isset($answers)) {
                   70789:                     $answers = array();
                   70790:                 }
                   70791: 
                   70792:                 array_unshift($completedPhases, $group['id']);
                   70793:                 if (!$script->run($answers, $group['id'])) {
                   70794:                     $script->run($completedPhases, '_undoOnError');
                   70795:                     return;
                   70796:                 }
                   70797:             } else {
                   70798:                 $script->run($completedPhases, '_undoOnError');
                   70799:                 return;
                   70800:             }
                   70801:         }
                   70802:     }
                   70803: 
                   70804:     /**
                   70805:      * Ask for user input, confirm the answers and continue until the user is satisfied
                   70806:      * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
                   70807:      *              'text to display', 'type' => 'string'[, default => 'default value'])
                   70808:      * @return array
                   70809:      */
                   70810:     function confirmDialog($params)
                   70811:     {
                   70812:         $answers = $prompts = $types = array();
                   70813:         foreach ($params as $param) {
                   70814:             $prompts[$param['name']] = $param['prompt'];
                   70815:             $types[$param['name']]   = $param['type'];
                   70816:             $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
                   70817:         }
                   70818: 
                   70819:         $tried = false;
                   70820:         do {
                   70821:             if ($tried) {
                   70822:                 $i = 1;
                   70823:                 foreach ($answers as $var => $value) {
                   70824:                     if (!strlen($value)) {
                   70825:                         echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
                   70826:                     }
                   70827:                     $i++;
                   70828:                 }
                   70829:             }
                   70830: 
                   70831:             $answers = $this->userDialog('', $prompts, $types, $answers);
                   70832:             $tried   = true;
                   70833:         } while (is_array($answers) && count(array_filter($answers)) != count($prompts));
                   70834: 
                   70835:         return $answers;
                   70836:     }
                   70837: 
                   70838:     function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
                   70839:     {
                   70840:         if (!is_array($prompts)) {
                   70841:             return array();
                   70842:         }
                   70843: 
                   70844:         $testprompts = array_keys($prompts);
                   70845:         $result      = $defaults;
                   70846: 
                   70847:         reset($prompts);
                   70848:         if (count($prompts) === 1) {
                   70849:             foreach ($prompts as $key => $prompt) {
                   70850:                 $type    = $types[$key];
                   70851:                 $default = @$defaults[$key];
                   70852:                 print "$prompt ";
                   70853:                 if ($default) {
                   70854:                     print "[$default] ";
                   70855:                 }
                   70856:                 print ": ";
                   70857: 
                   70858:                 $line         = fgets(STDIN, 2048);
                   70859:                 $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
                   70860:             }
                   70861: 
                   70862:             return $result;
                   70863:         }
                   70864: 
                   70865:         $first_run = true;
                   70866:         while (true) {
                   70867:             $descLength = max(array_map('strlen', $prompts));
                   70868:             $descFormat = "%-{$descLength}s";
                   70869:             $last       = count($prompts);
                   70870: 
                   70871:             $i = 0;
                   70872:             foreach ($prompts as $n => $var) {
                   70873:                 $res = isset($result[$n]) ? $result[$n] : null;
                   70874:                 printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
                   70875:             }
                   70876:             print "\n1-$last, 'all', 'abort', or Enter to continue: ";
                   70877: 
                   70878:             $tmp = trim(fgets(STDIN, 1024));
                   70879:             if (empty($tmp)) {
                   70880:                 break;
                   70881:             }
                   70882: 
                   70883:             if ($tmp == 'abort') {
                   70884:                 return false;
                   70885:             }
                   70886: 
                   70887:             if (isset($testprompts[(int)$tmp - 1])) {
                   70888:                 $var     = $testprompts[(int)$tmp - 1];
                   70889:                 $desc    = $prompts[$var];
                   70890:                 $current = @$result[$var];
                   70891:                 print "$desc [$current] : ";
                   70892:                 $tmp = trim(fgets(STDIN, 1024));
                   70893:                 if ($tmp !== '') {
                   70894:                     $result[$var] = $tmp;
                   70895:                 }
                   70896:             } elseif ($tmp == 'all') {
                   70897:                 foreach ($prompts as $var => $desc) {
                   70898:                     $current = $result[$var];
                   70899:                     print "$desc [$current] : ";
                   70900:                     $tmp = trim(fgets(STDIN, 1024));
                   70901:                     if (trim($tmp) !== '') {
                   70902:                         $result[$var] = trim($tmp);
                   70903:                     }
                   70904:                 }
                   70905:             }
                   70906: 
                   70907:             $first_run = false;
                   70908:         }
                   70909: 
                   70910:         return $result;
                   70911:     }
                   70912: 
                   70913:     function userConfirm($prompt, $default = 'yes')
                   70914:     {
                   70915:         trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
                   70916:         static $positives = array('y', 'yes', 'on', '1');
                   70917:         static $negatives = array('n', 'no', 'off', '0');
                   70918:         print "$this->lp$prompt [$default] : ";
                   70919:         $fp = fopen("php://stdin", "r");
                   70920:         $line = fgets($fp, 2048);
                   70921:         fclose($fp);
                   70922:         $answer = strtolower(trim($line));
                   70923:         if (empty($answer)) {
                   70924:             $answer = $default;
                   70925:         }
                   70926:         if (in_array($answer, $positives)) {
                   70927:             return true;
                   70928:         }
                   70929:         if (in_array($answer, $negatives)) {
                   70930:             return false;
                   70931:         }
                   70932:         if (in_array($default, $positives)) {
                   70933:             return true;
                   70934:         }
                   70935:         return false;
                   70936:     }
                   70937: 
                   70938:     function outputData($data, $command = '_default')
                   70939:     {
                   70940:         switch ($command) {
                   70941:             case 'channel-info':
                   70942:                 foreach ($data as $type => $section) {
                   70943:                     if ($type == 'main') {
                   70944:                         $section['data'] = array_values($section['data']);
                   70945:                     }
                   70946: 
                   70947:                     $this->outputData($section);
                   70948:                 }
                   70949:                 break;
                   70950:             case 'install':
                   70951:             case 'upgrade':
                   70952:             case 'upgrade-all':
                   70953:                 if (is_array($data) && isset($data['release_warnings'])) {
                   70954:                     $this->_displayLine('');
                   70955:                     $this->_startTable(array(
                   70956:                         'border' => false,
                   70957:                         'caption' => 'Release Warnings'
                   70958:                     ));
                   70959:                     $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
                   70960:                     $this->_endTable();
                   70961:                     $this->_displayLine('');
                   70962:                 }
                   70963: 
                   70964:                 $this->_displayLine(is_array($data) ? $data['data'] : $data);
                   70965:                 break;
                   70966:             case 'search':
                   70967:                 $this->_startTable($data);
                   70968:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   70969:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   70970:                 }
                   70971: 
                   70972:                 $packages = array();
                   70973:                 foreach($data['data'] as $category) {
                   70974:                     foreach($category as $name => $pkg) {
                   70975:                         $packages[$pkg[0]] = $pkg;
                   70976:                     }
                   70977:                 }
                   70978: 
                   70979:                 $p = array_keys($packages);
                   70980:                 natcasesort($p);
                   70981:                 foreach ($p as $name) {
                   70982:                     $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
                   70983:                 }
                   70984: 
                   70985:                 $this->_endTable();
                   70986:                 break;
                   70987:             case 'list-all':
                   70988:                 if (!isset($data['data'])) {
                   70989:                       $this->_displayLine('No packages in channel');
                   70990:                       break;
                   70991:                 }
                   70992: 
                   70993:                 $this->_startTable($data);
                   70994:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   70995:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   70996:                 }
                   70997: 
                   70998:                 $packages = array();
                   70999:                 foreach($data['data'] as $category) {
                   71000:                     foreach($category as $name => $pkg) {
                   71001:                         $packages[$pkg[0]] = $pkg;
                   71002:                     }
                   71003:                 }
                   71004: 
                   71005:                 $p = array_keys($packages);
                   71006:                 natcasesort($p);
                   71007:                 foreach ($p as $name) {
                   71008:                     $pkg = $packages[$name];
                   71009:                     unset($pkg[4], $pkg[5]);
                   71010:                     $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
                   71011:                 }
                   71012: 
                   71013:                 $this->_endTable();
                   71014:                 break;
                   71015:             case 'config-show':
                   71016:                 $data['border'] = false;
                   71017:                 $opts = array(
                   71018:                     0 => array('wrap' => 30),
                   71019:                     1 => array('wrap' => 20),
                   71020:                     2 => array('wrap' => 35)
                   71021:                 );
                   71022: 
                   71023:                 $this->_startTable($data);
                   71024:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   71025:                     $this->_tableRow($data['headline'], array('bold' => true), $opts);
                   71026:                 }
                   71027: 
                   71028:                 foreach ($data['data'] as $group) {
                   71029:                     foreach ($group as $value) {
                   71030:                         if ($value[2] == '') {
                   71031:                             $value[2] = "<not set>";
                   71032:                         }
                   71033: 
                   71034:                         $this->_tableRow($value, null, $opts);
                   71035:                     }
                   71036:                 }
                   71037: 
                   71038:                 $this->_endTable();
                   71039:                 break;
                   71040:             case 'remote-info':
                   71041:                 $d = $data;
                   71042:                 $data = array(
                   71043:                     'caption' => 'Package details:',
                   71044:                     'border'  => false,
                   71045:                     'data'    => array(
                   71046:                         array("Latest",      $data['stable']),
                   71047:                         array("Installed",   $data['installed']),
                   71048:                         array("Package",     $data['name']),
                   71049:                         array("License",     $data['license']),
                   71050:                         array("Category",    $data['category']),
                   71051:                         array("Summary",     $data['summary']),
                   71052:                         array("Description", $data['description']),
                   71053:                     ),
                   71054:                 );
                   71055: 
                   71056:                 if (isset($d['deprecated']) && $d['deprecated']) {
                   71057:                     $conf = &PEAR_Config::singleton();
                   71058:                     $reg = $conf->getRegistry();
                   71059:                     $name = $reg->parsedPackageNameToString($d['deprecated'], true);
                   71060:                     $data['data'][] = array('Deprecated! use', $name);
                   71061:                 }
                   71062:             default: {
                   71063:                 if (is_array($data)) {
                   71064:                     $this->_startTable($data);
                   71065:                     $count = count($data['data'][0]);
                   71066:                     if ($count == 2) {
                   71067:                         $opts = array(0 => array('wrap' => 25),
                   71068:                                       1 => array('wrap' => 48)
                   71069:                         );
                   71070:                     } elseif ($count == 3) {
                   71071:                         $opts = array(0 => array('wrap' => 30),
                   71072:                                       1 => array('wrap' => 20),
                   71073:                                       2 => array('wrap' => 35)
                   71074:                         );
                   71075:                     } else {
                   71076:                         $opts = null;
                   71077:                     }
                   71078:                     if (isset($data['headline']) && is_array($data['headline'])) {
                   71079:                         $this->_tableRow($data['headline'],
                   71080:                                          array('bold' => true),
                   71081:                                          $opts);
                   71082:                     }
                   71083: 
                   71084:                     if (is_array($data['data'])) {
                   71085:                         foreach($data['data'] as $row) {
                   71086:                             $this->_tableRow($row, null, $opts);
                   71087:                         }
                   71088:                     } else {
                   71089:                         $this->_tableRow(array($data['data']), null, $opts);
                   71090:                      }
                   71091:                     $this->_endTable();
                   71092:                 } else {
                   71093:                     $this->_displayLine($data);
                   71094:                 }
                   71095:             }
                   71096:         }
                   71097:     }
                   71098: 
                   71099:     function log($text, $append_crlf = true)
                   71100:     {
                   71101:         if ($append_crlf) {
                   71102:             return $this->_displayLine($text);
                   71103:         }
                   71104: 
                   71105:         return $this->_display($text);
                   71106:     }
                   71107: 
                   71108:     function bold($text)
                   71109:     {
                   71110:         if (empty($this->term['bold'])) {
                   71111:             return strtoupper($text);
                   71112:         }
                   71113: 
                   71114:         return $this->term['bold'] . $text . $this->term['normal'];
                   71115:     }
                   71116: 
                   71117:     function _displayHeading($title)
                   71118:     {
                   71119:         print $this->lp.$this->bold($title)."\n";
                   71120:         print $this->lp.str_repeat("=", strlen($title))."\n";
                   71121:     }
                   71122: 
                   71123:     function _startTable($params = array())
                   71124:     {
                   71125:         $params['table_data'] = array();
                   71126:         $params['widest']     = array();  // indexed by column
                   71127:         $params['highest']    = array(); // indexed by row
                   71128:         $params['ncols']      = 0;
                   71129:         $this->params         = $params;
                   71130:     }
                   71131: 
                   71132:     function _tableRow($columns, $rowparams = array(), $colparams = array())
                   71133:     {
                   71134:         $highest = 1;
                   71135:         for ($i = 0; $i < count($columns); $i++) {
                   71136:             $col = &$columns[$i];
                   71137:             if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
                   71138:                 $col = wordwrap($col, $colparams[$i]['wrap']);
                   71139:             }
                   71140: 
                   71141:             if (strpos($col, "\n") !== false) {
                   71142:                 $multiline = explode("\n", $col);
                   71143:                 $w = 0;
                   71144:                 foreach ($multiline as $n => $line) {
                   71145:                     $len = strlen($line);
                   71146:                     if ($len > $w) {
                   71147:                         $w = $len;
                   71148:                     }
                   71149:                 }
                   71150:                 $lines = count($multiline);
                   71151:             } else {
                   71152:                 $w = strlen($col);
                   71153:             }
                   71154: 
                   71155:             if (isset($this->params['widest'][$i])) {
                   71156:                 if ($w > $this->params['widest'][$i]) {
                   71157:                     $this->params['widest'][$i] = $w;
                   71158:                 }
                   71159:             } else {
                   71160:                 $this->params['widest'][$i] = $w;
                   71161:             }
                   71162: 
                   71163:             $tmp = count_chars($columns[$i], 1);
                   71164:             // handle unix, mac and windows formats
                   71165:             $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
                   71166:             if ($lines > $highest) {
                   71167:                 $highest = $lines;
                   71168:             }
                   71169:         }
                   71170: 
                   71171:         if (count($columns) > $this->params['ncols']) {
                   71172:             $this->params['ncols'] = count($columns);
                   71173:         }
                   71174: 
                   71175:         $new_row = array(
                   71176:             'data'      => $columns,
                   71177:             'height'    => $highest,
                   71178:             'rowparams' => $rowparams,
                   71179:             'colparams' => $colparams,
                   71180:         );
                   71181:         $this->params['table_data'][] = $new_row;
                   71182:     }
                   71183: 
                   71184:     function _endTable()
                   71185:     {
                   71186:         extract($this->params);
                   71187:         if (!empty($caption)) {
                   71188:             $this->_displayHeading($caption);
                   71189:         }
                   71190: 
                   71191:         if (count($table_data) === 0) {
                   71192:             return;
                   71193:         }
                   71194: 
                   71195:         if (!isset($width)) {
                   71196:             $width = $widest;
                   71197:         } else {
                   71198:             for ($i = 0; $i < $ncols; $i++) {
                   71199:                 if (!isset($width[$i])) {
                   71200:                     $width[$i] = $widest[$i];
                   71201:                 }
                   71202:             }
                   71203:         }
                   71204: 
                   71205:         $border = false;
                   71206:         if (empty($border)) {
                   71207:             $cellstart  = '';
                   71208:             $cellend    = ' ';
                   71209:             $rowend     = '';
                   71210:             $padrowend  = false;
                   71211:             $borderline = '';
                   71212:         } else {
                   71213:             $cellstart  = '| ';
                   71214:             $cellend    = ' ';
                   71215:             $rowend     = '|';
                   71216:             $padrowend  = true;
                   71217:             $borderline = '+';
                   71218:             foreach ($width as $w) {
                   71219:                 $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
                   71220:                 $borderline .= '+';
                   71221:             }
                   71222:         }
                   71223: 
                   71224:         if ($borderline) {
                   71225:             $this->_displayLine($borderline);
                   71226:         }
                   71227: 
                   71228:         for ($i = 0; $i < count($table_data); $i++) {
                   71229:             extract($table_data[$i]);
                   71230:             if (!is_array($rowparams)) {
                   71231:                 $rowparams = array();
                   71232:             }
                   71233: 
                   71234:             if (!is_array($colparams)) {
                   71235:                 $colparams = array();
                   71236:             }
                   71237: 
                   71238:             $rowlines = array();
                   71239:             if ($height > 1) {
                   71240:                 for ($c = 0; $c < count($data); $c++) {
                   71241:                     $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
                   71242:                     if (count($rowlines[$c]) < $height) {
                   71243:                         $rowlines[$c] = array_pad($rowlines[$c], $height, '');
                   71244:                     }
                   71245:                 }
                   71246:             } else {
                   71247:                 for ($c = 0; $c < count($data); $c++) {
                   71248:                     $rowlines[$c] = array($data[$c]);
                   71249:                 }
                   71250:             }
                   71251: 
                   71252:             for ($r = 0; $r < $height; $r++) {
                   71253:                 $rowtext = '';
                   71254:                 for ($c = 0; $c < count($data); $c++) {
                   71255:                     if (isset($colparams[$c])) {
                   71256:                         $attribs = array_merge($rowparams, $colparams);
                   71257:                     } else {
                   71258:                         $attribs = $rowparams;
                   71259:                     }
                   71260: 
                   71261:                     $w = isset($width[$c]) ? $width[$c] : 0;
                   71262:                     //$cell = $data[$c];
                   71263:                     $cell = $rowlines[$c][$r];
                   71264:                     $l = strlen($cell);
                   71265:                     if ($l > $w) {
                   71266:                         $cell = substr($cell, 0, $w);
                   71267:                     }
                   71268: 
                   71269:                     if (isset($attribs['bold'])) {
                   71270:                         $cell = $this->bold($cell);
                   71271:                     }
                   71272: 
                   71273:                     if ($l < $w) {
                   71274:                         // not using str_pad here because we may
                   71275:                         // add bold escape characters to $cell
                   71276:                         $cell .= str_repeat(' ', $w - $l);
                   71277:                     }
                   71278: 
                   71279:                     $rowtext .= $cellstart . $cell . $cellend;
                   71280:                 }
                   71281: 
                   71282:                 if (!$border) {
                   71283:                     $rowtext = rtrim($rowtext);
                   71284:                 }
                   71285: 
                   71286:                 $rowtext .= $rowend;
                   71287:                 $this->_displayLine($rowtext);
                   71288:             }
                   71289:         }
                   71290: 
                   71291:         if ($borderline) {
                   71292:             $this->_displayLine($borderline);
                   71293:         }
                   71294:     }
                   71295: 
                   71296:     function _displayLine($text)
                   71297:     {
                   71298:         print "$this->lp$text\n";
                   71299:     }
                   71300: 
                   71301:     function _display($text)
                   71302:     {
                   71303:         print $text;
                   71304:     }
                   71305: }<?php
                   71306: /**
                   71307:  * PEAR_Installer
                   71308:  *
                   71309:  * PHP versions 4 and 5
                   71310:  *
                   71311:  * @category   pear
                   71312:  * @package    PEAR
                   71313:  * @author     Stig Bakken <ssb@php.net>
                   71314:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   71315:  * @author     Martin Jansen <mj@php.net>
                   71316:  * @author     Greg Beaver <cellog@php.net>
                   71317:  * @copyright  1997-2009 The Authors
                   71318:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   71319:  * @version    CVS: $Id: Installer.php 312945 2011-07-05 18:38:56Z dufuz $
                   71320:  * @link       http://pear.php.net/package/PEAR
                   71321:  * @since      File available since Release 0.1
                   71322:  */
                   71323: 
                   71324: /**
                   71325:  * Used for installation groups in package.xml 2.0 and platform exceptions
                   71326:  */
                   71327: require_once 'phar://install-pear-nozlib.phar/' . 'OS/Guess.php';
                   71328: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
                   71329: 
                   71330: define('PEAR_INSTALLER_NOBINARY', -240);
                   71331: /**
                   71332:  * Administration class used to install PEAR packages and maintain the
                   71333:  * installed package database.
                   71334:  *
                   71335:  * @category   pear
                   71336:  * @package    PEAR
                   71337:  * @author     Stig Bakken <ssb@php.net>
                   71338:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   71339:  * @author     Martin Jansen <mj@php.net>
                   71340:  * @author     Greg Beaver <cellog@php.net>
                   71341:  * @copyright  1997-2009 The Authors
                   71342:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   71343:  * @version    Release: 1.10.0beta1
                   71344:  * @link       http://pear.php.net/package/PEAR
                   71345:  * @since      Class available since Release 0.1
                   71346:  */
                   71347: class PEAR_Installer extends PEAR_Downloader
                   71348: {
                   71349:     /** name of the package directory, for example Foo-1.0
                   71350:      * @var string
                   71351:      */
                   71352:     var $pkgdir;
                   71353: 
                   71354:     /** directory where PHP code files go
                   71355:      * @var string
                   71356:      */
                   71357:     var $phpdir;
                   71358: 
                   71359:     /** directory where PHP extension files go
                   71360:      * @var string
                   71361:      */
                   71362:     var $extdir;
                   71363: 
                   71364:     /** directory where documentation goes
                   71365:      * @var string
                   71366:      */
                   71367:     var $docdir;
                   71368: 
                   71369:     /** installation root directory (ala PHP's INSTALL_ROOT or
                   71370:      * automake's DESTDIR
                   71371:      * @var string
                   71372:      */
                   71373:     var $installroot = '';
                   71374: 
                   71375:     /** debug level
                   71376:      * @var int
                   71377:      */
                   71378:     var $debug = 1;
                   71379: 
                   71380:     /** temporary directory
                   71381:      * @var string
                   71382:      */
                   71383:     var $tmpdir;
                   71384: 
                   71385:     /**
                   71386:      * PEAR_Registry object used by the installer
                   71387:      * @var PEAR_Registry
                   71388:      */
                   71389:     var $registry;
                   71390: 
                   71391:     /**
                   71392:      * array of PEAR_Downloader_Packages
                   71393:      * @var array
                   71394:      */
                   71395:     var $_downloadedPackages;
                   71396: 
                   71397:     /** List of file transactions queued for an install/upgrade/uninstall.
                   71398:      *
                   71399:      *  Format:
                   71400:      *    array(
                   71401:      *      0 => array("rename => array("from-file", "to-file")),
                   71402:      *      1 => array("delete" => array("file-to-delete")),
                   71403:      *      ...
                   71404:      *    )
                   71405:      *
                   71406:      * @var array
                   71407:      */
                   71408:     var $file_operations = array();
                   71409: 
                   71410:     /**
                   71411:      * PEAR_Installer constructor.
                   71412:      *
                   71413:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
                   71414:      *
                   71415:      * @access public
                   71416:      */
                   71417:     function PEAR_Installer(&$ui)
                   71418:     {
                   71419:         parent::PEAR_Common();
                   71420:         $this->setFrontendObject($ui);
                   71421:         $this->debug = $this->config->get('verbose');
                   71422:     }
                   71423: 
                   71424:     function setOptions($options)
                   71425:     {
                   71426:         $this->_options = $options;
                   71427:     }
                   71428: 
                   71429:     function setConfig(&$config)
                   71430:     {
                   71431:         $this->config    = &$config;
                   71432:         $this->_registry = &$config->getRegistry();
                   71433:     }
                   71434: 
                   71435:     function _removeBackups($files)
                   71436:     {
                   71437:         foreach ($files as $path) {
                   71438:             $this->addFileOperation('removebackup', array($path));
                   71439:         }
                   71440:     }
                   71441: 
                   71442:     /**
                   71443:      * Delete a package's installed files, does not remove empty directories.
                   71444:      *
                   71445:      * @param string package name
                   71446:      * @param string channel name
                   71447:      * @param bool if true, then files are backed up first
                   71448:      * @return bool TRUE on success, or a PEAR error on failure
                   71449:      * @access protected
                   71450:      */
                   71451:     function _deletePackageFiles($package, $channel = false, $backup = false)
                   71452:     {
                   71453:         if (!$channel) {
                   71454:             $channel = 'pear.php.net';
                   71455:         }
                   71456: 
                   71457:         if (!strlen($package)) {
                   71458:             return $this->raiseError("No package to uninstall given");
                   71459:         }
                   71460: 
                   71461:         if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
                   71462:             // to avoid race conditions, include all possible needed files
                   71463:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   71464:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Replace.php';
                   71465:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Unixeol.php';
                   71466:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Windowseol.php';
                   71467:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   71468:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   71469:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v1.php';
                   71470:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v2.php';
                   71471:         }
                   71472: 
                   71473:         $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
                   71474:         if ($filelist == null) {
                   71475:             return $this->raiseError("$channel/$package not installed");
                   71476:         }
                   71477: 
                   71478:         $ret = array();
                   71479:         foreach ($filelist as $file => $props) {
                   71480:             if (empty($props['installed_as'])) {
                   71481:                 continue;
                   71482:             }
                   71483: 
                   71484:             $path = $props['installed_as'];
                   71485:             if ($backup) {
                   71486:                 $this->addFileOperation('backup', array($path));
                   71487:                 $ret[] = $path;
                   71488:             }
                   71489: 
                   71490:             $this->addFileOperation('delete', array($path));
                   71491:         }
                   71492: 
                   71493:         if ($backup) {
                   71494:             return $ret;
                   71495:         }
                   71496: 
                   71497:         return true;
                   71498:     }
                   71499: 
                   71500:     /**
                   71501:      * @param string filename
                   71502:      * @param array attributes from <file> tag in package.xml
                   71503:      * @param string path to install the file in
                   71504:      * @param array options from command-line
                   71505:      * @access private
                   71506:      */
                   71507:     function _installFile($file, $atts, $tmp_path, $options)
                   71508:     {
                   71509:         // return if this file is meant for another platform
                   71510:         static $os;
                   71511:         if (!isset($this->_registry)) {
                   71512:             $this->_registry = &$this->config->getRegistry();
                   71513:         }
                   71514: 
                   71515:         if (isset($atts['platform'])) {
                   71516:             if (empty($os)) {
                   71517:                 $os = new OS_Guess;
                   71518:             }
                   71519: 
                   71520:             if (strlen($atts['platform']) && $atts['platform']{0} == '!') {
                   71521:                 $negate   = true;
                   71522:                 $platform = substr($atts['platform'], 1);
                   71523:             } else {
                   71524:                 $negate    = false;
                   71525:                 $platform = $atts['platform'];
                   71526:             }
                   71527: 
                   71528:             if ((bool) $os->matchSignature($platform) === $negate) {
                   71529:                 $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
                   71530:                 return PEAR_INSTALLER_SKIPPED;
                   71531:             }
                   71532:         }
                   71533: 
                   71534:         $channel = $this->pkginfo->getChannel();
                   71535:         // assemble the destination paths
                   71536:         switch ($atts['role']) {
                   71537:             case 'src':
                   71538:             case 'extsrc':
                   71539:                 $this->source_files++;
                   71540:                 return;
                   71541:             case 'doc':
                   71542:             case 'data':
                   71543:             case 'test':
                   71544:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
                   71545:                             DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
                   71546:                 unset($atts['baseinstalldir']);
                   71547:                 break;
                   71548:             case 'ext':
                   71549:             case 'php':
                   71550:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
                   71551:                 break;
                   71552:             case 'script':
                   71553:                 $dest_dir = $this->config->get('bin_dir', null, $channel);
                   71554:                 break;
                   71555:             default:
                   71556:                 return $this->raiseError("Invalid role `$atts[role]' for file $file");
                   71557:         }
                   71558: 
                   71559:         $save_destdir = $dest_dir;
                   71560:         if (!empty($atts['baseinstalldir'])) {
                   71561:             $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   71562:         }
                   71563: 
                   71564:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   71565:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   71566:         }
                   71567: 
                   71568:         if (empty($atts['install-as'])) {
                   71569:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   71570:         } else {
                   71571:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   71572:         }
                   71573:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   71574: 
                   71575:         // Clean up the DIRECTORY_SEPARATOR mess
                   71576:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   71577:         list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   71578:                                                     array(DIRECTORY_SEPARATOR,
                   71579:                                                           DIRECTORY_SEPARATOR,
                   71580:                                                           DIRECTORY_SEPARATOR),
                   71581:                                                     array($dest_file, $orig_file));
                   71582:         $final_dest_file = $installed_as = $dest_file;
                   71583:         if (isset($this->_options['packagingroot'])) {
                   71584:             $installedas_dest_dir  = dirname($final_dest_file);
                   71585:             $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   71586:             $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
                   71587:         } else {
                   71588:             $installedas_dest_dir  = dirname($final_dest_file);
                   71589:             $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   71590:         }
                   71591: 
                   71592:         $dest_dir  = dirname($final_dest_file);
                   71593:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   71594:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   71595:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   71596:         }
                   71597: 
                   71598:         if (
                   71599:             empty($this->_options['register-only']) &&
                   71600:             (!file_exists($dest_dir) || !is_dir($dest_dir))
                   71601:         ) {
                   71602:             if (!$this->mkDirHier($dest_dir)) {
                   71603:                 return $this->raiseError("failed to mkdir $dest_dir",
                   71604:                                          PEAR_INSTALLER_FAILED);
                   71605:             }
                   71606:             $this->log(3, "+ mkdir $dest_dir");
                   71607:         }
                   71608: 
                   71609:         // pretty much nothing happens if we are only registering the install
                   71610:         if (empty($this->_options['register-only'])) {
                   71611:             if (empty($atts['replacements'])) {
                   71612:                 if (!file_exists($orig_file)) {
                   71613:                     return $this->raiseError("file $orig_file does not exist",
                   71614:                                              PEAR_INSTALLER_FAILED);
                   71615:                 }
                   71616: 
                   71617:                 if (!@copy($orig_file, $dest_file)) {
                   71618:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   71619:                                              PEAR_INSTALLER_FAILED);
                   71620:                 }
                   71621: 
                   71622:                 $this->log(3, "+ cp $orig_file $dest_file");
                   71623:                 if (isset($atts['md5sum'])) {
                   71624:                     $md5sum = md5_file($dest_file);
                   71625:                 }
                   71626:             } else {
                   71627:                 // file with replacements
                   71628:                 if (!file_exists($orig_file)) {
                   71629:                     return $this->raiseError("file does not exist",
                   71630:                                              PEAR_INSTALLER_FAILED);
                   71631:                 }
                   71632: 
                   71633:                 $contents = file_get_contents($orig_file);
                   71634:                 if ($contents === false) {
                   71635:                     $contents = '';
                   71636:                 }
                   71637: 
                   71638:                 if (isset($atts['md5sum'])) {
                   71639:                     $md5sum = md5($contents);
                   71640:                 }
                   71641: 
                   71642:                 $subst_from = $subst_to = array();
                   71643:                 foreach ($atts['replacements'] as $a) {
                   71644:                     $to = '';
                   71645:                     if ($a['type'] == 'php-const') {
                   71646:                         if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
                   71647:                             eval("\$to = $a[to];");
                   71648:                         } else {
                   71649:                             if (!isset($options['soft'])) {
                   71650:                                 $this->log(0, "invalid php-const replacement: $a[to]");
                   71651:                             }
                   71652:                             continue;
                   71653:                         }
                   71654:                     } elseif ($a['type'] == 'pear-config') {
                   71655:                         if ($a['to'] == 'master_server') {
                   71656:                             $chan = $this->_registry->getChannel($channel);
                   71657:                             if (!PEAR::isError($chan)) {
                   71658:                                 $to = $chan->getServer();
                   71659:                             } else {
                   71660:                                 $to = $this->config->get($a['to'], null, $channel);
                   71661:                             }
                   71662:                         } else {
                   71663:                             $to = $this->config->get($a['to'], null, $channel);
                   71664:                         }
                   71665: 
                   71666:                         if (is_null($to)) {
                   71667:                             if (!isset($options['soft'])) {
                   71668:                                 $this->log(0, "invalid pear-config replacement: $a[to]");
                   71669:                             }
                   71670: 
                   71671:                             continue;
                   71672:                         }
                   71673:                     } elseif ($a['type'] == 'package-info') {
                   71674:                         if ($t = $this->pkginfo->packageInfo($a['to'])) {
                   71675:                             $to = $t;
                   71676:                         } else {
                   71677:                             if (!isset($options['soft'])) {
                   71678:                                 $this->log(0, "invalid package-info replacement: $a[to]");
                   71679:                             }
                   71680: 
                   71681:                             continue;
                   71682:                         }
                   71683:                     }
                   71684: 
                   71685:                     if (!is_null($to)) {
                   71686:                         $subst_from[] = $a['from'];
                   71687:                         $subst_to[] = $to;
                   71688:                     }
                   71689:                 }
                   71690: 
                   71691:                 $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
                   71692:                 if (sizeof($subst_from)) {
                   71693:                     $contents = str_replace($subst_from, $subst_to, $contents);
                   71694:                 }
                   71695: 
                   71696:                 $wp = @fopen($dest_file, "wb");
                   71697:                 if (!is_resource($wp)) {
                   71698:                     return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   71699:                                              PEAR_INSTALLER_FAILED);
                   71700:                 }
                   71701: 
                   71702:                 if (@fwrite($wp, $contents) === false) {
                   71703:                     return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   71704:                                              PEAR_INSTALLER_FAILED);
                   71705:                 }
                   71706: 
                   71707:                 fclose($wp);
                   71708:             }
                   71709: 
                   71710:             // check the md5
                   71711:             if (isset($md5sum)) {
                   71712:                 if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
                   71713:                     $this->log(2, "md5sum ok: $final_dest_file");
                   71714:                 } else {
                   71715:                     if (empty($options['force'])) {
                   71716:                         // delete the file
                   71717:                         if (file_exists($dest_file)) {
                   71718:                             unlink($dest_file);
                   71719:                         }
                   71720: 
                   71721:                         if (!isset($options['ignore-errors'])) {
                   71722:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   71723:                                                  PEAR_INSTALLER_FAILED);
                   71724:                         }
                   71725: 
                   71726:                         if (!isset($options['soft'])) {
                   71727:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   71728:                         }
                   71729:                     } else {
                   71730:                         if (!isset($options['soft'])) {
                   71731:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   71732:                         }
                   71733:                     }
                   71734:                 }
                   71735:             }
                   71736: 
                   71737:             // set file permissions
                   71738:             if (!OS_WINDOWS) {
                   71739:                 $umask = $this->config->get('umask');
                   71740:                 if ($atts['role'] == 'script') {
                   71741:                     $mode = 0777 & ~(int)octdec($umask);
                   71742:                     $this->log(3, "+ chmod +x $dest_file");
                   71743:                 } else {
                   71744:                     $mode = 0666 & ~(int)octdec($umask);
                   71745:                 }
                   71746: 
                   71747:                 if ($atts['role'] != 'src') {
                   71748:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   71749:                     if (!@chmod($dest_file, $mode)) {
                   71750:                         if (!isset($options['soft'])) {
                   71751:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   71752:                         }
                   71753:                     }
                   71754:                 }
                   71755:             }
                   71756: 
                   71757:             if ($atts['role'] == 'src') {
                   71758:                 rename($dest_file, $final_dest_file);
                   71759:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   71760:             } else {
                   71761:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file,
                   71762:                     $atts['role'] == 'ext'));
                   71763:             }
                   71764:         }
                   71765: 
                   71766:         // Store the full path where the file was installed for easy unistall
                   71767:         if ($atts['role'] != 'script') {
                   71768:             $loc = $this->config->get($atts['role'] . '_dir');
                   71769:         } else {
                   71770:             $loc = $this->config->get('bin_dir');
                   71771:         }
                   71772: 
                   71773:         if ($atts['role'] != 'src') {
                   71774:             $this->addFileOperation("installed_as", array($file, $installed_as,
                   71775:                                     $loc,
                   71776:                                     dirname(substr($installedas_dest_file, strlen($loc)))));
                   71777:         }
                   71778: 
                   71779:         //$this->log(2, "installed: $dest_file");
                   71780:         return PEAR_INSTALLER_OK;
                   71781:     }
                   71782: 
                   71783:     /**
                   71784:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   71785:      * @param string filename
                   71786:      * @param array attributes from <file> tag in package.xml
                   71787:      * @param string path to install the file in
                   71788:      * @param array options from command-line
                   71789:      * @access private
                   71790:      */
                   71791:     function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
                   71792:     {
                   71793:         $atts = $real_atts;
                   71794:         if (!isset($this->_registry)) {
                   71795:             $this->_registry = &$this->config->getRegistry();
                   71796:         }
                   71797: 
                   71798:         $channel = $pkg->getChannel();
                   71799:         // assemble the destination paths
                   71800:         $roles = PEAR_Installer_Role::getValidRoles($pkg->getPackageType());
                   71801:         if (!in_array($atts['attribs']['role'], $roles)) {
                   71802:             return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
                   71803:                     "' for file $file");
                   71804:         }
                   71805: 
                   71806:         $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
                   71807:         $err  = $role->setup($this, $pkg, $atts['attribs'], $file);
                   71808:         if (PEAR::isError($err)) {
                   71809:             return $err;
                   71810:         }
                   71811: 
                   71812:         if (!$role->isInstallable()) {
                   71813:             return;
                   71814:         }
                   71815: 
                   71816:         $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
                   71817:         if (PEAR::isError($info)) {
                   71818:             return $info;
                   71819:         }
                   71820: 
                   71821:         list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
                   71822:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   71823:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   71824:         }
                   71825: 
                   71826:         $final_dest_file = $installed_as = $dest_file;
                   71827:         if (isset($this->_options['packagingroot'])) {
                   71828:             $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
                   71829:         }
                   71830: 
                   71831:         $dest_dir  = dirname($final_dest_file);
                   71832:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   71833: 
                   71834:         if (empty($this->_options['register-only'])) {
                   71835:             if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
                   71836:                 if (!$this->mkDirHier($dest_dir)) {
                   71837:                     return $this->raiseError("failed to mkdir $dest_dir",
                   71838:                                              PEAR_INSTALLER_FAILED);
                   71839:                 }
                   71840:                 $this->log(3, "+ mkdir $dest_dir");
                   71841:             }
                   71842:         }
                   71843: 
                   71844:         $attribs = $atts['attribs'];
                   71845:         unset($atts['attribs']);
                   71846:         // pretty much nothing happens if we are only registering the install
                   71847:         if (empty($this->_options['register-only'])) {
                   71848:             if (!count($atts)) { // no tasks
                   71849:                 if (!file_exists($orig_file)) {
                   71850:                     return $this->raiseError("file $orig_file does not exist",
                   71851:                                              PEAR_INSTALLER_FAILED);
                   71852:                 }
                   71853: 
                   71854:                 if (!@copy($orig_file, $dest_file)) {
                   71855:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   71856:                                              PEAR_INSTALLER_FAILED);
                   71857:                 }
                   71858: 
                   71859:                 $this->log(3, "+ cp $orig_file $dest_file");
                   71860:                 if (isset($attribs['md5sum'])) {
                   71861:                     $md5sum = md5_file($dest_file);
                   71862:                 }
                   71863:             } else { // file with tasks
                   71864:                 if (!file_exists($orig_file)) {
                   71865:                     return $this->raiseError("file $orig_file does not exist",
                   71866:                                              PEAR_INSTALLER_FAILED);
                   71867:                 }
                   71868: 
                   71869:                 $contents = file_get_contents($orig_file);
                   71870:                 if ($contents === false) {
                   71871:                     $contents = '';
                   71872:                 }
                   71873: 
                   71874:                 if (isset($attribs['md5sum'])) {
                   71875:                     $md5sum = md5($contents);
                   71876:                 }
                   71877: 
                   71878:                 foreach ($atts as $tag => $raw) {
                   71879:                     $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
                   71880:                     $task = "PEAR_Task_$tag";
                   71881:                     $task = &new $task($this->config, $this, PEAR_TASK_INSTALL);
                   71882:                     if (!$task->isScript()) { // scripts are only handled after installation
                   71883:                         $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
                   71884:                         $res = $task->startSession($pkg, $contents, $final_dest_file);
                   71885:                         if ($res === false) {
                   71886:                             continue; // skip this file
                   71887:                         }
                   71888: 
                   71889:                         if (PEAR::isError($res)) {
                   71890:                             return $res;
                   71891:                         }
                   71892: 
                   71893:                         $contents = $res; // save changes
                   71894:                     }
                   71895: 
                   71896:                     $wp = @fopen($dest_file, "wb");
                   71897:                     if (!is_resource($wp)) {
                   71898:                         return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   71899:                                                  PEAR_INSTALLER_FAILED);
                   71900:                     }
                   71901: 
                   71902:                     if (fwrite($wp, $contents) === false) {
                   71903:                         return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   71904:                                                  PEAR_INSTALLER_FAILED);
                   71905:                     }
                   71906: 
                   71907:                     fclose($wp);
                   71908:                 }
                   71909:             }
                   71910: 
                   71911:             // check the md5
                   71912:             if (isset($md5sum)) {
                   71913:                 // Make sure the original md5 sum matches with expected
                   71914:                 if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
                   71915:                     $this->log(2, "md5sum ok: $final_dest_file");
                   71916: 
                   71917:                     if (isset($contents)) {
                   71918:                         // set md5 sum based on $content in case any tasks were run.
                   71919:                         $real_atts['attribs']['md5sum'] = md5($contents);
                   71920:                     }
                   71921:                 } else {
                   71922:                     if (empty($options['force'])) {
                   71923:                         // delete the file
                   71924:                         if (file_exists($dest_file)) {
                   71925:                             unlink($dest_file);
                   71926:                         }
                   71927: 
                   71928:                         if (!isset($options['ignore-errors'])) {
                   71929:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   71930:                                                      PEAR_INSTALLER_FAILED);
                   71931:                         }
                   71932: 
                   71933:                         if (!isset($options['soft'])) {
                   71934:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   71935:                         }
                   71936:                     } else {
                   71937:                         if (!isset($options['soft'])) {
                   71938:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   71939:                         }
                   71940:                     }
                   71941:                 }
                   71942:             } else {
                   71943:                 $real_atts['attribs']['md5sum'] = md5_file($dest_file);
                   71944:             }
                   71945: 
                   71946:             //set file permissions
                   71947:             if (!OS_WINDOWS) {
                   71948:                 if ($role->isExecutable()) {
                   71949:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                   71950:                     $this->log(3, "+ chmod +x $dest_file");
                   71951:                 } else {
                   71952:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   71953:                 }
                   71954: 
                   71955:                 if ($attribs['role'] != 'src') {
                   71956:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   71957:                     if (!@chmod($dest_file, $mode)) {
                   71958:                         if (!isset($options['soft'])) {
                   71959:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   71960:                         }
                   71961:                     }
                   71962:                 }
                   71963:             }
                   71964: 
                   71965:             if ($attribs['role'] == 'src') {
                   71966:                 rename($dest_file, $final_dest_file);
                   71967:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   71968:             } else {
                   71969:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
                   71970:             }
                   71971:         }
                   71972: 
                   71973:         // Store the full path where the file was installed for easy uninstall
                   71974:         if ($attribs['role'] != 'src') {
                   71975:             $loc = $this->config->get($role->getLocationConfig(), null, $channel);
                   71976:             $this->addFileOperation('installed_as', array($file, $installed_as,
                   71977:                                 $loc,
                   71978:                                 dirname(substr($installed_as, strlen($loc)))));
                   71979:         }
                   71980: 
                   71981:         //$this->log(2, "installed: $dest_file");
                   71982:         return PEAR_INSTALLER_OK;
                   71983:     }
                   71984: 
                   71985:     /**
                   71986:      * Add a file operation to the current file transaction.
                   71987:      *
                   71988:      * @see startFileTransaction()
                   71989:      * @param string $type This can be one of:
                   71990:      *    - rename:  rename a file ($data has 3 values)
                   71991:      *    - backup:  backup an existing file ($data has 1 value)
                   71992:      *    - removebackup:  clean up backups created during install ($data has 1 value)
                   71993:      *    - chmod:   change permissions on a file ($data has 2 values)
                   71994:      *    - delete:  delete a file ($data has 1 value)
                   71995:      *    - rmdir:   delete a directory if empty ($data has 1 value)
                   71996:      *    - installed_as: mark a file as installed ($data has 4 values).
                   71997:      * @param array $data For all file operations, this array must contain the
                   71998:      *    full path to the file or directory that is being operated on.  For
                   71999:      *    the rename command, the first parameter must be the file to rename,
                   72000:      *    the second its new name, the third whether this is a PHP extension.
                   72001:      *
                   72002:      *    The installed_as operation contains 4 elements in this order:
                   72003:      *    1. Filename as listed in the filelist element from package.xml
                   72004:      *    2. Full path to the installed file
                   72005:      *    3. Full path from the php_dir configuration variable used in this
                   72006:      *       installation
                   72007:      *    4. Relative path from the php_dir that this file is installed in
                   72008:      */
                   72009:     function addFileOperation($type, $data)
                   72010:     {
                   72011:         if (!is_array($data)) {
                   72012:             return $this->raiseError('Internal Error: $data in addFileOperation'
                   72013:                 . ' must be an array, was ' . gettype($data));
                   72014:         }
                   72015: 
                   72016:         if ($type == 'chmod') {
                   72017:             $octmode = decoct($data[0]);
                   72018:             $this->log(3, "adding to transaction: $type $octmode $data[1]");
                   72019:         } else {
                   72020:             $this->log(3, "adding to transaction: $type " . implode(" ", $data));
                   72021:         }
                   72022:         $this->file_operations[] = array($type, $data);
                   72023:     }
                   72024: 
                   72025:     function startFileTransaction($rollback_in_case = false)
                   72026:     {
                   72027:         if (count($this->file_operations) && $rollback_in_case) {
                   72028:             $this->rollbackFileTransaction();
                   72029:         }
                   72030:         $this->file_operations = array();
                   72031:     }
                   72032: 
                   72033:     function commitFileTransaction()
                   72034:     {
                   72035:         //first, check permissions and such manually
                   72036:         $errors = array();
                   72037:         foreach ($this->file_operations as $key => $tr) {
                   72038:             list($type, $data) = $tr;
                   72039:             switch ($type) {
                   72040:                 case 'rename':
                   72041:                     if (!file_exists($data[0])) {
                   72042:                         $errors[] = "cannot rename file $data[0], doesn't exist";
                   72043:                     }
                   72044: 
                   72045:                     // check that dest dir. is writable
                   72046:                     if (!is_writable(dirname($data[1]))) {
                   72047:                         $errors[] = "permission denied ($type): $data[1]";
                   72048:                     }
                   72049:                     break;
                   72050:                 case 'chmod':
                   72051:                     // check that file is writable
                   72052:                     if (!is_writable($data[1])) {
                   72053:                         $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
                   72054:                     }
                   72055:                     break;
                   72056:                 case 'delete':
                   72057:                     if (!file_exists($data[0])) {
                   72058:                         $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
                   72059:                     }
                   72060: 
                   72061:                     // check that directory is writable
                   72062:                     if (file_exists($data[0])) {
                   72063:                         if (!is_writable(dirname($data[0]))) {
                   72064:                             $errors[] = "permission denied ($type): $data[0]";
                   72065:                         } else {
                   72066:                             // make sure the file to be deleted can be opened for writing
                   72067:                             $fp = false;
                   72068:                             if (!is_dir($data[0]) &&
                   72069:                                   (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
                   72070:                                 $errors[] = "permission denied ($type): $data[0]";
                   72071:                             } elseif ($fp) {
                   72072:                                 fclose($fp);
                   72073:                             }
                   72074:                         }
                   72075: 
                   72076:                         /* Verify we are not deleting a file owned by another package
                   72077:                          * This can happen when a file moves from package A to B in
                   72078:                          * an upgrade ala http://pear.php.net/17986
                   72079:                          */
                   72080:                         $info = array(
                   72081:                             'package' => strtolower($this->pkginfo->getName()),
                   72082:                             'channel' => strtolower($this->pkginfo->getChannel()),
                   72083:                         );
                   72084:                         $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
                   72085:                         if (is_array($result)) {
                   72086:                             $res = array_diff($result, $info);
                   72087:                             if (!empty($res)) {
                   72088:                                 $new = $this->_registry->getPackage($result[1], $result[0]);
                   72089:                                 $this->file_operations[$key] = false;
                   72090:                                 $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.");
                   72091:                             }
                   72092:                         }
                   72093:                     }
                   72094:                     break;
                   72095:             }
                   72096:         }
                   72097: 
                   72098:         $n = count($this->file_operations);
                   72099:         $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
                   72100: 
                   72101:         $m = count($errors);
                   72102:         if ($m > 0) {
                   72103:             foreach ($errors as $error) {
                   72104:                 if (!isset($this->_options['soft'])) {
                   72105:                     $this->log(1, $error);
                   72106:                 }
                   72107:             }
                   72108: 
                   72109:             if (!isset($this->_options['ignore-errors'])) {
                   72110:                 return false;
                   72111:             }
                   72112:         }
                   72113: 
                   72114:         $this->_dirtree = array();
                   72115:         // really commit the transaction
                   72116:         foreach ($this->file_operations as $i => $tr) {
                   72117:             if (!$tr) {
                   72118:                 // support removal of non-existing backups
                   72119:                 continue;
                   72120:             }
                   72121: 
                   72122:             list($type, $data) = $tr;
                   72123:             switch ($type) {
                   72124:                 case 'backup':
                   72125:                     if (!file_exists($data[0])) {
                   72126:                         $this->file_operations[$i] = false;
                   72127:                         break;
                   72128:                     }
                   72129: 
                   72130:                     if (!@copy($data[0], $data[0] . '.bak')) {
                   72131:                         $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
                   72132:                             '.bak ' . $php_errormsg);
                   72133:                         return false;
                   72134:                     }
                   72135:                     $this->log(3, "+ backup $data[0] to $data[0].bak");
                   72136:                     break;
                   72137:                 case 'removebackup':
                   72138:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   72139:                         unlink($data[0] . '.bak');
                   72140:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   72141:                     }
                   72142:                     break;
                   72143:                 case 'rename':
                   72144:                     $test = file_exists($data[1]) ? @unlink($data[1]) : null;
                   72145:                     if (!$test && file_exists($data[1])) {
                   72146:                         if ($data[2]) {
                   72147:                             $extra = ', this extension must be installed manually.  Rename to "' .
                   72148:                                 basename($data[1]) . '"';
                   72149:                         } else {
                   72150:                             $extra = '';
                   72151:                         }
                   72152: 
                   72153:                         if (!isset($this->_options['soft'])) {
                   72154:                             $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
                   72155:                                 $data[0] . $extra);
                   72156:                         }
                   72157: 
                   72158:                         if (!isset($this->_options['ignore-errors'])) {
                   72159:                             return false;
                   72160:                         }
                   72161:                     }
                   72162: 
                   72163:                     // permissions issues with rename - copy() is far superior
                   72164:                     $perms = @fileperms($data[0]);
                   72165:                     if (!@copy($data[0], $data[1])) {
                   72166:                         $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
                   72167:                             ' ' . $php_errormsg);
                   72168:                         return false;
                   72169:                     }
                   72170: 
                   72171:                     // copy over permissions, otherwise they are lost
                   72172:                     @chmod($data[1], $perms);
                   72173:                     @unlink($data[0]);
                   72174:                     $this->log(3, "+ mv $data[0] $data[1]");
                   72175:                     break;
                   72176:                 case 'chmod':
                   72177:                     if (!@chmod($data[1], $data[0])) {
                   72178:                         $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
                   72179:                             decoct($data[0]) . ' ' . $php_errormsg);
                   72180:                         return false;
                   72181:                     }
                   72182: 
                   72183:                     $octmode = decoct($data[0]);
                   72184:                     $this->log(3, "+ chmod $octmode $data[1]");
                   72185:                     break;
                   72186:                 case 'delete':
                   72187:                     if (file_exists($data[0])) {
                   72188:                         if (!@unlink($data[0])) {
                   72189:                             $this->log(1, 'Could not delete ' . $data[0] . ' ' .
                   72190:                                 $php_errormsg);
                   72191:                             return false;
                   72192:                         }
                   72193:                         $this->log(3, "+ rm $data[0]");
                   72194:                     }
                   72195:                     break;
                   72196:                 case 'rmdir':
                   72197:                     if (file_exists($data[0])) {
                   72198:                         do {
                   72199:                             $testme = opendir($data[0]);
                   72200:                             while (false !== ($entry = readdir($testme))) {
                   72201:                                 if ($entry == '.' || $entry == '..') {
                   72202:                                     continue;
                   72203:                                 }
                   72204:                                 closedir($testme);
                   72205:                                 break 2; // this directory is not empty and can't be
                   72206:                                          // deleted
                   72207:                             }
                   72208: 
                   72209:                             closedir($testme);
                   72210:                             if (!@rmdir($data[0])) {
                   72211:                                 $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
                   72212:                                     $php_errormsg);
                   72213:                                 return false;
                   72214:                             }
                   72215:                             $this->log(3, "+ rmdir $data[0]");
                   72216:                         } while (false);
                   72217:                     }
                   72218:                     break;
                   72219:                 case 'installed_as':
                   72220:                     $this->pkginfo->setInstalledAs($data[0], $data[1]);
                   72221:                     if (!isset($this->_dirtree[dirname($data[1])])) {
                   72222:                         $this->_dirtree[dirname($data[1])] = true;
                   72223:                         $this->pkginfo->setDirtree(dirname($data[1]));
                   72224: 
                   72225:                         while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
                   72226:                                 $data[3] != '/' && $data[3] != '\\') {
                   72227:                             $this->pkginfo->setDirtree($pp =
                   72228:                                 $this->_prependPath($data[3], $data[2]));
                   72229:                             $this->_dirtree[$pp] = true;
                   72230:                             $data[3] = dirname($data[3]);
                   72231:                         }
                   72232:                     }
                   72233:                     break;
                   72234:             }
                   72235:         }
                   72236: 
                   72237:         $this->log(2, "successfully committed $n file operations");
                   72238:         $this->file_operations = array();
                   72239:         return true;
                   72240:     }
                   72241: 
                   72242:     function rollbackFileTransaction()
                   72243:     {
                   72244:         $n = count($this->file_operations);
                   72245:         $this->log(2, "rolling back $n file operations");
                   72246:         foreach ($this->file_operations as $tr) {
                   72247:             list($type, $data) = $tr;
                   72248:             switch ($type) {
                   72249:                 case 'backup':
                   72250:                     if (file_exists($data[0] . '.bak')) {
                   72251:                         if (file_exists($data[0] && is_writable($data[0]))) {
                   72252:                             unlink($data[0]);
                   72253:                         }
                   72254:                         @copy($data[0] . '.bak', $data[0]);
                   72255:                         $this->log(3, "+ restore $data[0] from $data[0].bak");
                   72256:                     }
                   72257:                     break;
                   72258:                 case 'removebackup':
                   72259:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   72260:                         unlink($data[0] . '.bak');
                   72261:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   72262:                     }
                   72263:                     break;
                   72264:                 case 'rename':
                   72265:                     @unlink($data[0]);
                   72266:                     $this->log(3, "+ rm $data[0]");
                   72267:                     break;
                   72268:                 case 'mkdir':
                   72269:                     @rmdir($data[0]);
                   72270:                     $this->log(3, "+ rmdir $data[0]");
                   72271:                     break;
                   72272:                 case 'chmod':
                   72273:                     break;
                   72274:                 case 'delete':
                   72275:                     break;
                   72276:                 case 'installed_as':
                   72277:                     $this->pkginfo->setInstalledAs($data[0], false);
                   72278:                     break;
                   72279:             }
                   72280:         }
                   72281:         $this->pkginfo->resetDirtree();
                   72282:         $this->file_operations = array();
                   72283:     }
                   72284: 
                   72285:     function mkDirHier($dir)
                   72286:     {
                   72287:         $this->addFileOperation('mkdir', array($dir));
                   72288:         return parent::mkDirHier($dir);
                   72289:     }
                   72290: 
                   72291:     /**
                   72292:      * Download any files and their dependencies, if necessary
                   72293:      *
                   72294:      * @param array a mixed list of package names, local files, or package.xml
                   72295:      * @param PEAR_Config
                   72296:      * @param array options from the command line
                   72297:      * @param array this is the array that will be populated with packages to
                   72298:      *              install.  Format of each entry:
                   72299:      *
                   72300:      * <code>
                   72301:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   72302:      *    'info' => array() // parsed package.xml
                   72303:      * );
                   72304:      * </code>
                   72305:      * @param array this will be populated with any error messages
                   72306:      * @param false private recursion variable
                   72307:      * @param false private recursion variable
                   72308:      * @param false private recursion variable
                   72309:      * @deprecated in favor of PEAR_Downloader
                   72310:      */
                   72311:     function download($packages, $options, &$config, &$installpackages,
                   72312:                       &$errors, $installed = false, $willinstall = false, $state = false)
                   72313:     {
                   72314:         // trickiness: initialize here
                   72315:         parent::PEAR_Downloader($this->ui, $options, $config);
                   72316:         $ret             = parent::download($packages);
                   72317:         $errors          = $this->getErrorMsgs();
                   72318:         $installpackages = $this->getDownloadedPackages();
                   72319:         trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " .
                   72320:                       "in favor of PEAR_Downloader class", E_USER_WARNING);
                   72321:         return $ret;
                   72322:     }
                   72323: 
                   72324:     function _parsePackageXml(&$descfile)
                   72325:     {
                   72326:         // Parse xml file
                   72327:         $pkg = new PEAR_PackageFile($this->config, $this->debug);
                   72328:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   72329:         $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
                   72330:         PEAR::staticPopErrorHandling();
                   72331:         if (PEAR::isError($p)) {
                   72332:             if (is_array($p->getUserInfo())) {
                   72333:                 foreach ($p->getUserInfo() as $err) {
                   72334:                     $loglevel = $err['level'] == 'error' ? 0 : 1;
                   72335:                     if (!isset($this->_options['soft'])) {
                   72336:                         $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
                   72337:                     }
                   72338:                 }
                   72339:             }
                   72340:             return $this->raiseError('Installation failed: invalid package file');
                   72341:         }
                   72342: 
                   72343:         $descfile = $p->getPackageFile();
                   72344:         return $p;
                   72345:     }
                   72346: 
                   72347:     /**
                   72348:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   72349:      * dependency validation
                   72350:      * @param array
                   72351:      */
                   72352:     function setDownloadedPackages(&$pkgs)
                   72353:     {
                   72354:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   72355:         $err = $this->analyzeDependencies($pkgs);
                   72356:         PEAR::popErrorHandling();
                   72357:         if (PEAR::isError($err)) {
                   72358:             return $err;
                   72359:         }
                   72360:         $this->_downloadedPackages = &$pkgs;
                   72361:     }
                   72362: 
                   72363:     /**
                   72364:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   72365:      * dependency validation
                   72366:      * @param array
                   72367:      */
                   72368:     function setUninstallPackages(&$pkgs)
                   72369:     {
                   72370:         $this->_downloadedPackages = &$pkgs;
                   72371:     }
                   72372: 
                   72373:     function getInstallPackages()
                   72374:     {
                   72375:         return $this->_downloadedPackages;
                   72376:     }
                   72377: 
                   72378:     /**
                   72379:      * Installs the files within the package file specified.
                   72380:      *
                   72381:      * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
                   72382:      *        or a pre-initialized packagefile object
                   72383:      * @param array $options
                   72384:      * recognized options:
                   72385:      * - installroot   : optional prefix directory for installation
                   72386:      * - force         : force installation
                   72387:      * - register-only : update registry but don't install files
                   72388:      * - upgrade       : upgrade existing install
                   72389:      * - soft          : fail silently
                   72390:      * - nodeps        : ignore dependency conflicts/missing dependencies
                   72391:      * - alldeps       : install all dependencies
                   72392:      * - onlyreqdeps   : install only required dependencies
                   72393:      *
                   72394:      * @return array|PEAR_Error package info if successful
                   72395:      */
                   72396:     function install($pkgfile, $options = array())
                   72397:     {
                   72398:         $this->_options = $options;
                   72399:         $this->_registry = &$this->config->getRegistry();
                   72400:         if (is_object($pkgfile)) {
                   72401:             $dlpkg    = &$pkgfile;
                   72402:             $pkg      = $pkgfile->getPackageFile();
                   72403:             $pkgfile  = $pkg->getArchiveFile();
                   72404:             $descfile = $pkg->getPackageFile();
                   72405:         } else {
                   72406:             $descfile = $pkgfile;
                   72407:             $pkg      = $this->_parsePackageXml($descfile);
                   72408:             if (PEAR::isError($pkg)) {
                   72409:                 return $pkg;
                   72410:             }
                   72411:         }
                   72412: 
                   72413:         $tmpdir = dirname($descfile);
                   72414:         if (realpath($descfile) != realpath($pkgfile)) {
                   72415:             // Use the temp_dir since $descfile can contain the download dir path
                   72416:             $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
                   72417:             $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');
                   72418: 
                   72419:             $tar = new Archive_Tar($pkgfile);
                   72420:             if (!$tar->extract($tmpdir)) {
                   72421:                 return $this->raiseError("unable to unpack $pkgfile");
                   72422:             }
                   72423:         }
                   72424: 
                   72425:         $name    = $pkg->getName();
                   72426:         $channel = $pkg->getChannel();
                   72427:         if (isset($this->_options['packagingroot'])) {
                   72428:             $regdir = $this->_prependPath(
                   72429:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   72430:                 $this->_options['packagingroot']);
                   72431: 
                   72432:             $packrootphp_dir = $this->_prependPath(
                   72433:                 $this->config->get('php_dir', null, $channel),
                   72434:                 $this->_options['packagingroot']);
                   72435:         }
                   72436: 
                   72437:         if (isset($options['installroot'])) {
                   72438:             $this->config->setInstallRoot($options['installroot']);
                   72439:             $this->_registry = &$this->config->getRegistry();
                   72440:             $installregistry = &$this->_registry;
                   72441:             $this->installroot = ''; // all done automagically now
                   72442:             $php_dir = $this->config->get('php_dir', null, $channel);
                   72443:         } else {
                   72444:             $this->config->setInstallRoot(false);
                   72445:             $this->_registry = &$this->config->getRegistry();
                   72446:             if (isset($this->_options['packagingroot'])) {
                   72447:                 $installregistry = &new PEAR_Registry($regdir);
                   72448:                 if (!$installregistry->channelExists($channel, true)) {
                   72449:                     // we need to fake a channel-discover of this channel
                   72450:                     $chanobj = $this->_registry->getChannel($channel, true);
                   72451:                     $installregistry->addChannel($chanobj);
                   72452:                 }
                   72453:                 $php_dir = $packrootphp_dir;
                   72454:             } else {
                   72455:                 $installregistry = &$this->_registry;
                   72456:                 $php_dir = $this->config->get('php_dir', null, $channel);
                   72457:             }
                   72458:             $this->installroot = '';
                   72459:         }
                   72460: 
                   72461:         // checks to do when not in "force" mode
                   72462:         if (empty($options['force']) &&
                   72463:               (file_exists($this->config->get('php_dir')) &&
                   72464:                is_dir($this->config->get('php_dir')))) {
                   72465:             $testp = $channel == 'pear.php.net' ? $name : array($channel, $name);
                   72466:             $instfilelist = $pkg->getInstallationFileList(true);
                   72467:             if (PEAR::isError($instfilelist)) {
                   72468:                 return $instfilelist;
                   72469:             }
                   72470: 
                   72471:             // ensure we have the most accurate registry
                   72472:             $installregistry->flushFileMap();
                   72473:             $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
                   72474:             if (PEAR::isError($test)) {
                   72475:                 return $test;
                   72476:             }
                   72477: 
                   72478:             if (sizeof($test)) {
                   72479:                 $pkgs = $this->getInstallPackages();
                   72480:                 $found = false;
                   72481:                 foreach ($pkgs as $param) {
                   72482:                     if ($pkg->isSubpackageOf($param)) {
                   72483:                         $found = true;
                   72484:                         break;
                   72485:                     }
                   72486:                 }
                   72487: 
                   72488:                 if ($found) {
                   72489:                     // subpackages can conflict with earlier versions of parent packages
                   72490:                     $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
                   72491:                     $tmp = $test;
                   72492:                     foreach ($tmp as $file => $info) {
                   72493:                         if (is_array($info)) {
                   72494:                             if (strtolower($info[1]) == strtolower($param->getPackage()) &&
                   72495:                                   strtolower($info[0]) == strtolower($param->getChannel())
                   72496:                             ) {
                   72497:                                 if (isset($parentreg['filelist'][$file])) {
                   72498:                                     unset($parentreg['filelist'][$file]);
                   72499:                                 } else{
                   72500:                                     $pos     = strpos($file, '/');
                   72501:                                     $basedir = substr($file, 0, $pos);
                   72502:                                     $file2   = substr($file, $pos + 1);
                   72503:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   72504:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   72505:                                     ) {
                   72506:                                         unset($parentreg['filelist'][$file2]);
                   72507:                                     }
                   72508:                                 }
                   72509: 
                   72510:                                 unset($test[$file]);
                   72511:                             }
                   72512:                         } else {
                   72513:                             if (strtolower($param->getChannel()) != 'pear.php.net') {
                   72514:                                 continue;
                   72515:                             }
                   72516: 
                   72517:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   72518:                                 if (isset($parentreg['filelist'][$file])) {
                   72519:                                     unset($parentreg['filelist'][$file]);
                   72520:                                 } else{
                   72521:                                     $pos     = strpos($file, '/');
                   72522:                                     $basedir = substr($file, 0, $pos);
                   72523:                                     $file2   = substr($file, $pos + 1);
                   72524:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   72525:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   72526:                                     ) {
                   72527:                                         unset($parentreg['filelist'][$file2]);
                   72528:                                     }
                   72529:                                 }
                   72530: 
                   72531:                                 unset($test[$file]);
                   72532:                             }
                   72533:                         }
                   72534:                     }
                   72535: 
                   72536:                     $pfk = &new PEAR_PackageFile($this->config);
                   72537:                     $parentpkg = &$pfk->fromArray($parentreg);
                   72538:                     $installregistry->updatePackage2($parentpkg);
                   72539:                 }
                   72540: 
                   72541:                 if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
                   72542:                     $tmp = $test;
                   72543:                     foreach ($tmp as $file => $info) {
                   72544:                         if (is_string($info)) {
                   72545:                             // pear.php.net packages are always stored as strings
                   72546:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   72547:                                 // upgrading existing package
                   72548:                                 unset($test[$file]);
                   72549:                             }
                   72550:                         }
                   72551:                     }
                   72552:                 }
                   72553: 
                   72554:                 if (count($test)) {
                   72555:                     $msg = "$channel/$name: conflicting files found:\n";
                   72556:                     $longest = max(array_map("strlen", array_keys($test)));
                   72557:                     $fmt = "%${longest}s (%s)\n";
                   72558:                     foreach ($test as $file => $info) {
                   72559:                         if (!is_array($info)) {
                   72560:                             $info = array('pear.php.net', $info);
                   72561:                         }
                   72562:                         $info = $info[0] . '/' . $info[1];
                   72563:                         $msg .= sprintf($fmt, $file, $info);
                   72564:                     }
                   72565: 
                   72566:                     if (!isset($options['ignore-errors'])) {
                   72567:                         return $this->raiseError($msg);
                   72568:                     }
                   72569: 
                   72570:                     if (!isset($options['soft'])) {
                   72571:                         $this->log(0, "WARNING: $msg");
                   72572:                     }
                   72573:                 }
                   72574:             }
                   72575:         }
                   72576: 
                   72577:         $this->startFileTransaction();
                   72578: 
                   72579:         // Figure out what channel to use and if the package exists or not
                   72580:         $usechannel = $channel;
                   72581:         if ($channel == 'pecl.php.net') {
                   72582:             $test = $installregistry->packageExists($name, $channel);
                   72583:             if (!$test) {
                   72584:                 $test = $installregistry->packageExists($name, 'pear.php.net');
                   72585:                 $usechannel = 'pear.php.net';
                   72586:             }
                   72587:         } else {
                   72588:             $test = $installregistry->packageExists($name, $channel);
                   72589:         }
                   72590: 
                   72591:         // checks to do only when installing new packages
                   72592:         if (empty($options['upgrade']) && empty($options['soft'])) {
                   72593:             if (empty($options['force']) && $test) {
                   72594:                 return $this->raiseError("$channel/$name is already installed");
                   72595:             }
                   72596:         } else {
                   72597:             // Upgrade
                   72598:             if ($test) {
                   72599:                 $v1 = $installregistry->packageInfo($name, 'version', $usechannel);
                   72600:                 $v2 = $pkg->getVersion();
                   72601:                 $cmp = version_compare("$v1", "$v2", 'gt');
                   72602:                 if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
                   72603:                     return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
                   72604:                 }
                   72605:             }
                   72606:         }
                   72607: 
                   72608:         // Do cleanups for upgrade and install, remove old release's files first
                   72609:         if ($test && empty($options['register-only'])) {
                   72610:             $err = $this->_deletePackageFiles($name, $usechannel, true);
                   72611:             if (PEAR::isError($err)) {
                   72612:                 if (!isset($options['ignore-errors'])) {
                   72613:                     return $this->raiseError($err);
                   72614:                 }
                   72615: 
                   72616:                 if (!isset($options['soft'])) {
                   72617:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   72618:                 }
                   72619:             } else {
                   72620:                 $backedup = $err;
                   72621:             }
                   72622:         }
                   72623: 
                   72624:         // Copy files to dest dir
                   72625: 
                   72626:         // info from the package it self we want to access from _installFile
                   72627:         $this->pkginfo = &$pkg;
                   72628:         // used to determine whether we should build any C code
                   72629:         $this->source_files = 0;
                   72630: 
                   72631:         $savechannel = $this->config->get('default_channel');
                   72632:         if (empty($options['register-only']) && !is_dir($php_dir)) {
                   72633:             if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
                   72634:                 return $this->raiseError("no installation destination directory '$php_dir'\n");
                   72635:             }
                   72636:         }
                   72637: 
                   72638:         if (substr($pkgfile, -4) != '.xml') {
                   72639:             $tmpdir .= DIRECTORY_SEPARATOR . $name . '-' . $pkg->getVersion();
                   72640:         }
                   72641: 
                   72642:         $this->configSet('default_channel', $channel);
                   72643:         // install files
                   72644: 
                   72645:         $filelist = $pkg->getInstallationFilelist();
                   72646:         if (PEAR::isError($filelist)) {
                   72647:             return $filelist;
                   72648:         }
                   72649: 
                   72650:         $p = &$installregistry->getPackage($name, $channel);
                   72651:         $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
                   72652: 
                   72653:         $pkg->resetFilelist();
                   72654:         $version = $installregistry->packageInfo($pkg->getPackage(), 'version', $pkg->getChannel());
                   72655:         $pkg->setLastInstalledVersion($version);
                   72656:         foreach ($filelist as $file => $atts) {
                   72657:             $this->expectError(PEAR_INSTALLER_FAILED);
                   72658:             if ($pkg->getPackagexmlVersion() == '1.0') {
                   72659:                 $res = $this->_installFile($file, $atts, $tmpdir, $options);
                   72660:             } else {
                   72661:                 $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
                   72662:             }
                   72663:             $this->popExpect();
                   72664: 
                   72665:             if (PEAR::isError($res)) {
                   72666:                 if (empty($options['ignore-errors'])) {
                   72667:                     $this->rollbackFileTransaction();
                   72668:                     if ($res->getMessage() == "file does not exist") {
                   72669:                         $this->raiseError("file $file in package.xml does not exist");
                   72670:                     }
                   72671: 
                   72672:                     return $this->raiseError($res);
                   72673:                 }
                   72674: 
                   72675:                 if (!isset($options['soft'])) {
                   72676:                     $this->log(0, "Warning: " . $res->getMessage());
                   72677:                 }
                   72678:             }
                   72679: 
                   72680:             $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
                   72681:             if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
                   72682:                 // Register files that were installed
                   72683:                 $pkg->installedFile($file, $atts);
                   72684:             }
                   72685:         }
                   72686: 
                   72687:         // compile and install source files
                   72688:         if ($this->source_files > 0 && empty($options['nobuild'])) {
                   72689:             if (!isset($options['__compile_configureoptions'])) {
                   72690:                 $options['__compile_configureoptions'] = array();
                   72691:             }
                   72692: 
                   72693:             if (PEAR::isError($err =
                   72694:                   $this->_compileSourceFiles($savechannel, $pkg, $options['__compile_configureoptions']))) {
                   72695:                 return $err;
                   72696:             }
                   72697:         }
                   72698: 
                   72699:         if (isset($backedup)) {
                   72700:             $this->_removeBackups($backedup);
                   72701:         }
                   72702: 
                   72703:         if (!$this->commitFileTransaction()) {
                   72704:             $this->rollbackFileTransaction();
                   72705:             $this->configSet('default_channel', $savechannel);
                   72706:             return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
                   72707:         }
                   72708: 
                   72709:         // See if package already exists
                   72710:         $usechannel = $channel;
                   72711:         if ($channel == 'pecl.php.net') {
                   72712:             $test = $installregistry->packageExists($name, $channel);
                   72713:             if (!$test) {
                   72714:                 $test = $installregistry->packageExists($name, 'pear.php.net');
                   72715:                 $usechannel = 'pear.php.net';
                   72716:             }
                   72717:         } else {
                   72718:             $test = $installregistry->packageExists($name, $channel);
                   72719:         }
                   72720: 
                   72721:         $ret          = false;
                   72722:         $installphase = 'install';
                   72723:         $oldversion   = false;
                   72724:         // Register that the package is installed
                   72725:         if (empty($options['upgrade'])) {
                   72726:             // if 'force' is used, replace the info in registry
                   72727:             if (!empty($options['force']) && $test) {
                   72728:                 $oldversion = $installregistry->packageInfo($name, 'version', $usechannel);
                   72729:                 $installregistry->deletePackage($name, $usechannel);
                   72730:             }
                   72731:             $ret = $installregistry->addPackage2($pkg);
                   72732:         } else {
                   72733:             if ($dirtree) {
                   72734:                 $this->startFileTransaction();
                   72735:                 // attempt to delete empty directories
                   72736:                 uksort($dirtree, array($this, '_sortDirs'));
                   72737:                 foreach($dirtree as $dir => $notused) {
                   72738:                     $this->addFileOperation('rmdir', array($dir));
                   72739:                 }
                   72740:                 $this->commitFileTransaction();
                   72741:             }
                   72742: 
                   72743:             // new: upgrade installs a package if it isn't installed
                   72744:             if (!$test) {
                   72745:                 $ret = $installregistry->addPackage2($pkg);
                   72746:             } else {
                   72747:                 if ($usechannel != $channel) {
                   72748:                     $installregistry->deletePackage($name, $usechannel);
                   72749:                     $ret = $installregistry->addPackage2($pkg);
                   72750:                 } else {
                   72751:                     $ret = $installregistry->updatePackage2($pkg);
                   72752:                 }
                   72753:                 $installphase = 'upgrade';
                   72754:             }
                   72755:         }
                   72756: 
                   72757:         if (!$ret) {
                   72758:             $this->configSet('default_channel', $savechannel);
                   72759:             return $this->raiseError("Adding package $channel/$name to registry failed");
                   72760:         }
                   72761:         // }}}
                   72762: 
                   72763:         $this->configSet('default_channel', $savechannel);
                   72764:         if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
                   72765:             if (PEAR_Task_Common::hasPostinstallTasks()) {
                   72766:                 PEAR_Task_Common::runPostinstallTasks($installphase);
                   72767:             }
                   72768:         }
                   72769: 
                   72770:         return $pkg->toArray(true);
                   72771:     }
                   72772: 
                   72773:     /**
                   72774:      * @param string
                   72775:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   72776:      */
                   72777:     function _compileSourceFiles($savechannel, &$filelist, $configure_options = array())
                   72778:     {
                   72779:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Builder.php';
                   72780:         $this->log(1, "$this->source_files source files, building");
                   72781:         $bob = &new PEAR_Builder($this->ui);
                   72782:         $bob->debug = $this->debug;
                   72783:         $built = $bob->build($filelist, array(&$this, '_buildCallback'), $configure_options);
                   72784:         if (PEAR::isError($built)) {
                   72785:             $this->rollbackFileTransaction();
                   72786:             $this->configSet('default_channel', $savechannel);
                   72787:             return $built;
                   72788:         }
                   72789: 
                   72790:         $this->log(1, "\nBuild process completed successfully");
                   72791:         foreach ($built as $ext) {
                   72792:             $bn = basename($ext['file']);
                   72793:             list($_ext_name, $_ext_suff) = explode('.', $bn);
                   72794:             if ($_ext_suff == '.so' || $_ext_suff == '.dll') {
                   72795:                 if (extension_loaded($_ext_name)) {
                   72796:                     $this->raiseError("Extension '$_ext_name' already loaded. " .
                   72797:                                       'Please unload it in your php.ini file ' .
                   72798:                                       'prior to install or upgrade');
                   72799:                 }
                   72800:                 $role = 'ext';
                   72801:             } else {
                   72802:                 $role = 'src';
                   72803:             }
                   72804: 
                   72805:             $dest = $ext['dest'];
                   72806:             $packagingroot = '';
                   72807:             if (isset($this->_options['packagingroot'])) {
                   72808:                 $packagingroot = $this->_options['packagingroot'];
                   72809:             }
                   72810: 
                   72811:             $copyto = $this->_prependPath($dest, $packagingroot);
                   72812:             $extra  = $copyto != $dest ? " as '$copyto'" : '';
                   72813:             $this->log(1, "Installing '$dest'$extra");
                   72814: 
                   72815:             $copydir = dirname($copyto);
                   72816:             // pretty much nothing happens if we are only registering the install
                   72817:             if (empty($this->_options['register-only'])) {
                   72818:                 if (!file_exists($copydir) || !is_dir($copydir)) {
                   72819:                     if (!$this->mkDirHier($copydir)) {
                   72820:                         return $this->raiseError("failed to mkdir $copydir",
                   72821:                             PEAR_INSTALLER_FAILED);
                   72822:                     }
                   72823: 
                   72824:                     $this->log(3, "+ mkdir $copydir");
                   72825:                 }
                   72826: 
                   72827:                 if (!@copy($ext['file'], $copyto)) {
                   72828:                     return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED);
                   72829:                 }
                   72830: 
                   72831:                 $this->log(3, "+ cp $ext[file] $copyto");
                   72832:                 $this->addFileOperation('rename', array($ext['file'], $copyto));
                   72833:                 if (!OS_WINDOWS) {
                   72834:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   72835:                     $this->addFileOperation('chmod', array($mode, $copyto));
                   72836:                     if (!@chmod($copyto, $mode)) {
                   72837:                         $this->log(0, "failed to change mode of $copyto ($php_errormsg)");
                   72838:                     }
                   72839:                 }
                   72840:             }
                   72841: 
                   72842:             $data = array(
                   72843:                 'role'         => $role,
                   72844:                 'name'         => $bn,
                   72845:                 'installed_as' => $dest,
                   72846:                 'php_api'      => $ext['php_api'],
                   72847:                 'zend_mod_api' => $ext['zend_mod_api'],
                   72848:                 'zend_ext_api' => $ext['zend_ext_api'],
                   72849:             );
                   72850: 
                   72851:             if ($filelist->getPackageXmlVersion() == '1.0') {
                   72852:                 $filelist->installedFile($bn, $data);
                   72853:             } else {
                   72854:                 $filelist->installedFile($bn, array('attribs' => $data));
                   72855:             }
                   72856:         }
                   72857:     }
                   72858: 
                   72859:     function &getUninstallPackages()
                   72860:     {
                   72861:         return $this->_downloadedPackages;
                   72862:     }
                   72863: 
                   72864:     /**
                   72865:      * Uninstall a package
                   72866:      *
                   72867:      * This method removes all files installed by the application, and then
                   72868:      * removes any empty directories.
                   72869:      * @param string package name
                   72870:      * @param array Command-line options.  Possibilities include:
                   72871:      *
                   72872:      *              - installroot: base installation dir, if not the default
                   72873:      *              - register-only : update registry but don't remove files
                   72874:      *              - nodeps: do not process dependencies of other packages to ensure
                   72875:      *                        uninstallation does not break things
                   72876:      */
                   72877:     function uninstall($package, $options = array())
                   72878:     {
                   72879:         $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
                   72880:         $this->config->setInstallRoot($installRoot);
                   72881: 
                   72882:         $this->installroot = '';
                   72883:         $this->_registry = &$this->config->getRegistry();
                   72884:         if (is_object($package)) {
                   72885:             $channel = $package->getChannel();
                   72886:             $pkg     = $package;
                   72887:             $package = $pkg->getPackage();
                   72888:         } else {
                   72889:             $pkg = false;
                   72890:             $info = $this->_registry->parsePackageName($package,
                   72891:                 $this->config->get('default_channel'));
                   72892:             $channel = $info['channel'];
                   72893:             $package = $info['package'];
                   72894:         }
                   72895: 
                   72896:         $savechannel = $this->config->get('default_channel');
                   72897:         $this->configSet('default_channel', $channel);
                   72898:         if (!is_object($pkg)) {
                   72899:             $pkg = $this->_registry->getPackage($package, $channel);
                   72900:         }
                   72901: 
                   72902:         if (!$pkg) {
                   72903:             $this->configSet('default_channel', $savechannel);
                   72904:             return $this->raiseError($this->_registry->parsedPackageNameToString(
                   72905:                 array(
                   72906:                     'channel' => $channel,
                   72907:                     'package' => $package
                   72908:                 ), true) . ' not installed');
                   72909:         }
                   72910: 
                   72911:         if ($pkg->getInstalledBinary()) {
                   72912:             // this is just an alias for a binary package
                   72913:             return $this->_registry->deletePackage($package, $channel);
                   72914:         }
                   72915: 
                   72916:         $filelist = $pkg->getFilelist();
                   72917:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   72918:         if (!class_exists('PEAR_Dependency2')) {
                   72919:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   72920:         }
                   72921: 
                   72922:         $depchecker = &new PEAR_Dependency2($this->config, $options,
                   72923:             array('channel' => $channel, 'package' => $package),
                   72924:             PEAR_VALIDATE_UNINSTALLING);
                   72925:         $e = $depchecker->validatePackageUninstall($this);
                   72926:         PEAR::staticPopErrorHandling();
                   72927:         if (PEAR::isError($e)) {
                   72928:             if (!isset($options['ignore-errors'])) {
                   72929:                 return $this->raiseError($e);
                   72930:             }
                   72931: 
                   72932:             if (!isset($options['soft'])) {
                   72933:                 $this->log(0, 'WARNING: ' . $e->getMessage());
                   72934:             }
                   72935:         } elseif (is_array($e)) {
                   72936:             if (!isset($options['soft'])) {
                   72937:                 $this->log(0, $e[0]);
                   72938:             }
                   72939:         }
                   72940: 
                   72941:         $this->pkginfo = &$pkg;
                   72942:         // pretty much nothing happens if we are only registering the uninstall
                   72943:         if (empty($options['register-only'])) {
                   72944:             // Delete the files
                   72945:             $this->startFileTransaction();
                   72946:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   72947:             if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
                   72948:                 PEAR::popErrorHandling();
                   72949:                 $this->rollbackFileTransaction();
                   72950:                 $this->configSet('default_channel', $savechannel);
                   72951:                 if (!isset($options['ignore-errors'])) {
                   72952:                     return $this->raiseError($err);
                   72953:                 }
                   72954: 
                   72955:                 if (!isset($options['soft'])) {
                   72956:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   72957:                 }
                   72958:             } else {
                   72959:                 PEAR::popErrorHandling();
                   72960:             }
                   72961: 
                   72962:             if (!$this->commitFileTransaction()) {
                   72963:                 $this->rollbackFileTransaction();
                   72964:                 if (!isset($options['ignore-errors'])) {
                   72965:                     return $this->raiseError("uninstall failed");
                   72966:                 }
                   72967: 
                   72968:                 if (!isset($options['soft'])) {
                   72969:                     $this->log(0, 'WARNING: uninstall failed');
                   72970:                 }
                   72971:             } else {
                   72972:                 $this->startFileTransaction();
                   72973:                 $dirtree = $pkg->getDirTree();
                   72974:                 if ($dirtree === false) {
                   72975:                     $this->configSet('default_channel', $savechannel);
                   72976:                     return $this->_registry->deletePackage($package, $channel);
                   72977:                 }
                   72978: 
                   72979:                 // attempt to delete empty directories
                   72980:                 uksort($dirtree, array($this, '_sortDirs'));
                   72981:                 foreach($dirtree as $dir => $notused) {
                   72982:                     $this->addFileOperation('rmdir', array($dir));
                   72983:                 }
                   72984: 
                   72985:                 if (!$this->commitFileTransaction()) {
                   72986:                     $this->rollbackFileTransaction();
                   72987:                     if (!isset($options['ignore-errors'])) {
                   72988:                         return $this->raiseError("uninstall failed");
                   72989:                     }
                   72990: 
                   72991:                     if (!isset($options['soft'])) {
                   72992:                         $this->log(0, 'WARNING: uninstall failed');
                   72993:                     }
                   72994:                 }
                   72995:             }
                   72996:         }
                   72997: 
                   72998:         $this->configSet('default_channel', $savechannel);
                   72999:         // Register that the package is no longer installed
                   73000:         return $this->_registry->deletePackage($package, $channel);
                   73001:     }
                   73002: 
                   73003:     /**
                   73004:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   73005:      *
                   73006:      * It also removes duplicate dependencies
                   73007:      * @param array an array of PEAR_PackageFile_v[1/2] objects
                   73008:      * @return array|PEAR_Error array of array(packagefilename, package.xml contents)
                   73009:      */
                   73010:     function sortPackagesForUninstall(&$packages)
                   73011:     {
                   73012:         $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
                   73013:         if (PEAR::isError($this->_dependencyDB)) {
                   73014:             return $this->_dependencyDB;
                   73015:         }
                   73016:         usort($packages, array(&$this, '_sortUninstall'));
                   73017:     }
                   73018: 
                   73019:     function _sortUninstall($a, $b)
                   73020:     {
                   73021:         if (!$a->getDeps() && !$b->getDeps()) {
                   73022:             return 0; // neither package has dependencies, order is insignificant
                   73023:         }
                   73024:         if ($a->getDeps() && !$b->getDeps()) {
                   73025:             return -1; // $a must be installed after $b because $a has dependencies
                   73026:         }
                   73027:         if (!$a->getDeps() && $b->getDeps()) {
                   73028:             return 1; // $b must be installed after $a because $b has dependencies
                   73029:         }
                   73030:         // both packages have dependencies
                   73031:         if ($this->_dependencyDB->dependsOn($a, $b)) {
                   73032:             return -1;
                   73033:         }
                   73034:         if ($this->_dependencyDB->dependsOn($b, $a)) {
                   73035:             return 1;
                   73036:         }
                   73037:         return 0;
                   73038:     }
                   73039: 
                   73040:     function _sortDirs($a, $b)
                   73041:     {
                   73042:         if (strnatcmp($a, $b) == -1) return 1;
                   73043:         if (strnatcmp($a, $b) == 1) return -1;
                   73044:         return 0;
                   73045:     }
                   73046: 
                   73047:     function _buildCallback($what, $data)
                   73048:     {
                   73049:         if (($what == 'cmdoutput' && $this->debug > 1) ||
                   73050:             ($what == 'output' && $this->debug > 0)) {
                   73051:             $this->ui->outputData(rtrim($data), 'build');
                   73052:         }
                   73053:     }
                   73054: }<?php
                   73055: /**
                   73056:  * PEAR_Installer_Role
                   73057:  *
                   73058:  * PHP versions 4 and 5
                   73059:  *
                   73060:  * @category   pear
                   73061:  * @package    PEAR
                   73062:  * @author     Greg Beaver <cellog@php.net>
                   73063:  * @copyright  1997-2009 The Authors
                   73064:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73065:  * @version    CVS: $Id: Role.php 278552 2009-04-10 19:42:49Z dufuz $
                   73066:  * @link       http://pear.php.net/package/PEAR
                   73067:  * @since      File available since Release 1.4.0a1
                   73068:  */
                   73069: 
                   73070: /**
                   73071:  * base class for installer roles
                   73072:  */
                   73073: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role/Common.php';
                   73074: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   73075: /**
                   73076:  * @category   pear
                   73077:  * @package    PEAR
                   73078:  * @author     Greg Beaver <cellog@php.net>
                   73079:  * @copyright  1997-2009 The Authors
                   73080:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73081:  * @version    Release: 1.10.0beta1
                   73082:  * @link       http://pear.php.net/package/PEAR
                   73083:  * @since      Class available since Release 1.4.0a1
                   73084:  */
                   73085: class PEAR_Installer_Role
                   73086: {
                   73087:     /**
                   73088:      * Set up any additional configuration variables that file roles require
                   73089:      *
                   73090:      * Never call this directly, it is called by the PEAR_Config constructor
                   73091:      * @param PEAR_Config
                   73092:      * @access private
                   73093:      * @static
                   73094:      */
                   73095:     function initializeConfig(&$config)
                   73096:     {
                   73097:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73098:             PEAR_Installer_Role::registerRoles();
                   73099:         }
                   73100: 
                   73101:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
                   73102:             if (!$info['config_vars']) {
                   73103:                 continue;
                   73104:             }
                   73105: 
                   73106:             $config->_addConfigVars($class, $info['config_vars']);
                   73107:         }
                   73108:     }
                   73109: 
                   73110:     /**
                   73111:      * @param PEAR_PackageFile_v2
                   73112:      * @param string role name
                   73113:      * @param PEAR_Config
                   73114:      * @return PEAR_Installer_Role_Common
                   73115:      * @static
                   73116:      */
                   73117:     function &factory($pkg, $role, &$config)
                   73118:     {
                   73119:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73120:             PEAR_Installer_Role::registerRoles();
                   73121:         }
                   73122: 
                   73123:         if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
                   73124:             $a = false;
                   73125:             return $a;
                   73126:         }
                   73127: 
                   73128:         $a = 'PEAR_Installer_Role_' . ucfirst($role);
                   73129:         if (!class_exists($a)) {
                   73130:             require_once 'phar://install-pear-nozlib.phar/' . str_replace('_', '/', $a) . '.php';
                   73131:         }
                   73132: 
                   73133:         $b = new $a($config);
                   73134:         return $b;
                   73135:     }
                   73136: 
                   73137:     /**
                   73138:      * Get a list of file roles that are valid for the particular release type.
                   73139:      *
                   73140:      * For instance, src files serve no purpose in regular php releases.
                   73141:      * @param string
                   73142:      * @param bool clear cache
                   73143:      * @return array
                   73144:      * @static
                   73145:      */
                   73146:     function getValidRoles($release, $clear = false)
                   73147:     {
                   73148:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73149:             PEAR_Installer_Role::registerRoles();
                   73150:         }
                   73151: 
                   73152:         static $ret = array();
                   73153:         if ($clear) {
                   73154:             $ret = array();
                   73155:         }
                   73156: 
                   73157:         if (isset($ret[$release])) {
                   73158:             return $ret[$release];
                   73159:         }
                   73160: 
                   73161:         $ret[$release] = array();
                   73162:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   73163:             if (in_array($release, $okreleases['releasetypes'])) {
                   73164:                 $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   73165:             }
                   73166:         }
                   73167: 
                   73168:         return $ret[$release];
                   73169:     }
                   73170: 
                   73171:     /**
                   73172:      * Get a list of roles that require their files to be installed
                   73173:      *
                   73174:      * Most roles must be installed, but src and package roles, for instance
                   73175:      * are pseudo-roles.  src files are compiled into a new extension.  Package
                   73176:      * roles are actually fully bundled releases of a package
                   73177:      * @param bool clear cache
                   73178:      * @return array
                   73179:      * @static
                   73180:      */
                   73181:     function getInstallableRoles($clear = false)
                   73182:     {
                   73183:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73184:             PEAR_Installer_Role::registerRoles();
                   73185:         }
                   73186: 
                   73187:         static $ret;
                   73188:         if ($clear) {
                   73189:             unset($ret);
                   73190:         }
                   73191: 
                   73192:         if (isset($ret)) {
                   73193:             return $ret;
                   73194:         }
                   73195: 
                   73196:         $ret = array();
                   73197:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   73198:             if ($okreleases['installable']) {
                   73199:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   73200:             }
                   73201:         }
                   73202: 
                   73203:         return $ret;
                   73204:     }
                   73205: 
                   73206:     /**
                   73207:      * Return an array of roles that are affected by the baseinstalldir attribute
                   73208:      *
                   73209:      * Most roles ignore this attribute, and instead install directly into:
                   73210:      * PackageName/filepath
                   73211:      * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
                   73212:      * @param bool clear cache
                   73213:      * @return array
                   73214:      * @static
                   73215:      */
                   73216:     function getBaseinstallRoles($clear = false)
                   73217:     {
                   73218:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73219:             PEAR_Installer_Role::registerRoles();
                   73220:         }
                   73221: 
                   73222:         static $ret;
                   73223:         if ($clear) {
                   73224:             unset($ret);
                   73225:         }
                   73226: 
                   73227:         if (isset($ret)) {
                   73228:             return $ret;
                   73229:         }
                   73230: 
                   73231:         $ret = array();
                   73232:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   73233:             if ($okreleases['honorsbaseinstall']) {
                   73234:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   73235:             }
                   73236:         }
                   73237: 
                   73238:         return $ret;
                   73239:     }
                   73240: 
                   73241:     /**
                   73242:      * Return an array of file roles that should be analyzed for PHP content at package time,
                   73243:      * like the "php" role.
                   73244:      * @param bool clear cache
                   73245:      * @return array
                   73246:      * @static
                   73247:      */
                   73248:     function getPhpRoles($clear = false)
                   73249:     {
                   73250:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   73251:             PEAR_Installer_Role::registerRoles();
                   73252:         }
                   73253: 
                   73254:         static $ret;
                   73255:         if ($clear) {
                   73256:             unset($ret);
                   73257:         }
                   73258: 
                   73259:         if (isset($ret)) {
                   73260:             return $ret;
                   73261:         }
                   73262: 
                   73263:         $ret = array();
                   73264:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   73265:             if ($okreleases['phpfile']) {
                   73266:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   73267:             }
                   73268:         }
                   73269: 
                   73270:         return $ret;
                   73271:     }
                   73272: 
                   73273:     /**
                   73274:      * Scan through the Command directory looking for classes
                   73275:      * and see what commands they implement.
                   73276:      * @param string which directory to look for classes, defaults to
                   73277:      *               the Installer/Roles subdirectory of
                   73278:      *               the directory from where this file (__FILE__) is
                   73279:      *               included.
                   73280:      *
                   73281:      * @return bool TRUE on success, a PEAR error on failure
                   73282:      * @access public
                   73283:      * @static
                   73284:      */
                   73285:     function registerRoles($dir = null)
                   73286:     {
                   73287:         $GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
                   73288:         $parser = new PEAR_XMLParser;
                   73289:         if ($dir === null) {
                   73290:             $dir = dirname(__FILE__) . '/Role';
                   73291:         }
                   73292: 
                   73293:         if (!file_exists($dir) || !is_dir($dir)) {
                   73294:             return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
                   73295:         }
                   73296: 
                   73297:         $dp = @opendir($dir);
                   73298:         if (empty($dp)) {
                   73299:             return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
                   73300:         }
                   73301: 
                   73302:         while ($entry = readdir($dp)) {
                   73303:             if ($entry{0} == '.' || substr($entry, -4) != '.xml') {
                   73304:                 continue;
                   73305:             }
                   73306: 
                   73307:             $class = "PEAR_Installer_Role_".substr($entry, 0, -4);
                   73308:             // List of roles
                   73309:             if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
                   73310:                 $file = "$dir/$entry";
                   73311:                 $parser->parse(file_get_contents($file));
                   73312:                 $data = $parser->getData();
                   73313:                 if (!is_array($data['releasetypes'])) {
                   73314:                     $data['releasetypes'] = array($data['releasetypes']);
                   73315:                 }
                   73316: 
                   73317:                 $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
                   73318:             }
                   73319:         }
                   73320: 
                   73321:         closedir($dp);
                   73322:         ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
                   73323:         PEAR_Installer_Role::getBaseinstallRoles(true);
                   73324:         PEAR_Installer_Role::getInstallableRoles(true);
                   73325:         PEAR_Installer_Role::getPhpRoles(true);
                   73326:         PEAR_Installer_Role::getValidRoles('****', true);
                   73327:         return true;
                   73328:     }
                   73329: }<?php
                   73330: /**
                   73331:  * Base class for all installation roles.
                   73332:  *
                   73333:  * PHP versions 4 and 5
                   73334:  *
                   73335:  * @category   pear
                   73336:  * @package    PEAR
                   73337:  * @author     Greg Beaver <cellog@php.net>
                   73338:  * @copyright  1997-2006 The PHP Group
                   73339:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73340:  * @version    CVS: $Id: Common.php 312908 2011-07-04 19:43:30Z dufuz $
                   73341:  * @link       http://pear.php.net/package/PEAR
                   73342:  * @since      File available since Release 1.4.0a1
                   73343:  */
                   73344: /**
                   73345:  * Base class for all installation roles.
                   73346:  *
                   73347:  * This class allows extensibility of file roles.  Packages with complex
                   73348:  * customization can now provide custom file roles along with the possibility of
                   73349:  * adding configuration values to match.
                   73350:  * @category   pear
                   73351:  * @package    PEAR
                   73352:  * @author     Greg Beaver <cellog@php.net>
                   73353:  * @copyright  1997-2006 The PHP Group
                   73354:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73355:  * @version    Release: 1.10.0beta1
                   73356:  * @link       http://pear.php.net/package/PEAR
                   73357:  * @since      Class available since Release 1.4.0a1
                   73358:  */
                   73359: class PEAR_Installer_Role_Common
                   73360: {
                   73361:     /**
                   73362:      * @var PEAR_Config
                   73363:      * @access protected
                   73364:      */
                   73365:     var $config;
                   73366: 
                   73367:     /**
                   73368:      * @param PEAR_Config
                   73369:      */
                   73370:     function PEAR_Installer_Role_Common(&$config)
                   73371:     {
                   73372:         $this->config = $config;
                   73373:     }
                   73374: 
                   73375:     /**
                   73376:      * Retrieve configuration information about a file role from its XML info
                   73377:      *
                   73378:      * @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
                   73379:      * @return array
                   73380:      */
                   73381:     function getInfo($role)
                   73382:     {
                   73383:         if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
                   73384:             return PEAR::raiseError('Unknown Role class: "' . $role . '"');
                   73385:         }
                   73386:         return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
                   73387:     }
                   73388: 
                   73389:     /**
                   73390:      * This is called for each file to set up the directories and files
                   73391:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   73392:      * @param array attributes from the <file> tag
                   73393:      * @param string file name
                   73394:      * @return array an array consisting of:
                   73395:      *
                   73396:      *    1 the original, pre-baseinstalldir installation directory
                   73397:      *    2 the final installation directory
                   73398:      *    3 the full path to the final location of the file
                   73399:      *    4 the location of the pre-installation file
                   73400:      */
                   73401:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
                   73402:     {
                   73403:         $role = $this->getRoleFromClass();
                   73404:         $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
                   73405:         if (PEAR::isError($info)) {
                   73406:             return $info;
                   73407:         }
                   73408: 
                   73409:         if (!$info['locationconfig']) {
                   73410:             return false;
                   73411:         }
                   73412: 
                   73413:         if ($info['honorsbaseinstall']) {
                   73414:             $dest_dir = $save_destdir = $this->config->get($info['locationconfig'], $layer,
                   73415:                 $pkg->getChannel());
                   73416:             if (!empty($atts['baseinstalldir'])) {
                   73417:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   73418:             }
                   73419:         } elseif ($info['unusualbaseinstall']) {
                   73420:             $dest_dir = $save_destdir = $this->config->get($info['locationconfig'],
                   73421:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   73422:             if (!empty($atts['baseinstalldir'])) {
                   73423:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   73424:             }
                   73425:         } else {
                   73426:             $save_destdir = $dest_dir = $this->config->get($info['locationconfig'],
                   73427:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   73428:         }
                   73429: 
                   73430:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   73431:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   73432:         }
                   73433: 
                   73434:         if (empty($atts['install-as'])) {
                   73435:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   73436:         } else {
                   73437:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   73438:         }
                   73439: 
                   73440:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   73441: 
                   73442:         // Clean up the DIRECTORY_SEPARATOR mess
                   73443:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   73444: 
                   73445:         list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   73446:                                                     array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
                   73447:                                                           DIRECTORY_SEPARATOR),
                   73448:                                                     array($dest_dir, $dest_file, $orig_file));
                   73449: 
                   73450:         return array($save_destdir, $dest_dir, $dest_file, $orig_file);
                   73451:     }
                   73452: 
                   73453:     /**
                   73454:      * Get the name of the configuration variable that specifies the location of this file
                   73455:      * @return string|false
                   73456:      */
                   73457:     function getLocationConfig()
                   73458:     {
                   73459:         $role = ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))));
                   73460:         $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
                   73461:         if (PEAR::isError($info)) {
                   73462:             return $info;
                   73463:         }
                   73464: 
                   73465:         return $info['locationconfig'];
                   73466:     }
                   73467: 
                   73468:     /**
                   73469:      * Do any unusual setup here
                   73470:      * @param PEAR_Installer
                   73471:      * @param PEAR_PackageFile_v2
                   73472:      * @param array file attributes
                   73473:      * @param string file name
                   73474:      */
                   73475:     function setup(&$installer, $pkg, $atts, $file)
                   73476:     {
                   73477:     }
                   73478: 
                   73479:     function isExecutable()
                   73480:     {
                   73481:         $role = $this->getRoleFromClass();
                   73482:         $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
                   73483:         if (PEAR::isError($info)) {
                   73484:             return $info;
                   73485:         }
                   73486: 
                   73487:         return $info['executable'];
                   73488:     }
                   73489: 
                   73490:     function isInstallable()
                   73491:     {
                   73492:         $role = $this->getRoleFromClass();
                   73493:         $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
                   73494:         if (PEAR::isError($info)) {
                   73495:             return $info;
                   73496:         }
                   73497: 
                   73498:         return $info['installable'];
                   73499:     }
                   73500: 
                   73501:     function isExtension()
                   73502:     {
                   73503:         $role = $this->getRoleFromClass();
                   73504:         $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
                   73505:         if (PEAR::isError($info)) {
                   73506:             return $info;
                   73507:         }
                   73508: 
                   73509:         return $info['phpextension'];
                   73510:     }
                   73511: 
                   73512:     function getRoleFromClass()
                   73513:     {
                   73514:         $lower = strtolower(get_class($this));
                   73515:         return ucfirst(str_replace('pear_installer_role_', '', $lower));
                   73516:     }
                   73517: }<?php
                   73518: /**
                   73519:  * PEAR_Installer_Role_Data
                   73520:  *
                   73521:  * PHP versions 4 and 5
                   73522:  *
                   73523:  * @category   pear
                   73524:  * @package    PEAR
                   73525:  * @author     Greg Beaver <cellog@php.net>
                   73526:  * @copyright  1997-2009 The Authors
                   73527:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73528:  * @version    CVS: $Id: Data.php 276383 2009-02-24 23:39:37Z dufuz $
                   73529:  * @link       http://pear.php.net/package/PEAR
                   73530:  * @since      File available since Release 1.4.0a1
                   73531:  */
                   73532: 
                   73533: /**
                   73534:  * @category   pear
                   73535:  * @package    PEAR
                   73536:  * @author     Greg Beaver <cellog@php.net>
                   73537:  * @copyright  1997-2009 The Authors
                   73538:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73539:  * @version    Release: 1.10.0beta1
                   73540:  * @link       http://pear.php.net/package/PEAR
                   73541:  * @since      Class available since Release 1.4.0a1
                   73542:  */
                   73543: class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
                   73544: ?><role version="1.0">
                   73545:  <releasetypes>php</releasetypes>
                   73546:  <releasetypes>extsrc</releasetypes>
                   73547:  <releasetypes>extbin</releasetypes>
                   73548:  <releasetypes>zendextsrc</releasetypes>
                   73549:  <releasetypes>zendextbin</releasetypes>
                   73550:  <installable>1</installable>
                   73551:  <locationconfig>data_dir</locationconfig>
                   73552:  <honorsbaseinstall />
                   73553:  <unusualbaseinstall />
                   73554:  <phpfile />
                   73555:  <executable />
                   73556:  <phpextension />
                   73557:  <config_vars />
                   73558: </role><?php
                   73559: /**
                   73560:  * PEAR_Installer_Role_Doc
                   73561:  *
                   73562:  * PHP versions 4 and 5
                   73563:  *
                   73564:  * @category   pear
                   73565:  * @package    PEAR
                   73566:  * @author     Greg Beaver <cellog@php.net>
                   73567:  * @copyright  1997-2009 The Authors
                   73568:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73569:  * @version    CVS: $Id: Doc.php 276383 2009-02-24 23:39:37Z dufuz $
                   73570:  * @link       http://pear.php.net/package/PEAR
                   73571:  * @since      File available since Release 1.4.0a1
                   73572:  */
                   73573: 
                   73574: /**
                   73575:  * @category   pear
                   73576:  * @package    PEAR
                   73577:  * @author     Greg Beaver <cellog@php.net>
                   73578:  * @copyright  1997-2009 The Authors
                   73579:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73580:  * @version    Release: 1.10.0beta1
                   73581:  * @link       http://pear.php.net/package/PEAR
                   73582:  * @since      Class available since Release 1.4.0a1
                   73583:  */
                   73584: class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
                   73585: ?><role version="1.0">
                   73586:  <releasetypes>php</releasetypes>
                   73587:  <releasetypes>extsrc</releasetypes>
                   73588:  <releasetypes>extbin</releasetypes>
                   73589:  <releasetypes>zendextsrc</releasetypes>
                   73590:  <releasetypes>zendextbin</releasetypes>
                   73591:  <installable>1</installable>
                   73592:  <locationconfig>doc_dir</locationconfig>
                   73593:  <honorsbaseinstall />
                   73594:  <unusualbaseinstall />
                   73595:  <phpfile />
                   73596:  <executable />
                   73597:  <phpextension />
                   73598:  <config_vars />
                   73599: </role><?php
                   73600: /**
                   73601:  * PEAR_Installer_Role_Php
                   73602:  *
                   73603:  * PHP versions 4 and 5
                   73604:  *
                   73605:  * @category   pear
                   73606:  * @package    PEAR
                   73607:  * @author     Greg Beaver <cellog@php.net>
                   73608:  * @copyright  1997-2009 The Authors
                   73609:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73610:  * @version    CVS: $Id: Php.php 276383 2009-02-24 23:39:37Z dufuz $
                   73611:  * @link       http://pear.php.net/package/PEAR
                   73612:  * @since      File available since Release 1.4.0a1
                   73613:  */
                   73614: 
                   73615: /**
                   73616:  * @category   pear
                   73617:  * @package    PEAR
                   73618:  * @author     Greg Beaver <cellog@php.net>
                   73619:  * @copyright  1997-2009 The Authors
                   73620:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73621:  * @version    Release: 1.10.0beta1
                   73622:  * @link       http://pear.php.net/package/PEAR
                   73623:  * @since      Class available since Release 1.4.0a1
                   73624:  */
                   73625: class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
                   73626: ?><role version="1.0">
                   73627:  <releasetypes>php</releasetypes>
                   73628:  <releasetypes>extsrc</releasetypes>
                   73629:  <releasetypes>extbin</releasetypes>
                   73630:  <releasetypes>zendextsrc</releasetypes>
                   73631:  <releasetypes>zendextbin</releasetypes>
                   73632:  <installable>1</installable>
                   73633:  <locationconfig>php_dir</locationconfig>
                   73634:  <honorsbaseinstall>1</honorsbaseinstall>
                   73635:  <unusualbaseinstall />
                   73636:  <phpfile>1</phpfile>
                   73637:  <executable />
                   73638:  <phpextension />
                   73639:  <config_vars />
                   73640: </role><?php
                   73641: /**
                   73642:  * PEAR_Installer_Role_Script
                   73643:  *
                   73644:  * PHP versions 4 and 5
                   73645:  *
                   73646:  * @category   pear
                   73647:  * @package    PEAR
                   73648:  * @author     Greg Beaver <cellog@php.net>
                   73649:  * @copyright  1997-2009 The Authors
                   73650:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73651:  * @version    CVS: $Id: Script.php 276383 2009-02-24 23:39:37Z dufuz $
                   73652:  * @link       http://pear.php.net/package/PEAR
                   73653:  * @since      File available since Release 1.4.0a1
                   73654:  */
                   73655: 
                   73656: /**
                   73657:  * @category   pear
                   73658:  * @package    PEAR
                   73659:  * @author     Greg Beaver <cellog@php.net>
                   73660:  * @copyright  1997-2009 The Authors
                   73661:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73662:  * @version    Release: 1.10.0beta1
                   73663:  * @link       http://pear.php.net/package/PEAR
                   73664:  * @since      Class available since Release 1.4.0a1
                   73665:  */
                   73666: class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
                   73667: ?><role version="1.0">
                   73668:  <releasetypes>php</releasetypes>
                   73669:  <releasetypes>extsrc</releasetypes>
                   73670:  <releasetypes>extbin</releasetypes>
                   73671:  <releasetypes>zendextsrc</releasetypes>
                   73672:  <releasetypes>zendextbin</releasetypes>
                   73673:  <installable>1</installable>
                   73674:  <locationconfig>bin_dir</locationconfig>
                   73675:  <honorsbaseinstall>1</honorsbaseinstall>
                   73676:  <unusualbaseinstall />
                   73677:  <phpfile />
                   73678:  <executable>1</executable>
                   73679:  <phpextension />
                   73680:  <config_vars />
                   73681: </role><?php
                   73682: /**
                   73683:  * PEAR_Installer_Role_Test
                   73684:  *
                   73685:  * PHP versions 4 and 5
                   73686:  *
                   73687:  * @category   pear
                   73688:  * @package    PEAR
                   73689:  * @author     Greg Beaver <cellog@php.net>
                   73690:  * @copyright  1997-2009 The Authors
                   73691:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73692:  * @version    CVS: $Id: Test.php 276383 2009-02-24 23:39:37Z dufuz $
                   73693:  * @link       http://pear.php.net/package/PEAR
                   73694:  * @since      File available since Release 1.4.0a1
                   73695:  */
                   73696: 
                   73697: /**
                   73698:  * @category   pear
                   73699:  * @package    PEAR
                   73700:  * @author     Greg Beaver <cellog@php.net>
                   73701:  * @copyright  1997-2009 The Authors
                   73702:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73703:  * @version    Release: 1.10.0beta1
                   73704:  * @link       http://pear.php.net/package/PEAR
                   73705:  * @since      Class available since Release 1.4.0a1
                   73706:  */
                   73707: class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
                   73708: ?><role version="1.0">
                   73709:  <releasetypes>php</releasetypes>
                   73710:  <releasetypes>extsrc</releasetypes>
                   73711:  <releasetypes>extbin</releasetypes>
                   73712:  <releasetypes>zendextsrc</releasetypes>
                   73713:  <releasetypes>zendextbin</releasetypes>
                   73714:  <installable>1</installable>
                   73715:  <locationconfig>test_dir</locationconfig>
                   73716:  <honorsbaseinstall />
                   73717:  <unusualbaseinstall />
                   73718:  <phpfile />
                   73719:  <executable />
                   73720:  <phpextension />
                   73721:  <config_vars />
                   73722: </role><?php
                   73723: /**
                   73724:  * PEAR_PackageFile, package.xml parsing utility class
                   73725:  *
                   73726:  * PHP versions 4 and 5
                   73727:  *
                   73728:  * @category   pear
                   73729:  * @package    PEAR
                   73730:  * @author     Greg Beaver <cellog@php.net>
                   73731:  * @copyright  1997-2009 The Authors
                   73732:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73733:  * @version    CVS: $Id: PackageFile.php 312909 2011-07-04 19:49:14Z dufuz $
                   73734:  * @link       http://pear.php.net/package/PEAR
                   73735:  * @since      File available since Release 1.4.0a1
                   73736:  */
                   73737: 
                   73738: /**
                   73739:  * needed for PEAR_VALIDATE_* constants
                   73740:  */
                   73741: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   73742: /**
                   73743:  * Error code if the package.xml <package> tag does not contain a valid version
                   73744:  */
                   73745: define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
                   73746: /**
                   73747:  * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
                   73748:  * currently
                   73749:  */
                   73750: define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
                   73751: /**
                   73752:  * Abstraction for the package.xml package description file
                   73753:  *
                   73754:  * @category   pear
                   73755:  * @package    PEAR
                   73756:  * @author     Greg Beaver <cellog@php.net>
                   73757:  * @copyright  1997-2009 The Authors
                   73758:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   73759:  * @version    Release: 1.10.0beta1
                   73760:  * @link       http://pear.php.net/package/PEAR
                   73761:  * @since      Class available since Release 1.4.0a1
                   73762:  */
                   73763: class PEAR_PackageFile
                   73764: {
                   73765:     /**
                   73766:      * @var PEAR_Config
                   73767:      */
                   73768:     var $_config;
                   73769:     var $_debug;
                   73770: 
                   73771:     var $_logger = false;
                   73772:     /**
                   73773:      * @var boolean
                   73774:      */
                   73775:     var $_rawReturn = false;
                   73776: 
                   73777:     /**
                   73778:      * helper for extracting Archive_Tar errors
                   73779:      * @var array
                   73780:      * @access private
                   73781:      */
                   73782:     var $_extractErrors = array();
                   73783: 
                   73784:     /**
                   73785:      *
                   73786:      * @param   PEAR_Config $config
                   73787:      * @param   ?   $debug
                   73788:      * @param   string @tmpdir Optional temporary directory for uncompressing
                   73789:      *          files
                   73790:      */
                   73791:     function PEAR_PackageFile(&$config, $debug = false)
                   73792:     {
                   73793:         $this->_config = $config;
                   73794:         $this->_debug = $debug;
                   73795:     }
                   73796: 
                   73797:     /**
                   73798:      * Turn off validation - return a parsed package.xml without checking it
                   73799:      *
                   73800:      * This is used by the package-validate command
                   73801:      */
                   73802:     function rawReturn()
                   73803:     {
                   73804:         $this->_rawReturn = true;
                   73805:     }
                   73806: 
                   73807:     function setLogger(&$l)
                   73808:     {
                   73809:         $this->_logger = &$l;
                   73810:     }
                   73811: 
                   73812:     /**
                   73813:      * Create a PEAR_PackageFile_Parser_v* of a given version.
                   73814:      * @param   int $version
                   73815:      * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
                   73816:      */
                   73817:     function &parserFactory($version)
                   73818:     {
                   73819:         if (!in_array($version{0}, array('1', '2'))) {
                   73820:             $a = false;
                   73821:             return $a;
                   73822:         }
                   73823: 
                   73824:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
                   73825:         $version = $version{0};
                   73826:         $class = "PEAR_PackageFile_Parser_v$version";
                   73827:         $a = new $class;
                   73828:         return $a;
                   73829:     }
                   73830: 
                   73831:     /**
                   73832:      * For simpler unit-testing
                   73833:      * @return string
                   73834:      */
                   73835:     function getClassPrefix()
                   73836:     {
                   73837:         return 'PEAR_PackageFile_v';
                   73838:     }
                   73839: 
                   73840:     /**
                   73841:      * Create a PEAR_PackageFile_v* of a given version.
                   73842:      * @param   int $version
                   73843:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
                   73844:      */
                   73845:     function &factory($version)
                   73846:     {
                   73847:         if (!in_array($version{0}, array('1', '2'))) {
                   73848:             $a = false;
                   73849:             return $a;
                   73850:         }
                   73851: 
                   73852:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v' . $version{0} . '.php';
                   73853:         $version = $version{0};
                   73854:         $class = $this->getClassPrefix() . $version;
                   73855:         $a = new $class;
                   73856:         return $a;
                   73857:     }
                   73858: 
                   73859:     /**
                   73860:      * Create a PEAR_PackageFile_v* from its toArray() method
                   73861:      *
                   73862:      * WARNING: no validation is performed, the array is assumed to be valid,
                   73863:      * always parse from xml if you want validation.
                   73864:      * @param   array $arr
                   73865:      * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
                   73866:      * @uses    factory() to construct the returned object.
                   73867:      */
                   73868:     function &fromArray($arr)
                   73869:     {
                   73870:         if (isset($arr['xsdversion'])) {
                   73871:             $obj = &$this->factory($arr['xsdversion']);
                   73872:             if ($this->_logger) {
                   73873:                 $obj->setLogger($this->_logger);
                   73874:             }
                   73875: 
                   73876:             $obj->setConfig($this->_config);
                   73877:             $obj->fromArray($arr);
                   73878:             return $obj;
                   73879:         }
                   73880: 
                   73881:         if (isset($arr['package']['attribs']['version'])) {
                   73882:             $obj = &$this->factory($arr['package']['attribs']['version']);
                   73883:         } else {
                   73884:             $obj = &$this->factory('1.0');
                   73885:         }
                   73886: 
                   73887:         if ($this->_logger) {
                   73888:             $obj->setLogger($this->_logger);
                   73889:         }
                   73890: 
                   73891:         $obj->setConfig($this->_config);
                   73892:         $obj->fromArray($arr);
                   73893:         return $obj;
                   73894:     }
                   73895: 
                   73896:     /**
                   73897:      * Create a PEAR_PackageFile_v* from an XML string.
                   73898:      * @access  public
                   73899:      * @param   string $data contents of package.xml file
                   73900:      * @param   int $state package state (one of PEAR_VALIDATE_* constants)
                   73901:      * @param   string $file full path to the package.xml file (and the files
                   73902:      *          it references)
                   73903:      * @param   string $archive optional name of the archive that the XML was
                   73904:      *          extracted from, if any
                   73905:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   73906:      * @uses    parserFactory() to construct a parser to load the package.
                   73907:      */
                   73908:     function &fromXmlString($data, $state, $file, $archive = false)
                   73909:     {
                   73910:         if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
                   73911:             if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
                   73912:                 return PEAR::raiseError('package.xml version "' . $packageversion[1] .
                   73913:                     '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
                   73914:             }
                   73915: 
                   73916:             $object = &$this->parserFactory($packageversion[1]);
                   73917:             if ($this->_logger) {
                   73918:                 $object->setLogger($this->_logger);
                   73919:             }
                   73920: 
                   73921:             $object->setConfig($this->_config);
                   73922:             $pf = $object->parse($data, $file, $archive);
                   73923:             if (PEAR::isError($pf)) {
                   73924:                 return $pf;
                   73925:             }
                   73926: 
                   73927:             if ($this->_rawReturn) {
                   73928:                 return $pf;
                   73929:             }
                   73930: 
                   73931:             if (!$pf->validate($state)) {;
                   73932:                 if ($this->_config->get('verbose') > 0
                   73933:                     && $this->_logger && $pf->getValidationWarnings(false)
                   73934:                 ) {
                   73935:                     foreach ($pf->getValidationWarnings(false) as $warning) {
                   73936:                         $this->_logger->log(0, 'ERROR: ' . $warning['message']);
                   73937:                     }
                   73938:                 }
                   73939: 
                   73940:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   73941:                     2, null, null, $pf->getValidationWarnings());
                   73942:                 return $a;
                   73943:             }
                   73944: 
                   73945:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   73946:                 foreach ($pf->getValidationWarnings() as $warning) {
                   73947:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   73948:                 }
                   73949:             }
                   73950: 
                   73951:             if (method_exists($pf, 'flattenFilelist')) {
                   73952:                 $pf->flattenFilelist(); // for v2
                   73953:             }
                   73954: 
                   73955:             return $pf;
                   73956:         } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
                   73957:             $a = PEAR::raiseError('package.xml file "' . $file .
                   73958:                 '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
                   73959:             return $a;
                   73960:         } else {
                   73961:             if (!class_exists('PEAR_ErrorStack')) {
                   73962:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
                   73963:             }
                   73964: 
                   73965:             PEAR_ErrorStack::staticPush('PEAR_PackageFile',
                   73966:                 PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
                   73967:                 'warning', array('xml' => $data), 'package.xml "' . $file .
                   73968:                     '" has no package.xml <package> version');
                   73969:             $object = &$this->parserFactory('1.0');
                   73970:             $object->setConfig($this->_config);
                   73971:             $pf = $object->parse($data, $file, $archive);
                   73972:             if (PEAR::isError($pf)) {
                   73973:                 return $pf;
                   73974:             }
                   73975: 
                   73976:             if ($this->_rawReturn) {
                   73977:                 return $pf;
                   73978:             }
                   73979: 
                   73980:             if (!$pf->validate($state)) {
                   73981:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   73982:                     2, null, null, $pf->getValidationWarnings());
                   73983:                 return $a;
                   73984:             }
                   73985: 
                   73986:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   73987:                 foreach ($pf->getValidationWarnings() as $warning) {
                   73988:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   73989:                 }
                   73990:             }
                   73991: 
                   73992:             if (method_exists($pf, 'flattenFilelist')) {
                   73993:                 $pf->flattenFilelist(); // for v2
                   73994:             }
                   73995: 
                   73996:             return $pf;
                   73997:         }
                   73998:     }
                   73999: 
                   74000:     /**
                   74001:      * Register a temporary file or directory.  When the destructor is
                   74002:      * executed, all registered temporary files and directories are
                   74003:      * removed.
                   74004:      *
                   74005:      * @param string  $file  name of file or directory
                   74006:      * @return  void
                   74007:      */
                   74008:     function addTempFile($file)
                   74009:     {
                   74010:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   74011:     }
                   74012: 
                   74013:     /**
                   74014:      * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
                   74015:      * @access  public
                   74016:      * @param string contents of package.xml file
                   74017:      * @param int package state (one of PEAR_VALIDATE_* constants)
                   74018:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   74019:      * @using   Archive_Tar to extract the files
                   74020:      * @using   fromPackageFile() to load the package after the package.xml
                   74021:      *          file is extracted.
                   74022:      */
                   74023:     function &fromTgzFile($file, $state)
                   74024:     {
                   74025:         if (!class_exists('Archive_Tar')) {
                   74026:             require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
                   74027:         }
                   74028: 
                   74029:         $tar = new Archive_Tar($file);
                   74030:         if ($this->_debug <= 1) {
                   74031:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   74032:         }
                   74033: 
                   74034:         $content = $tar->listContent();
                   74035:         if ($this->_debug <= 1) {
                   74036:             $tar->popErrorHandling();
                   74037:         }
                   74038: 
                   74039:         if (!is_array($content)) {
                   74040:             if (is_string($file) && strlen($file < 255) &&
                   74041:                   (!file_exists($file) || !@is_file($file))) {
                   74042:                 $ret = PEAR::raiseError("could not open file \"$file\"");
                   74043:                 return $ret;
                   74044:             }
                   74045: 
                   74046:             $file = realpath($file);
                   74047:             $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                   74048:                                      '. Invalid tgz file.');
                   74049:             return $ret;
                   74050:         }
                   74051: 
                   74052:         if (!count($content) && !@is_file($file)) {
                   74053:             $ret = PEAR::raiseError("could not open file \"$file\"");
                   74054:             return $ret;
                   74055:         }
                   74056: 
                   74057:         $xml      = null;
                   74058:         $origfile = $file;
                   74059:         foreach ($content as $file) {
                   74060:             $name = $file['filename'];
                   74061:             if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
                   74062:                 $xml = $name;
                   74063:                 break;
                   74064:             }
                   74065: 
                   74066:             if ($name == 'package.xml') {
                   74067:                 $xml = $name;
                   74068:                 break;
                   74069:             } elseif (preg_match('/package.xml$/', $name, $match)) {
                   74070:                 $xml = $name;
                   74071:                 break;
                   74072:             }
                   74073:         }
                   74074: 
                   74075:         $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
                   74076:         if ($tmpdir === false) {
                   74077:             $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
                   74078:             return $ret;
                   74079:         }
                   74080: 
                   74081:         PEAR_PackageFile::addTempFile($tmpdir);
                   74082: 
                   74083:         $this->_extractErrors();
                   74084:         PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
                   74085: 
                   74086:         if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
                   74087:             $extra = implode("\n", $this->_extractErrors());
                   74088:             if ($extra) {
                   74089:                 $extra = ' ' . $extra;
                   74090:             }
                   74091: 
                   74092:             PEAR::staticPopErrorHandling();
                   74093:             $ret = PEAR::raiseError('could not extract the package.xml file from "' .
                   74094:                 $origfile . '"' . $extra);
                   74095:             return $ret;
                   74096:         }
                   74097: 
                   74098:         PEAR::staticPopErrorHandling();
                   74099:         $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
                   74100:         return $ret;
                   74101:     }
                   74102: 
                   74103:     /**
                   74104:      * helper callback for extracting Archive_Tar errors
                   74105:      *
                   74106:      * @param PEAR_Error|null $err
                   74107:      * @return array
                   74108:      * @access private
                   74109:      */
                   74110:     function _extractErrors($err = null)
                   74111:     {
                   74112:         static $errors = array();
                   74113:         if ($err === null) {
                   74114:             $e = $errors;
                   74115:             $errors = array();
                   74116:             return $e;
                   74117:         }
                   74118:         $errors[] = $err->getMessage();
                   74119:     }
                   74120: 
                   74121:     /**
                   74122:      * Create a PEAR_PackageFile_v* from a package.xml file.
                   74123:      *
                   74124:      * @access public
                   74125:      * @param   string  $descfile  name of package xml file
                   74126:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   74127:      * @param   string|false $archive name of the archive this package.xml came
                   74128:      *          from, if any
                   74129:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   74130:      * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
                   74131:      *          XML is loaded from the package.xml file.
                   74132:      */
                   74133:     function &fromPackageFile($descfile, $state, $archive = false)
                   74134:     {
                   74135:         $fp = false;
                   74136:         if (is_string($descfile) && strlen($descfile) < 255 &&
                   74137:              (
                   74138:               !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
                   74139:               || (!$fp = @fopen($descfile, 'r'))
                   74140:              )
                   74141:         ) {
                   74142:             $a = PEAR::raiseError("Unable to open $descfile");
                   74143:             return $a;
                   74144:         }
                   74145: 
                   74146:         // read the whole thing so we only get one cdata callback
                   74147:         // for each block of cdata
                   74148:         fclose($fp);
                   74149:         $data = file_get_contents($descfile);
                   74150:         $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
                   74151:         return $ret;
                   74152:     }
                   74153: 
                   74154:     /**
                   74155:      * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
                   74156:      *
                   74157:      * This method is able to extract information about a package from a .tgz
                   74158:      * archive or from a XML package definition file.
                   74159:      *
                   74160:      * @access public
                   74161:      * @param   string  $info file name
                   74162:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   74163:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   74164:      * @uses    fromPackageFile() if the file appears to be XML
                   74165:      * @uses    fromTgzFile() to load all non-XML files
                   74166:      */
                   74167:     function &fromAnyFile($info, $state)
                   74168:     {
                   74169:         if (is_dir($info)) {
                   74170:             $dir_name = realpath($info);
                   74171:             if (file_exists($dir_name . '/package.xml')) {
                   74172:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
                   74173:             } elseif (file_exists($dir_name .  '/package2.xml')) {
                   74174:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
                   74175:             } else {
                   74176:                 $info = PEAR::raiseError("No package definition found in '$info' directory");
                   74177:             }
                   74178: 
                   74179:             return $info;
                   74180:         }
                   74181: 
                   74182:         $fp = false;
                   74183:         if (is_string($info) && strlen($info) < 255 &&
                   74184:              (file_exists($info) || ($fp = @fopen($info, 'r')))
                   74185:         ) {
                   74186: 
                   74187:             if ($fp) {
                   74188:                 fclose($fp);
                   74189:             }
                   74190: 
                   74191:             $tmp = substr($info, -4);
                   74192:             if ($tmp == '.xml') {
                   74193:                 $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   74194:             } elseif ($tmp == '.tar' || $tmp == '.tgz') {
                   74195:                 $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   74196:             } else {
                   74197:                 $fp   = fopen($info, 'r');
                   74198:                 $test = fread($fp, 5);
                   74199:                 fclose($fp);
                   74200:                 if ($test == '<?xml') {
                   74201:                     $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   74202:                 } else {
                   74203:                     $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   74204:                 }
                   74205:             }
                   74206: 
                   74207:             return $info;
                   74208:         }
                   74209: 
                   74210:         $info = PEAR::raiseError("Cannot open '$info' for parsing");
                   74211:         return $info;
                   74212:     }
                   74213: }<?php
                   74214: /**
                   74215:  * package.xml generation class, package.xml version 1.0
                   74216:  *
                   74217:  * PHP versions 4 and 5
                   74218:  *
                   74219:  * @category   pear
                   74220:  * @package    PEAR
                   74221:  * @author     Greg Beaver <cellog@php.net>
                   74222:  * @copyright  1997-2009 The Authors
                   74223:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   74224:  * @version    CVS: $Id: v1.php 286494 2009-07-29 06:57:11Z dufuz $
                   74225:  * @link       http://pear.php.net/package/PEAR
                   74226:  * @since      File available since Release 1.4.0a1
                   74227:  */
                   74228: /**
                   74229:  * needed for PEAR_VALIDATE_* constants
                   74230:  */
                   74231: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   74232: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   74233: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   74234: /**
                   74235:  * This class converts a PEAR_PackageFile_v1 object into any output format.
                   74236:  *
                   74237:  * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
                   74238:  * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
                   74239:  * @category   pear
                   74240:  * @package    PEAR
                   74241:  * @author     Greg Beaver <cellog@php.net>
                   74242:  * @copyright  1997-2009 The Authors
                   74243:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   74244:  * @version    Release: 1.10.0beta1
                   74245:  * @link       http://pear.php.net/package/PEAR
                   74246:  * @since      Class available since Release 1.4.0a1
                   74247:  */
                   74248: class PEAR_PackageFile_Generator_v1
                   74249: {
                   74250:     /**
                   74251:      * @var PEAR_PackageFile_v1
                   74252:      */
                   74253:     var $_packagefile;
                   74254:     function PEAR_PackageFile_Generator_v1(&$packagefile)
                   74255:     {
                   74256:         $this->_packagefile = &$packagefile;
                   74257:     }
                   74258: 
                   74259:     function getPackagerVersion()
                   74260:     {
                   74261:         return '1.10.0beta1';
                   74262:     }
                   74263: 
                   74264:     /**
                   74265:      * @param PEAR_Packager
                   74266:      * @param bool if true, a .tgz is written, otherwise a .tar is written
                   74267:      * @param string|null directory in which to save the .tgz
                   74268:      * @return string|PEAR_Error location of package or error object
                   74269:      */
                   74270:     function toTgz(&$packager, $compress = true, $where = null)
                   74271:     {
                   74272:         require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
                   74273:         if ($where === null) {
                   74274:             if (!($where = System::mktemp(array('-d')))) {
                   74275:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
                   74276:             }
                   74277:         } elseif (!@System::mkDir(array('-p', $where))) {
                   74278:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
                   74279:                 ' not be created');
                   74280:         }
                   74281:         if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
                   74282:               !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
                   74283:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
                   74284:                 ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
                   74285:         }
                   74286:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   74287:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
                   74288:         }
                   74289:         $pkginfo = $this->_packagefile->getArray();
                   74290:         $ext = $compress ? '.tgz' : '.tar';
                   74291:         $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
                   74292:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   74293:         if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
                   74294:               !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
                   74295:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
                   74296:                 getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
                   74297:         }
                   74298:         if ($pkgfile = $this->_packagefile->getPackageFile()) {
                   74299:             $pkgdir = dirname(realpath($pkgfile));
                   74300:             $pkgfile = basename($pkgfile);
                   74301:         } else {
                   74302:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
                   74303:                 'be created from a real file');
                   74304:         }
                   74305:         // {{{ Create the package file list
                   74306:         $filelist = array();
                   74307:         $i = 0;
                   74308: 
                   74309:         foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
                   74310:             $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   74311:             if (!file_exists($file)) {
                   74312:                 return PEAR::raiseError("File does not exist: $fname");
                   74313:             } else {
                   74314:                 $filelist[$i++] = $file;
                   74315:                 if (!isset($atts['md5sum'])) {
                   74316:                     $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
                   74317:                 }
                   74318:                 $packager->log(2, "Adding file $fname");
                   74319:             }
                   74320:         }
                   74321:         // }}}
                   74322:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   74323:         if ($packagexml) {
                   74324:             $tar =& new Archive_Tar($dest_package, $compress);
                   74325:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   74326:             // ----- Creates with the package.xml file
                   74327:             $ok = $tar->createModify(array($packagexml), '', $where);
                   74328:             if (PEAR::isError($ok)) {
                   74329:                 return $ok;
                   74330:             } elseif (!$ok) {
                   74331:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   74332:             }
                   74333:             // ----- Add the content of the package
                   74334:             if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
                   74335:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   74336:             }
                   74337:             return $dest_package;
                   74338:         }
                   74339:     }
                   74340: 
                   74341:     /**
                   74342:      * @param string|null directory to place the package.xml in, or null for a temporary dir
                   74343:      * @param int one of the PEAR_VALIDATE_* constants
                   74344:      * @param string name of the generated file
                   74345:      * @param bool if true, then no analysis will be performed on role="php" files
                   74346:      * @return string|PEAR_Error path to the created file on success
                   74347:      */
                   74348:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
                   74349:                            $nofilechecking = false)
                   74350:     {
                   74351:         if (!$this->_packagefile->validate($state, $nofilechecking)) {
                   74352:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
                   74353:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   74354:         }
                   74355:         if ($where === null) {
                   74356:             if (!($where = System::mktemp(array('-d')))) {
                   74357:                 return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
                   74358:             }
                   74359:         } elseif (!@System::mkDir(array('-p', $where))) {
                   74360:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
                   74361:                 ' not be created');
                   74362:         }
                   74363:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   74364:         $np = @fopen($newpkgfile, 'wb');
                   74365:         if (!$np) {
                   74366:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
                   74367:                "$name as $newpkgfile");
                   74368:         }
                   74369:         fwrite($np, $this->toXml($state, true));
                   74370:         fclose($np);
                   74371:         return $newpkgfile;
                   74372:     }
                   74373: 
                   74374:     /**
                   74375:      * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
                   74376:      *
                   74377:      * @param string $string
                   74378:      * @return string
                   74379:      * @access private
                   74380:      */
                   74381:     function _fixXmlEncoding($string)
                   74382:     {
                   74383:         if (version_compare(phpversion(), '5.0.0', 'lt')) {
                   74384:             $string = utf8_encode($string);
                   74385:         }
                   74386:         return strtr($string, array(
                   74387:                                           '&'  => '&amp;',
                   74388:                                           '>'  => '&gt;',
                   74389:                                           '<'  => '&lt;',
                   74390:                                           '"'  => '&quot;',
                   74391:                                           '\'' => '&apos;' ));
                   74392:     }
                   74393: 
                   74394:     /**
                   74395:      * Return an XML document based on the package info (as returned
                   74396:      * by the PEAR_Common::infoFrom* methods).
                   74397:      *
                   74398:      * @return string XML data
                   74399:      */
                   74400:     function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
                   74401:     {
                   74402:         $this->_packagefile->setDate(date('Y-m-d'));
                   74403:         if (!$this->_packagefile->validate($state, $nofilevalidation)) {
                   74404:             return false;
                   74405:         }
                   74406:         $pkginfo = $this->_packagefile->getArray();
                   74407:         static $maint_map = array(
                   74408:             "handle" => "user",
                   74409:             "name" => "name",
                   74410:             "email" => "email",
                   74411:             "role" => "role",
                   74412:             );
                   74413:         $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
                   74414:         $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
                   74415:         $ret .= "<package version=\"1.0\" packagerversion=\"1.10.0beta1\">\n" .
                   74416: " <name>$pkginfo[package]</name>";
                   74417:         if (isset($pkginfo['extends'])) {
                   74418:             $ret .= "\n<extends>$pkginfo[extends]</extends>";
                   74419:         }
                   74420:         $ret .=
                   74421:  "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
                   74422: " <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
                   74423: " <maintainers>\n";
                   74424:         foreach ($pkginfo['maintainers'] as $maint) {
                   74425:             $ret .= "  <maintainer>\n";
                   74426:             foreach ($maint_map as $idx => $elm) {
                   74427:                 $ret .= "   <$elm>";
                   74428:                 $ret .= $this->_fixXmlEncoding($maint[$idx]);
                   74429:                 $ret .= "</$elm>\n";
                   74430:             }
                   74431:             $ret .= "  </maintainer>\n";
                   74432:         }
                   74433:         $ret .= "  </maintainers>\n";
                   74434:         $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
                   74435:         if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
                   74436:             $ret .= " <changelog>\n";
                   74437:             foreach ($pkginfo['changelog'] as $oldrelease) {
                   74438:                 $ret .= $this->_makeReleaseXml($oldrelease, true);
                   74439:             }
                   74440:             $ret .= " </changelog>\n";
                   74441:         }
                   74442:         $ret .= "</package>\n";
                   74443:         return $ret;
                   74444:     }
                   74445: 
                   74446:     // }}}
                   74447:     // {{{ _makeReleaseXml()
                   74448: 
                   74449:     /**
                   74450:      * Generate part of an XML description with release information.
                   74451:      *
                   74452:      * @param array  $pkginfo    array with release information
                   74453:      * @param bool   $changelog  whether the result will be in a changelog element
                   74454:      *
                   74455:      * @return string XML data
                   74456:      *
                   74457:      * @access private
                   74458:      */
                   74459:     function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
                   74460:     {
                   74461:         // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
                   74462:         $indent = $changelog ? "  " : "";
                   74463:         $ret = "$indent <release>\n";
                   74464:         if (!empty($pkginfo['version'])) {
                   74465:             $ret .= "$indent  <version>$pkginfo[version]</version>\n";
                   74466:         }
                   74467:         if (!empty($pkginfo['release_date'])) {
                   74468:             $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
                   74469:         }
                   74470:         if (!empty($pkginfo['release_license'])) {
                   74471:             $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
                   74472:         }
                   74473:         if (!empty($pkginfo['release_state'])) {
                   74474:             $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
                   74475:         }
                   74476:         if (!empty($pkginfo['release_notes'])) {
                   74477:             $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
                   74478:             ."\n$indent  </notes>\n";
                   74479:         }
                   74480:         if (!empty($pkginfo['release_warnings'])) {
                   74481:             $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
                   74482:         }
                   74483:         if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
                   74484:             $ret .= "$indent  <deps>\n";
                   74485:             foreach ($pkginfo['release_deps'] as $dep) {
                   74486:                 $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
                   74487:                 if (isset($dep['version'])) {
                   74488:                     $ret .= " version=\"$dep[version]\"";
                   74489:                 }
                   74490:                 if (isset($dep['optional'])) {
                   74491:                     $ret .= " optional=\"$dep[optional]\"";
                   74492:                 }
                   74493:                 if (isset($dep['name'])) {
                   74494:                     $ret .= ">$dep[name]</dep>\n";
                   74495:                 } else {
                   74496:                     $ret .= "/>\n";
                   74497:                 }
                   74498:             }
                   74499:             $ret .= "$indent  </deps>\n";
                   74500:         }
                   74501:         if (isset($pkginfo['configure_options'])) {
                   74502:             $ret .= "$indent  <configureoptions>\n";
                   74503:             foreach ($pkginfo['configure_options'] as $c) {
                   74504:                 $ret .= "$indent   <configureoption name=\"".
                   74505:                     $this->_fixXmlEncoding($c['name']) . "\"";
                   74506:                 if (isset($c['default'])) {
                   74507:                     $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
                   74508:                 }
                   74509:                 $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
                   74510:                 $ret .= "/>\n";
                   74511:             }
                   74512:             $ret .= "$indent  </configureoptions>\n";
                   74513:         }
                   74514:         if (isset($pkginfo['provides'])) {
                   74515:             foreach ($pkginfo['provides'] as $key => $what) {
                   74516:                 $ret .= "$indent  <provides type=\"$what[type]\" ";
                   74517:                 $ret .= "name=\"$what[name]\" ";
                   74518:                 if (isset($what['extends'])) {
                   74519:                     $ret .= "extends=\"$what[extends]\" ";
                   74520:                 }
                   74521:                 $ret .= "/>\n";
                   74522:             }
                   74523:         }
                   74524:         if (isset($pkginfo['filelist'])) {
                   74525:             $ret .= "$indent  <filelist>\n";
                   74526:             if ($state ^ PEAR_VALIDATE_PACKAGING) {
                   74527:                 $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
                   74528:             } else {
                   74529:                 foreach ($pkginfo['filelist'] as $file => $fa) {
                   74530:                     if (!isset($fa['role'])) {
                   74531:                         $fa['role'] = '';
                   74532:                     }
                   74533:                     $ret .= "$indent   <file role=\"$fa[role]\"";
                   74534:                     if (isset($fa['baseinstalldir'])) {
                   74535:                         $ret .= ' baseinstalldir="' .
                   74536:                             $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
                   74537:                     }
                   74538:                     if (isset($fa['md5sum'])) {
                   74539:                         $ret .= " md5sum=\"$fa[md5sum]\"";
                   74540:                     }
                   74541:                     if (isset($fa['platform'])) {
                   74542:                         $ret .= " platform=\"$fa[platform]\"";
                   74543:                     }
                   74544:                     if (!empty($fa['install-as'])) {
                   74545:                         $ret .= ' install-as="' .
                   74546:                             $this->_fixXmlEncoding($fa['install-as']) . '"';
                   74547:                     }
                   74548:                     $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   74549:                     if (empty($fa['replacements'])) {
                   74550:                         $ret .= "/>\n";
                   74551:                     } else {
                   74552:                         $ret .= ">\n";
                   74553:                         foreach ($fa['replacements'] as $r) {
                   74554:                             $ret .= "$indent    <replace";
                   74555:                             foreach ($r as $k => $v) {
                   74556:                                 $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   74557:                             }
                   74558:                             $ret .= "/>\n";
                   74559:                         }
                   74560:                         $ret .= "$indent   </file>\n";
                   74561:                     }
                   74562:                 }
                   74563:             }
                   74564:             $ret .= "$indent  </filelist>\n";
                   74565:         }
                   74566:         $ret .= "$indent </release>\n";
                   74567:         return $ret;
                   74568:     }
                   74569: 
                   74570:     /**
                   74571:      * @param array
                   74572:      * @access protected
                   74573:      */
                   74574:     function recursiveXmlFilelist($list)
                   74575:     {
                   74576:         $this->_dirs = array();
                   74577:         foreach ($list as $file => $attributes) {
                   74578:             $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
                   74579:         }
                   74580:         return $this->_formatDir($this->_dirs);
                   74581:     }
                   74582: 
                   74583:     /**
                   74584:      * @param array
                   74585:      * @param array
                   74586:      * @param string|null
                   74587:      * @param array|null
                   74588:      * @access private
                   74589:      */
                   74590:     function _addDir(&$dirs, $dir, $file = null, $attributes = null)
                   74591:     {
                   74592:         if ($dir == array() || $dir == array('.')) {
                   74593:             $dirs['files'][basename($file)] = $attributes;
                   74594:             return;
                   74595:         }
                   74596:         $curdir = array_shift($dir);
                   74597:         if (!isset($dirs['dirs'][$curdir])) {
                   74598:             $dirs['dirs'][$curdir] = array();
                   74599:         }
                   74600:         $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
                   74601:     }
                   74602: 
                   74603:     /**
                   74604:      * @param array
                   74605:      * @param string
                   74606:      * @param string
                   74607:      * @access private
                   74608:      */
                   74609:     function _formatDir($dirs, $indent = '', $curdir = '')
                   74610:     {
                   74611:         $ret = '';
                   74612:         if (!count($dirs)) {
                   74613:             return '';
                   74614:         }
                   74615:         if (isset($dirs['dirs'])) {
                   74616:             uksort($dirs['dirs'], 'strnatcasecmp');
                   74617:             foreach ($dirs['dirs'] as $dir => $contents) {
                   74618:                 $usedir = "$curdir/$dir";
                   74619:                 $ret .= "$indent   <dir name=\"$dir\">\n";
                   74620:                 $ret .= $this->_formatDir($contents, "$indent ", $usedir);
                   74621:                 $ret .= "$indent   </dir> <!-- $usedir -->\n";
                   74622:             }
                   74623:         }
                   74624:         if (isset($dirs['files'])) {
                   74625:             uksort($dirs['files'], 'strnatcasecmp');
                   74626:             foreach ($dirs['files'] as $file => $attribs) {
                   74627:                 $ret .= $this->_formatFile($file, $attribs, $indent);
                   74628:             }
                   74629:         }
                   74630:         return $ret;
                   74631:     }
                   74632: 
                   74633:     /**
                   74634:      * @param string
                   74635:      * @param array
                   74636:      * @param string
                   74637:      * @access private
                   74638:      */
                   74639:     function _formatFile($file, $attributes, $indent)
                   74640:     {
                   74641:         $ret = "$indent   <file role=\"$attributes[role]\"";
                   74642:         if (isset($attributes['baseinstalldir'])) {
                   74643:             $ret .= ' baseinstalldir="' .
                   74644:                 $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
                   74645:         }
                   74646:         if (isset($attributes['md5sum'])) {
                   74647:             $ret .= " md5sum=\"$attributes[md5sum]\"";
                   74648:         }
                   74649:         if (isset($attributes['platform'])) {
                   74650:             $ret .= " platform=\"$attributes[platform]\"";
                   74651:         }
                   74652:         if (!empty($attributes['install-as'])) {
                   74653:             $ret .= ' install-as="' .
                   74654:                 $this->_fixXmlEncoding($attributes['install-as']) . '"';
                   74655:         }
                   74656:         $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   74657:         if (empty($attributes['replacements'])) {
                   74658:             $ret .= "/>\n";
                   74659:         } else {
                   74660:             $ret .= ">\n";
                   74661:             foreach ($attributes['replacements'] as $r) {
                   74662:                 $ret .= "$indent    <replace";
                   74663:                 foreach ($r as $k => $v) {
                   74664:                     $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   74665:                 }
                   74666:                 $ret .= "/>\n";
                   74667:             }
                   74668:             $ret .= "$indent   </file>\n";
                   74669:         }
                   74670:         return $ret;
                   74671:     }
                   74672: 
                   74673:     // {{{ _unIndent()
                   74674: 
                   74675:     /**
                   74676:      * Unindent given string (?)
                   74677:      *
                   74678:      * @param string $str The string that has to be unindented.
                   74679:      * @return string
                   74680:      * @access private
                   74681:      */
                   74682:     function _unIndent($str)
                   74683:     {
                   74684:         // remove leading newlines
                   74685:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   74686:         // find whitespace at the beginning of the first line
                   74687:         $indent_len = strspn($str, " \t");
                   74688:         $indent = substr($str, 0, $indent_len);
                   74689:         $data = '';
                   74690:         // remove the same amount of whitespace from following lines
                   74691:         foreach (explode("\n", $str) as $line) {
                   74692:             if (substr($line, 0, $indent_len) == $indent) {
                   74693:                 $data .= substr($line, $indent_len) . "\n";
                   74694:             }
                   74695:         }
                   74696:         return $data;
                   74697:     }
                   74698: 
                   74699:     /**
                   74700:      * @return array
                   74701:      */
                   74702:     function dependenciesToV2()
                   74703:     {
                   74704:         $arr = array();
                   74705:         $this->_convertDependencies2_0($arr);
                   74706:         return $arr['dependencies'];
                   74707:     }
                   74708: 
                   74709:     /**
                   74710:      * Convert a package.xml version 1.0 into version 2.0
                   74711:      *
                   74712:      * Note that this does a basic conversion, to allow more advanced
                   74713:      * features like bundles and multiple releases
                   74714:      * @param string the classname to instantiate and return.  This must be
                   74715:      *               PEAR_PackageFile_v2 or a descendant
                   74716:      * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
                   74717:      *                strictest parameters will be converted
                   74718:      * @return PEAR_PackageFile_v2|PEAR_Error
                   74719:      */
                   74720:     function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
                   74721:     {
                   74722:         if ($strict) {
                   74723:             if (!$this->_packagefile->validate()) {
                   74724:                 $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
                   74725:                     ' to version 2.0', null, null, null,
                   74726:                     $this->_packagefile->getValidationWarnings(true));
                   74727:                 return $a;
                   74728:             }
                   74729:         }
                   74730: 
                   74731:         $arr = array(
                   74732:             'attribs' => array(
                   74733:                              'version' => '2.0',
                   74734:                              'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   74735:                              'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   74736:                              'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   74737:                              'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
                   74738: "http://pear.php.net/dtd/tasks-1.0.xsd\n" .
                   74739: "http://pear.php.net/dtd/package-2.0\n" .
                   74740: 'http://pear.php.net/dtd/package-2.0.xsd',
                   74741:                          ),
                   74742:             'name' => $this->_packagefile->getPackage(),
                   74743:             'channel' => 'pear.php.net',
                   74744:         );
                   74745:         $arr['summary'] = $this->_packagefile->getSummary();
                   74746:         $arr['description'] = $this->_packagefile->getDescription();
                   74747:         $maintainers = $this->_packagefile->getMaintainers();
                   74748:         foreach ($maintainers as $maintainer) {
                   74749:             if ($maintainer['role'] != 'lead') {
                   74750:                 continue;
                   74751:             }
                   74752:             $new = array(
                   74753:                 'name' => $maintainer['name'],
                   74754:                 'user' => $maintainer['handle'],
                   74755:                 'email' => $maintainer['email'],
                   74756:                 'active' => 'yes',
                   74757:             );
                   74758:             $arr['lead'][] = $new;
                   74759:         }
                   74760: 
                   74761:         if (!isset($arr['lead'])) { // some people... you know?
                   74762:             $arr['lead'] = array(
                   74763:                 'name' => 'unknown',
                   74764:                 'user' => 'unknown',
                   74765:                 'email' => 'noleadmaintainer@example.com',
                   74766:                 'active' => 'no',
                   74767:             );
                   74768:         }
                   74769: 
                   74770:         if (count($arr['lead']) == 1) {
                   74771:             $arr['lead'] = $arr['lead'][0];
                   74772:         }
                   74773: 
                   74774:         foreach ($maintainers as $maintainer) {
                   74775:             if ($maintainer['role'] == 'lead') {
                   74776:                 continue;
                   74777:             }
                   74778:             $new = array(
                   74779:                 'name' => $maintainer['name'],
                   74780:                 'user' => $maintainer['handle'],
                   74781:                 'email' => $maintainer['email'],
                   74782:                 'active' => 'yes',
                   74783:             );
                   74784:             $arr[$maintainer['role']][] = $new;
                   74785:         }
                   74786: 
                   74787:         if (isset($arr['developer']) && count($arr['developer']) == 1) {
                   74788:             $arr['developer'] = $arr['developer'][0];
                   74789:         }
                   74790: 
                   74791:         if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
                   74792:             $arr['contributor'] = $arr['contributor'][0];
                   74793:         }
                   74794: 
                   74795:         if (isset($arr['helper']) && count($arr['helper']) == 1) {
                   74796:             $arr['helper'] = $arr['helper'][0];
                   74797:         }
                   74798: 
                   74799:         $arr['date'] = $this->_packagefile->getDate();
                   74800:         $arr['version'] =
                   74801:             array(
                   74802:                 'release' => $this->_packagefile->getVersion(),
                   74803:                 'api' => $this->_packagefile->getVersion(),
                   74804:             );
                   74805:         $arr['stability'] =
                   74806:             array(
                   74807:                 'release' => $this->_packagefile->getState(),
                   74808:                 'api' => $this->_packagefile->getState(),
                   74809:             );
                   74810:         $licensemap =
                   74811:             array(
                   74812:                 'php' => 'http://www.php.net/license',
                   74813:                 'php license' => 'http://www.php.net/license',
                   74814:                 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
                   74815:                 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
                   74816:                 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   74817:                 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   74818:                 'mit' => 'http://www.opensource.org/licenses/mit-license.php',
                   74819:                 'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
                   74820:                 'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
                   74821:             );
                   74822: 
                   74823:         if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
                   74824:             $arr['license'] = array(
                   74825:                 'attribs' => array('uri' =>
                   74826:                     $licensemap[strtolower($this->_packagefile->getLicense())]),
                   74827:                 '_content' => $this->_packagefile->getLicense()
                   74828:                 );
                   74829:         } else {
                   74830:             // don't use bogus uri
                   74831:             $arr['license'] = $this->_packagefile->getLicense();
                   74832:         }
                   74833: 
                   74834:         $arr['notes'] = $this->_packagefile->getNotes();
                   74835:         $temp = array();
                   74836:         $arr['contents'] = $this->_convertFilelist2_0($temp);
                   74837:         $this->_convertDependencies2_0($arr);
                   74838:         $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
                   74839:             'extsrcrelease' : 'phprelease';
                   74840:         if ($release == 'extsrcrelease') {
                   74841:             $arr['channel'] = 'pecl.php.net';
                   74842:             $arr['providesextension'] = $arr['name']; // assumption
                   74843:         }
                   74844: 
                   74845:         $arr[$release] = array();
                   74846:         if ($this->_packagefile->getConfigureOptions()) {
                   74847:             $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
                   74848:             foreach ($arr[$release]['configureoption'] as $i => $opt) {
                   74849:                 $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
                   74850:             }
                   74851:             if (count($arr[$release]['configureoption']) == 1) {
                   74852:                 $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
                   74853:             }
                   74854:         }
                   74855: 
                   74856:         $this->_convertRelease2_0($arr[$release], $temp);
                   74857:         if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
                   74858:             // multiple extsrcrelease tags added in PEAR 1.4.1
                   74859:             $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
                   74860:         }
                   74861: 
                   74862:         if ($cl = $this->_packagefile->getChangelog()) {
                   74863:             foreach ($cl as $release) {
                   74864:                 $rel = array();
                   74865:                 $rel['version'] =
                   74866:                     array(
                   74867:                         'release' => $release['version'],
                   74868:                         'api' => $release['version'],
                   74869:                     );
                   74870:                 if (!isset($release['release_state'])) {
                   74871:                     $release['release_state'] = 'stable';
                   74872:                 }
                   74873: 
                   74874:                 $rel['stability'] =
                   74875:                     array(
                   74876:                         'release' => $release['release_state'],
                   74877:                         'api' => $release['release_state'],
                   74878:                     );
                   74879:                 if (isset($release['release_date'])) {
                   74880:                     $rel['date'] = $release['release_date'];
                   74881:                 } else {
                   74882:                     $rel['date'] = date('Y-m-d');
                   74883:                 }
                   74884: 
                   74885:                 if (isset($release['release_license'])) {
                   74886:                     if (isset($licensemap[strtolower($release['release_license'])])) {
                   74887:                         $uri = $licensemap[strtolower($release['release_license'])];
                   74888:                     } else {
                   74889:                         $uri = 'http://www.example.com';
                   74890:                     }
                   74891:                     $rel['license'] = array(
                   74892:                             'attribs' => array('uri' => $uri),
                   74893:                             '_content' => $release['release_license']
                   74894:                         );
                   74895:                 } else {
                   74896:                     $rel['license'] = $arr['license'];
                   74897:                 }
                   74898: 
                   74899:                 if (!isset($release['release_notes'])) {
                   74900:                     $release['release_notes'] = 'no release notes';
                   74901:                 }
                   74902: 
                   74903:                 $rel['notes'] = $release['release_notes'];
                   74904:                 $arr['changelog']['release'][] = $rel;
                   74905:             }
                   74906:         }
                   74907: 
                   74908:         $ret = new $class;
                   74909:         $ret->setConfig($this->_packagefile->_config);
                   74910:         if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
                   74911:             $ret->setLogger($this->_packagefile->_logger);
                   74912:         }
                   74913: 
                   74914:         $ret->fromArray($arr);
                   74915:         return $ret;
                   74916:     }
                   74917: 
                   74918:     /**
                   74919:      * @param array
                   74920:      * @param bool
                   74921:      * @access private
                   74922:      */
                   74923:     function _convertDependencies2_0(&$release, $internal = false)
                   74924:     {
                   74925:         $peardep = array('pearinstaller' =>
                   74926:             array('min' => '1.4.0b1')); // this is a lot safer
                   74927:         $required = $optional = array();
                   74928:         $release['dependencies'] = array('required' => array());
                   74929:         if ($this->_packagefile->hasDeps()) {
                   74930:             foreach ($this->_packagefile->getDeps() as $dep) {
                   74931:                 if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   74932:                     $required[] = $dep;
                   74933:                 } else {
                   74934:                     $optional[] = $dep;
                   74935:                 }
                   74936:             }
                   74937:             foreach (array('required', 'optional') as $arr) {
                   74938:                 $deps = array();
                   74939:                 foreach ($$arr as $dep) {
                   74940:                     // organize deps by dependency type and name
                   74941:                     if (!isset($deps[$dep['type']])) {
                   74942:                         $deps[$dep['type']] = array();
                   74943:                     }
                   74944:                     if (isset($dep['name'])) {
                   74945:                         $deps[$dep['type']][$dep['name']][] = $dep;
                   74946:                     } else {
                   74947:                         $deps[$dep['type']][] = $dep;
                   74948:                     }
                   74949:                 }
                   74950:                 do {
                   74951:                     if (isset($deps['php'])) {
                   74952:                         $php = array();
                   74953:                         if (count($deps['php']) > 1) {
                   74954:                             $php = $this->_processPhpDeps($deps['php']);
                   74955:                         } else {
                   74956:                             if (!isset($deps['php'][0])) {
                   74957:                                 list($key, $blah) = each ($deps['php']); // stupid buggy versions
                   74958:                                 $deps['php'] = array($blah[0]);
                   74959:                             }
                   74960:                             $php = $this->_processDep($deps['php'][0]);
                   74961:                             if (!$php) {
                   74962:                                 break; // poor mans throw
                   74963:                             }
                   74964:                         }
                   74965:                         $release['dependencies'][$arr]['php'] = $php;
                   74966:                     }
                   74967:                 } while (false);
                   74968:                 do {
                   74969:                     if (isset($deps['pkg'])) {
                   74970:                         $pkg = array();
                   74971:                         $pkg = $this->_processMultipleDepsName($deps['pkg']);
                   74972:                         if (!$pkg) {
                   74973:                             break; // poor mans throw
                   74974:                         }
                   74975:                         $release['dependencies'][$arr]['package'] = $pkg;
                   74976:                     }
                   74977:                 } while (false);
                   74978:                 do {
                   74979:                     if (isset($deps['ext'])) {
                   74980:                         $pkg = array();
                   74981:                         $pkg = $this->_processMultipleDepsName($deps['ext']);
                   74982:                         $release['dependencies'][$arr]['extension'] = $pkg;
                   74983:                     }
                   74984:                 } while (false);
                   74985:                 // skip sapi - it's not supported so nobody will have used it
                   74986:                 // skip os - it's not supported in 1.0
                   74987:             }
                   74988:         }
                   74989:         if (isset($release['dependencies']['required'])) {
                   74990:             $release['dependencies']['required'] =
                   74991:                 array_merge($peardep, $release['dependencies']['required']);
                   74992:         } else {
                   74993:             $release['dependencies']['required'] = $peardep;
                   74994:         }
                   74995:         if (!isset($release['dependencies']['required']['php'])) {
                   74996:             $release['dependencies']['required']['php'] =
                   74997:                 array('min' => '4.0.0');
                   74998:         }
                   74999:         $order = array();
                   75000:         $bewm = $release['dependencies']['required'];
                   75001:         $order['php'] = $bewm['php'];
                   75002:         $order['pearinstaller'] = $bewm['pearinstaller'];
                   75003:         isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
                   75004:         isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
                   75005:         $release['dependencies']['required'] = $order;
                   75006:     }
                   75007: 
                   75008:     /**
                   75009:      * @param array
                   75010:      * @access private
                   75011:      */
                   75012:     function _convertFilelist2_0(&$package)
                   75013:     {
                   75014:         $ret = array('dir' =>
                   75015:                     array(
                   75016:                         'attribs' => array('name' => '/'),
                   75017:                         'file' => array()
                   75018:                         )
                   75019:                     );
                   75020:         $package['platform'] =
                   75021:         $package['install-as'] = array();
                   75022:         $this->_isExtension = false;
                   75023:         foreach ($this->_packagefile->getFilelist() as $name => $file) {
                   75024:             $file['name'] = $name;
                   75025:             if (isset($file['role']) && $file['role'] == 'src') {
                   75026:                 $this->_isExtension = true;
                   75027:             }
                   75028:             if (isset($file['replacements'])) {
                   75029:                 $repl = $file['replacements'];
                   75030:                 unset($file['replacements']);
                   75031:             } else {
                   75032:                 unset($repl);
                   75033:             }
                   75034:             if (isset($file['install-as'])) {
                   75035:                 $package['install-as'][$name] = $file['install-as'];
                   75036:                 unset($file['install-as']);
                   75037:             }
                   75038:             if (isset($file['platform'])) {
                   75039:                 $package['platform'][$name] = $file['platform'];
                   75040:                 unset($file['platform']);
                   75041:             }
                   75042:             $file = array('attribs' => $file);
                   75043:             if (isset($repl)) {
                   75044:                 foreach ($repl as $replace ) {
                   75045:                     $file['tasks:replace'][] = array('attribs' => $replace);
                   75046:                 }
                   75047:                 if (count($repl) == 1) {
                   75048:                     $file['tasks:replace'] = $file['tasks:replace'][0];
                   75049:                 }
                   75050:             }
                   75051:             $ret['dir']['file'][] = $file;
                   75052:         }
                   75053:         return $ret;
                   75054:     }
                   75055: 
                   75056:     /**
                   75057:      * Post-process special files with install-as/platform attributes and
                   75058:      * make the release tag.
                   75059:      *
                   75060:      * This complex method follows this work-flow to create the release tags:
                   75061:      *
                   75062:      * <pre>
                   75063:      * - if any install-as/platform exist, create a generic release and fill it with
                   75064:      *   o <install as=..> tags for <file name=... install-as=...>
                   75065:      *   o <install as=..> tags for <file name=... platform=!... install-as=..>
                   75066:      *   o <ignore> tags for <file name=... platform=...>
                   75067:      *   o <ignore> tags for <file name=... platform=... install-as=..>
                   75068:      * - create a release for each platform encountered and fill with
                   75069:      *   o <install as..> tags for <file name=... install-as=...>
                   75070:      *   o <install as..> tags for <file name=... platform=this platform install-as=..>
                   75071:      *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
                   75072:      *   o <ignore> tags for <file name=... platform=!this platform>
                   75073:      *   o <ignore> tags for <file name=... platform=other platform>
                   75074:      *   o <ignore> tags for <file name=... platform=other platform install-as=..>
                   75075:      *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
                   75076:      * </pre>
                   75077:      *
                   75078:      * It does this by accessing the $package parameter, which contains an array with
                   75079:      * indices:
                   75080:      *
                   75081:      *  - platform: mapping of file => OS the file should be installed on
                   75082:      *  - install-as: mapping of file => installed name
                   75083:      *  - osmap: mapping of OS => list of files that should be installed
                   75084:      *    on that OS
                   75085:      *  - notosmap: mapping of OS => list of files that should not be
                   75086:      *    installed on that OS
                   75087:      *
                   75088:      * @param array
                   75089:      * @param array
                   75090:      * @access private
                   75091:      */
                   75092:     function _convertRelease2_0(&$release, $package)
                   75093:     {
                   75094:         //- if any install-as/platform exist, create a generic release and fill it with
                   75095:         if (count($package['platform']) || count($package['install-as'])) {
                   75096:             $generic = array();
                   75097:             $genericIgnore = array();
                   75098:             foreach ($package['install-as'] as $file => $as) {
                   75099:                 //o <install as=..> tags for <file name=... install-as=...>
                   75100:                 if (!isset($package['platform'][$file])) {
                   75101:                     $generic[] = $file;
                   75102:                     continue;
                   75103:                 }
                   75104:                 //o <install as=..> tags for <file name=... platform=!... install-as=..>
                   75105:                 if (isset($package['platform'][$file]) &&
                   75106:                       $package['platform'][$file]{0} == '!') {
                   75107:                     $generic[] = $file;
                   75108:                     continue;
                   75109:                 }
                   75110:                 //o <ignore> tags for <file name=... platform=... install-as=..>
                   75111:                 if (isset($package['platform'][$file]) &&
                   75112:                       $package['platform'][$file]{0} != '!') {
                   75113:                     $genericIgnore[] = $file;
                   75114:                     continue;
                   75115:                 }
                   75116:             }
                   75117:             foreach ($package['platform'] as $file => $platform) {
                   75118:                 if (isset($package['install-as'][$file])) {
                   75119:                     continue;
                   75120:                 }
                   75121:                 if ($platform{0} != '!') {
                   75122:                     //o <ignore> tags for <file name=... platform=...>
                   75123:                     $genericIgnore[] = $file;
                   75124:                 }
                   75125:             }
                   75126:             if (count($package['platform'])) {
                   75127:                 $oses = $notplatform = $platform = array();
                   75128:                 foreach ($package['platform'] as $file => $os) {
                   75129:                     // get a list of oses
                   75130:                     if ($os{0} == '!') {
                   75131:                         if (isset($oses[substr($os, 1)])) {
                   75132:                             continue;
                   75133:                         }
                   75134:                         $oses[substr($os, 1)] = count($oses);
                   75135:                     } else {
                   75136:                         if (isset($oses[$os])) {
                   75137:                             continue;
                   75138:                         }
                   75139:                         $oses[$os] = count($oses);
                   75140:                     }
                   75141:                 }
                   75142:                 //- create a release for each platform encountered and fill with
                   75143:                 foreach ($oses as $os => $releaseNum) {
                   75144:                     $release[$releaseNum]['installconditions']['os']['name'] = $os;
                   75145:                     $release[$releaseNum]['filelist'] = array('install' => array(),
                   75146:                         'ignore' => array());
                   75147:                     foreach ($package['install-as'] as $file => $as) {
                   75148:                         //o <install as=..> tags for <file name=... install-as=...>
                   75149:                         if (!isset($package['platform'][$file])) {
                   75150:                             $release[$releaseNum]['filelist']['install'][] =
                   75151:                                 array(
                   75152:                                     'attribs' => array(
                   75153:                                         'name' => $file,
                   75154:                                         'as' => $as,
                   75155:                                     ),
                   75156:                                 );
                   75157:                             continue;
                   75158:                         }
                   75159:                         //o <install as..> tags for
                   75160:                         //  <file name=... platform=this platform install-as=..>
                   75161:                         if (isset($package['platform'][$file]) &&
                   75162:                               $package['platform'][$file] == $os) {
                   75163:                             $release[$releaseNum]['filelist']['install'][] =
                   75164:                                 array(
                   75165:                                     'attribs' => array(
                   75166:                                         'name' => $file,
                   75167:                                         'as' => $as,
                   75168:                                     ),
                   75169:                                 );
                   75170:                             continue;
                   75171:                         }
                   75172:                         //o <install as..> tags for
                   75173:                         //  <file name=... platform=!other platform install-as=..>
                   75174:                         if (isset($package['platform'][$file]) &&
                   75175:                               $package['platform'][$file] != "!$os" &&
                   75176:                               $package['platform'][$file]{0} == '!') {
                   75177:                             $release[$releaseNum]['filelist']['install'][] =
                   75178:                                 array(
                   75179:                                     'attribs' => array(
                   75180:                                         'name' => $file,
                   75181:                                         'as' => $as,
                   75182:                                     ),
                   75183:                                 );
                   75184:                             continue;
                   75185:                         }
                   75186:                         //o <ignore> tags for
                   75187:                         //  <file name=... platform=!this platform install-as=..>
                   75188:                         if (isset($package['platform'][$file]) &&
                   75189:                               $package['platform'][$file] == "!$os") {
                   75190:                             $release[$releaseNum]['filelist']['ignore'][] =
                   75191:                                 array(
                   75192:                                     'attribs' => array(
                   75193:                                         'name' => $file,
                   75194:                                     ),
                   75195:                                 );
                   75196:                             continue;
                   75197:                         }
                   75198:                         //o <ignore> tags for
                   75199:                         //  <file name=... platform=other platform install-as=..>
                   75200:                         if (isset($package['platform'][$file]) &&
                   75201:                               $package['platform'][$file]{0} != '!' &&
                   75202:                               $package['platform'][$file] != $os) {
                   75203:                             $release[$releaseNum]['filelist']['ignore'][] =
                   75204:                                 array(
                   75205:                                     'attribs' => array(
                   75206:                                         'name' => $file,
                   75207:                                     ),
                   75208:                                 );
                   75209:                             continue;
                   75210:                         }
                   75211:                     }
                   75212:                     foreach ($package['platform'] as $file => $platform) {
                   75213:                         if (isset($package['install-as'][$file])) {
                   75214:                             continue;
                   75215:                         }
                   75216:                         //o <ignore> tags for <file name=... platform=!this platform>
                   75217:                         if ($platform == "!$os") {
                   75218:                             $release[$releaseNum]['filelist']['ignore'][] =
                   75219:                                 array(
                   75220:                                     'attribs' => array(
                   75221:                                         'name' => $file,
                   75222:                                     ),
                   75223:                                 );
                   75224:                             continue;
                   75225:                         }
                   75226:                         //o <ignore> tags for <file name=... platform=other platform>
                   75227:                         if ($platform{0} != '!' && $platform != $os) {
                   75228:                             $release[$releaseNum]['filelist']['ignore'][] =
                   75229:                                 array(
                   75230:                                     'attribs' => array(
                   75231:                                         'name' => $file,
                   75232:                                     ),
                   75233:                                 );
                   75234:                         }
                   75235:                     }
                   75236:                     if (!count($release[$releaseNum]['filelist']['install'])) {
                   75237:                         unset($release[$releaseNum]['filelist']['install']);
                   75238:                     }
                   75239:                     if (!count($release[$releaseNum]['filelist']['ignore'])) {
                   75240:                         unset($release[$releaseNum]['filelist']['ignore']);
                   75241:                     }
                   75242:                 }
                   75243:                 if (count($generic) || count($genericIgnore)) {
                   75244:                     $release[count($oses)] = array();
                   75245:                     if (count($generic)) {
                   75246:                         foreach ($generic as $file) {
                   75247:                             if (isset($package['install-as'][$file])) {
                   75248:                                 $installas = $package['install-as'][$file];
                   75249:                             } else {
                   75250:                                 $installas = $file;
                   75251:                             }
                   75252:                             $release[count($oses)]['filelist']['install'][] =
                   75253:                                 array(
                   75254:                                     'attribs' => array(
                   75255:                                         'name' => $file,
                   75256:                                         'as' => $installas,
                   75257:                                     )
                   75258:                                 );
                   75259:                         }
                   75260:                     }
                   75261:                     if (count($genericIgnore)) {
                   75262:                         foreach ($genericIgnore as $file) {
                   75263:                             $release[count($oses)]['filelist']['ignore'][] =
                   75264:                                 array(
                   75265:                                     'attribs' => array(
                   75266:                                         'name' => $file,
                   75267:                                     )
                   75268:                                 );
                   75269:                         }
                   75270:                     }
                   75271:                 }
                   75272:                 // cleanup
                   75273:                 foreach ($release as $i => $rel) {
                   75274:                     if (isset($rel['filelist']['install']) &&
                   75275:                           count($rel['filelist']['install']) == 1) {
                   75276:                         $release[$i]['filelist']['install'] =
                   75277:                             $release[$i]['filelist']['install'][0];
                   75278:                     }
                   75279:                     if (isset($rel['filelist']['ignore']) &&
                   75280:                           count($rel['filelist']['ignore']) == 1) {
                   75281:                         $release[$i]['filelist']['ignore'] =
                   75282:                             $release[$i]['filelist']['ignore'][0];
                   75283:                     }
                   75284:                 }
                   75285:                 if (count($release) == 1) {
                   75286:                     $release = $release[0];
                   75287:                 }
                   75288:             } else {
                   75289:                 // no platform atts, but some install-as atts
                   75290:                 foreach ($package['install-as'] as $file => $value) {
                   75291:                     $release['filelist']['install'][] =
                   75292:                         array(
                   75293:                             'attribs' => array(
                   75294:                                 'name' => $file,
                   75295:                                 'as' => $value
                   75296:                             )
                   75297:                         );
                   75298:                 }
                   75299:                 if (count($release['filelist']['install']) == 1) {
                   75300:                     $release['filelist']['install'] = $release['filelist']['install'][0];
                   75301:                 }
                   75302:             }
                   75303:         }
                   75304:     }
                   75305: 
                   75306:     /**
                   75307:      * @param array
                   75308:      * @return array
                   75309:      * @access private
                   75310:      */
                   75311:     function _processDep($dep)
                   75312:     {
                   75313:         if ($dep['type'] == 'php') {
                   75314:             if ($dep['rel'] == 'has') {
                   75315:                 // come on - everyone has php!
                   75316:                 return false;
                   75317:             }
                   75318:         }
                   75319:         $php = array();
                   75320:         if ($dep['type'] != 'php') {
                   75321:             $php['name'] = $dep['name'];
                   75322:             if ($dep['type'] == 'pkg') {
                   75323:                 $php['channel'] = 'pear.php.net';
                   75324:             }
                   75325:         }
                   75326:         switch ($dep['rel']) {
                   75327:             case 'gt' :
                   75328:                 $php['min'] = $dep['version'];
                   75329:                 $php['exclude'] = $dep['version'];
                   75330:             break;
                   75331:             case 'ge' :
                   75332:                 if (!isset($dep['version'])) {
                   75333:                     if ($dep['type'] == 'php') {
                   75334:                         if (isset($dep['name'])) {
                   75335:                             $dep['version'] = $dep['name'];
                   75336:                         }
                   75337:                     }
                   75338:                 }
                   75339:                 $php['min'] = $dep['version'];
                   75340:             break;
                   75341:             case 'lt' :
                   75342:                 $php['max'] = $dep['version'];
                   75343:                 $php['exclude'] = $dep['version'];
                   75344:             break;
                   75345:             case 'le' :
                   75346:                 $php['max'] = $dep['version'];
                   75347:             break;
                   75348:             case 'eq' :
                   75349:                 $php['min'] = $dep['version'];
                   75350:                 $php['max'] = $dep['version'];
                   75351:             break;
                   75352:             case 'ne' :
                   75353:                 $php['exclude'] = $dep['version'];
                   75354:             break;
                   75355:             case 'not' :
                   75356:                 $php['conflicts'] = 'yes';
                   75357:             break;
                   75358:         }
                   75359:         return $php;
                   75360:     }
                   75361: 
                   75362:     /**
                   75363:      * @param array
                   75364:      * @return array
                   75365:      */
                   75366:     function _processPhpDeps($deps)
                   75367:     {
                   75368:         $test = array();
                   75369:         foreach ($deps as $dep) {
                   75370:             $test[] = $this->_processDep($dep);
                   75371:         }
                   75372:         $min = array();
                   75373:         $max = array();
                   75374:         foreach ($test as $dep) {
                   75375:             if (!$dep) {
                   75376:                 continue;
                   75377:             }
                   75378:             if (isset($dep['min'])) {
                   75379:                 $min[$dep['min']] = count($min);
                   75380:             }
                   75381:             if (isset($dep['max'])) {
                   75382:                 $max[$dep['max']] = count($max);
                   75383:             }
                   75384:         }
                   75385:         if (count($min) > 0) {
                   75386:             uksort($min, 'version_compare');
                   75387:         }
                   75388:         if (count($max) > 0) {
                   75389:             uksort($max, 'version_compare');
                   75390:         }
                   75391:         if (count($min)) {
                   75392:             // get the highest minimum
                   75393:             $min = array_pop($a = array_flip($min));
                   75394:         } else {
                   75395:             $min = false;
                   75396:         }
                   75397:         if (count($max)) {
                   75398:             // get the lowest maximum
                   75399:             $max = array_shift($a = array_flip($max));
                   75400:         } else {
                   75401:             $max = false;
                   75402:         }
                   75403:         if ($min) {
                   75404:             $php['min'] = $min;
                   75405:         }
                   75406:         if ($max) {
                   75407:             $php['max'] = $max;
                   75408:         }
                   75409:         $exclude = array();
                   75410:         foreach ($test as $dep) {
                   75411:             if (!isset($dep['exclude'])) {
                   75412:                 continue;
                   75413:             }
                   75414:             $exclude[] = $dep['exclude'];
                   75415:         }
                   75416:         if (count($exclude)) {
                   75417:             $php['exclude'] = $exclude;
                   75418:         }
                   75419:         return $php;
                   75420:     }
                   75421: 
                   75422:     /**
                   75423:      * process multiple dependencies that have a name, like package deps
                   75424:      * @param array
                   75425:      * @return array
                   75426:      * @access private
                   75427:      */
                   75428:     function _processMultipleDepsName($deps)
                   75429:     {
                   75430:         $ret = $tests = array();
                   75431:         foreach ($deps as $name => $dep) {
                   75432:             foreach ($dep as $d) {
                   75433:                 $tests[$name][] = $this->_processDep($d);
                   75434:             }
                   75435:         }
                   75436: 
                   75437:         foreach ($tests as $name => $test) {
                   75438:             $max = $min = $php = array();
                   75439:             $php['name'] = $name;
                   75440:             foreach ($test as $dep) {
                   75441:                 if (!$dep) {
                   75442:                     continue;
                   75443:                 }
                   75444:                 if (isset($dep['channel'])) {
                   75445:                     $php['channel'] = 'pear.php.net';
                   75446:                 }
                   75447:                 if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
                   75448:                     $php['conflicts'] = 'yes';
                   75449:                 }
                   75450:                 if (isset($dep['min'])) {
                   75451:                     $min[$dep['min']] = count($min);
                   75452:                 }
                   75453:                 if (isset($dep['max'])) {
                   75454:                     $max[$dep['max']] = count($max);
                   75455:                 }
                   75456:             }
                   75457:             if (count($min) > 0) {
                   75458:                 uksort($min, 'version_compare');
                   75459:             }
                   75460:             if (count($max) > 0) {
                   75461:                 uksort($max, 'version_compare');
                   75462:             }
                   75463:             if (count($min)) {
                   75464:                 // get the highest minimum
                   75465:                 $min = array_pop($a = array_flip($min));
                   75466:             } else {
                   75467:                 $min = false;
                   75468:             }
                   75469:             if (count($max)) {
                   75470:                 // get the lowest maximum
                   75471:                 $max = array_shift($a = array_flip($max));
                   75472:             } else {
                   75473:                 $max = false;
                   75474:             }
                   75475:             if ($min) {
                   75476:                 $php['min'] = $min;
                   75477:             }
                   75478:             if ($max) {
                   75479:                 $php['max'] = $max;
                   75480:             }
                   75481:             $exclude = array();
                   75482:             foreach ($test as $dep) {
                   75483:                 if (!isset($dep['exclude'])) {
                   75484:                     continue;
                   75485:                 }
                   75486:                 $exclude[] = $dep['exclude'];
                   75487:             }
                   75488:             if (count($exclude)) {
                   75489:                 $php['exclude'] = $exclude;
                   75490:             }
                   75491:             $ret[] = $php;
                   75492:         }
                   75493:         return $ret;
                   75494:     }
                   75495: }
                   75496: ?><?php
                   75497: /**
                   75498:  * package.xml generation class, package.xml version 2.0
                   75499:  *
                   75500:  * PHP versions 4 and 5
                   75501:  *
                   75502:  * @category   pear
                   75503:  * @package    PEAR
                   75504:  * @author     Greg Beaver <cellog@php.net>
                   75505:  * @author     Stephan Schmidt (original XML_Serializer code)
                   75506:  * @copyright  1997-2009 The Authors
                   75507:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   75508:  * @version    CVS: $Id: v2.php 278907 2009-04-17 21:10:04Z dufuz $
                   75509:  * @link       http://pear.php.net/package/PEAR
                   75510:  * @since      File available since Release 1.4.0a1
                   75511:  */
                   75512: /**
                   75513:  * file/dir manipulation routines
                   75514:  */
                   75515: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   75516: require_once 'phar://install-pear-nozlib.phar/' . 'XML/Util.php';
                   75517: 
                   75518: /**
                   75519:  * This class converts a PEAR_PackageFile_v2 object into any output format.
                   75520:  *
                   75521:  * Supported output formats include array, XML string (using S. Schmidt's
                   75522:  * XML_Serializer, slightly customized)
                   75523:  * @category   pear
                   75524:  * @package    PEAR
                   75525:  * @author     Greg Beaver <cellog@php.net>
                   75526:  * @author     Stephan Schmidt (original XML_Serializer code)
                   75527:  * @copyright  1997-2009 The Authors
                   75528:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   75529:  * @version    Release: 1.10.0beta1
                   75530:  * @link       http://pear.php.net/package/PEAR
                   75531:  * @since      Class available since Release 1.4.0a1
                   75532:  */
                   75533: class PEAR_PackageFile_Generator_v2
                   75534: {
                   75535:    /**
                   75536:     * default options for the serialization
                   75537:     * @access private
                   75538:     * @var array $_defaultOptions
                   75539:     */
                   75540:     var $_defaultOptions = array(
                   75541:         'indent'             => ' ',                    // string used for indentation
                   75542:         'linebreak'          => "\n",                  // string used for newlines
                   75543:         'typeHints'          => false,                 // automatically add type hin attributes
                   75544:         'addDecl'            => true,                 // add an XML declaration
                   75545:         'defaultTagName'     => 'XML_Serializer_Tag',  // tag used for indexed arrays or invalid names
                   75546:         'classAsTagName'     => false,                 // use classname for objects in indexed arrays
                   75547:         'keyAttribute'       => '_originalKey',        // attribute where original key is stored
                   75548:         'typeAttribute'      => '_type',               // attribute for type (only if typeHints => true)
                   75549:         'classAttribute'     => '_class',              // attribute for class of objects (only if typeHints => true)
                   75550:         'scalarAsAttributes' => false,                 // scalar values (strings, ints,..) will be serialized as attribute
                   75551:         'prependAttributes'  => '',                    // prepend string for attributes
                   75552:         'indentAttributes'   => false,                 // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
                   75553:         'mode'               => 'simplexml',             // use 'simplexml' to use parent name as tagname if transforming an indexed array
                   75554:         'addDoctype'         => false,                 // add a doctype declaration
                   75555:         'doctype'            => null,                  // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
                   75556:         'rootName'           => 'package',                  // name of the root tag
                   75557:         'rootAttributes'     => array(
                   75558:             'version' => '2.0',
                   75559:             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   75560:             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   75561:             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   75562:             'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   75563: http://pear.php.net/dtd/tasks-1.0.xsd
                   75564: http://pear.php.net/dtd/package-2.0
                   75565: http://pear.php.net/dtd/package-2.0.xsd',
                   75566:         ),               // attributes of the root tag
                   75567:         'attributesArray'    => 'attribs',                  // all values in this key will be treated as attributes
                   75568:         'contentName'        => '_content',                   // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
                   75569:         'beautifyFilelist'   => false,
                   75570:         'encoding' => 'UTF-8',
                   75571:     );
                   75572: 
                   75573:    /**
                   75574:     * options for the serialization
                   75575:     * @access private
                   75576:     * @var array $options
                   75577:     */
                   75578:     var $options = array();
                   75579: 
                   75580:    /**
                   75581:     * current tag depth
                   75582:     * @var integer $_tagDepth
                   75583:     */
                   75584:     var $_tagDepth = 0;
                   75585: 
                   75586:    /**
                   75587:     * serilialized representation of the data
                   75588:     * @var string $_serializedData
                   75589:     */
                   75590:     var $_serializedData = null;
                   75591:     /**
                   75592:      * @var PEAR_PackageFile_v2
                   75593:      */
                   75594:     var $_packagefile;
                   75595:     /**
                   75596:      * @param PEAR_PackageFile_v2
                   75597:      */
                   75598:     function PEAR_PackageFile_Generator_v2(&$packagefile)
                   75599:     {
                   75600:         $this->_packagefile = &$packagefile;
                   75601:         if (isset($this->_packagefile->encoding)) {
                   75602:             $this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
                   75603:         }
                   75604:     }
                   75605: 
                   75606:     /**
                   75607:      * @return string
                   75608:      */
                   75609:     function getPackagerVersion()
                   75610:     {
                   75611:         return '1.10.0beta1';
                   75612:     }
                   75613: 
                   75614:     /**
                   75615:      * @param PEAR_Packager
                   75616:      * @param bool generate a .tgz or a .tar
                   75617:      * @param string|null temporary directory to package in
                   75618:      */
                   75619:     function toTgz(&$packager, $compress = true, $where = null)
                   75620:     {
                   75621:         $a = null;
                   75622:         return $this->toTgz2($packager, $a, $compress, $where);
                   75623:     }
                   75624: 
                   75625:     /**
                   75626:      * Package up both a package.xml and package2.xml for the same release
                   75627:      * @param PEAR_Packager
                   75628:      * @param PEAR_PackageFile_v1
                   75629:      * @param bool generate a .tgz or a .tar
                   75630:      * @param string|null temporary directory to package in
                   75631:      */
                   75632:     function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
                   75633:     {
                   75634:         require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
                   75635:         if (!$this->_packagefile->isEquivalent($pf1)) {
                   75636:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
                   75637:                 basename($pf1->getPackageFile()) .
                   75638:                 '" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
                   75639:                 . '"');
                   75640:         }
                   75641: 
                   75642:         if ($where === null) {
                   75643:             if (!($where = System::mktemp(array('-d')))) {
                   75644:                 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
                   75645:             }
                   75646:         } elseif (!@System::mkDir(array('-p', $where))) {
                   75647:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
                   75648:                 ' not be created');
                   75649:         }
                   75650: 
                   75651:         $file = $where . DIRECTORY_SEPARATOR . 'package.xml';
                   75652:         if (file_exists($file) && !is_file($file)) {
                   75653:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
                   75654:                 ' "' . $file  .'"');
                   75655:         }
                   75656: 
                   75657:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   75658:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
                   75659:         }
                   75660: 
                   75661:         $ext = $compress ? '.tgz' : '.tar';
                   75662:         $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
                   75663:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   75664:         if (file_exists($dest_package) && !is_file($dest_package)) {
                   75665:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
                   75666:                 $dest_package . '"');
                   75667:         }
                   75668: 
                   75669:         $pkgfile = $this->_packagefile->getPackageFile();
                   75670:         if (!$pkgfile) {
                   75671:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
                   75672:                 'be created from a real file');
                   75673:         }
                   75674: 
                   75675:         $pkgdir  = dirname(realpath($pkgfile));
                   75676:         $pkgfile = basename($pkgfile);
                   75677: 
                   75678:         // {{{ Create the package file list
                   75679:         $filelist = array();
                   75680:         $i = 0;
                   75681:         $this->_packagefile->flattenFilelist();
                   75682:         $contents = $this->_packagefile->getContents();
                   75683:         if (isset($contents['bundledpackage'])) { // bundles of packages
                   75684:             $contents = $contents['bundledpackage'];
                   75685:             if (!isset($contents[0])) {
                   75686:                 $contents = array($contents);
                   75687:             }
                   75688: 
                   75689:             $packageDir = $where;
                   75690:             foreach ($contents as $i => $package) {
                   75691:                 $fname = $package;
                   75692:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   75693:                 if (!file_exists($file)) {
                   75694:                     return $packager->raiseError("File does not exist: $fname");
                   75695:                 }
                   75696: 
                   75697:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   75698:                 System::mkdir(array('-p', dirname($tfile)));
                   75699:                 copy($file, $tfile);
                   75700:                 $filelist[$i++] = $tfile;
                   75701:                 $packager->log(2, "Adding package $fname");
                   75702:             }
                   75703:         } else { // normal packages
                   75704:             $contents = $contents['dir']['file'];
                   75705:             if (!isset($contents[0])) {
                   75706:                 $contents = array($contents);
                   75707:             }
                   75708: 
                   75709:             $packageDir = $where;
                   75710:             foreach ($contents as $i => $file) {
                   75711:                 $fname = $file['attribs']['name'];
                   75712:                 $atts = $file['attribs'];
                   75713:                 $orig = $file;
                   75714:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   75715:                 if (!file_exists($file)) {
                   75716:                     return $packager->raiseError("File does not exist: $fname");
                   75717:                 }
                   75718: 
                   75719:                 $origperms = fileperms($file);
                   75720:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   75721:                 unset($orig['attribs']);
                   75722:                 if (count($orig)) { // file with tasks
                   75723:                     // run any package-time tasks
                   75724:                     $contents = file_get_contents($file);
                   75725:                     foreach ($orig as $tag => $raw) {
                   75726:                         $tag = str_replace(
                   75727:                             array($this->_packagefile->getTasksNs() . ':', '-'),
                   75728:                             array('', '_'), $tag);
                   75729:                         $task = "PEAR_Task_$tag";
                   75730:                         $task = &new $task($this->_packagefile->_config,
                   75731:                             $this->_packagefile->_logger,
                   75732:                             PEAR_TASK_PACKAGE);
                   75733:                         $task->init($raw, $atts, null);
                   75734:                         $res = $task->startSession($this->_packagefile, $contents, $tfile);
                   75735:                         if (!$res) {
                   75736:                             continue; // skip this task
                   75737:                         }
                   75738: 
                   75739:                         if (PEAR::isError($res)) {
                   75740:                             return $res;
                   75741:                         }
                   75742: 
                   75743:                         $contents = $res; // save changes
                   75744:                         System::mkdir(array('-p', dirname($tfile)));
                   75745:                         $wp = fopen($tfile, "wb");
                   75746:                         fwrite($wp, $contents);
                   75747:                         fclose($wp);
                   75748:                     }
                   75749:                 }
                   75750: 
                   75751:                 if (!file_exists($tfile)) {
                   75752:                     System::mkdir(array('-p', dirname($tfile)));
                   75753:                     copy($file, $tfile);
                   75754:                 }
                   75755: 
                   75756:                 chmod($tfile, $origperms);
                   75757:                 $filelist[$i++] = $tfile;
                   75758:                 $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
                   75759:                 $packager->log(2, "Adding file $fname");
                   75760:             }
                   75761:         }
                   75762:             // }}}
                   75763: 
                   75764:         $name       = $pf1 !== null ? 'package2.xml' : 'package.xml';
                   75765:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
                   75766:         if ($packagexml) {
                   75767:             $tar =& new Archive_Tar($dest_package, $compress);
                   75768:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   75769:             // ----- Creates with the package.xml file
                   75770:             $ok = $tar->createModify(array($packagexml), '', $where);
                   75771:             if (PEAR::isError($ok)) {
                   75772:                 return $packager->raiseError($ok);
                   75773:             } elseif (!$ok) {
                   75774:                 return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
                   75775:                     ' failed');
                   75776:             }
                   75777: 
                   75778:             // ----- Add the content of the package
                   75779:             if (!$tar->addModify($filelist, $pkgver, $where)) {
                   75780:                 return $packager->raiseError(
                   75781:                     'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
                   75782:             }
                   75783: 
                   75784:             // add the package.xml version 1.0
                   75785:             if ($pf1 !== null) {
                   75786:                 $pfgen = &$pf1->getDefaultGenerator();
                   75787:                 $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   75788:                 if (!$tar->addModify(array($packagexml1), '', $where)) {
                   75789:                     return $packager->raiseError(
                   75790:                         'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
                   75791:                 }
                   75792:             }
                   75793: 
                   75794:             return $dest_package;
                   75795:         }
                   75796:     }
                   75797: 
                   75798:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
                   75799:     {
                   75800:         if (!$this->_packagefile->validate($state)) {
                   75801:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
                   75802:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   75803:         }
                   75804: 
                   75805:         if ($where === null) {
                   75806:             if (!($where = System::mktemp(array('-d')))) {
                   75807:                 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
                   75808:             }
                   75809:         } elseif (!@System::mkDir(array('-p', $where))) {
                   75810:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
                   75811:                 ' not be created');
                   75812:         }
                   75813: 
                   75814:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   75815:         $np = @fopen($newpkgfile, 'wb');
                   75816:         if (!$np) {
                   75817:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
                   75818:                "$name as $newpkgfile");
                   75819:         }
                   75820:         fwrite($np, $this->toXml($state));
                   75821:         fclose($np);
                   75822:         return $newpkgfile;
                   75823:     }
                   75824: 
                   75825:     function &toV2()
                   75826:     {
                   75827:         return $this->_packagefile;
                   75828:     }
                   75829: 
                   75830:     /**
                   75831:      * Return an XML document based on the package info (as returned
                   75832:      * by the PEAR_Common::infoFrom* methods).
                   75833:      *
                   75834:      * @return string XML data
                   75835:      */
                   75836:     function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
                   75837:     {
                   75838:         $this->_packagefile->setDate(date('Y-m-d'));
                   75839:         $this->_packagefile->setTime(date('H:i:s'));
                   75840:         if (!$this->_packagefile->validate($state)) {
                   75841:             return false;
                   75842:         }
                   75843: 
                   75844:         if (is_array($options)) {
                   75845:             $this->options = array_merge($this->_defaultOptions, $options);
                   75846:         } else {
                   75847:             $this->options = $this->_defaultOptions;
                   75848:         }
                   75849: 
                   75850:         $arr = $this->_packagefile->getArray();
                   75851:         if (isset($arr['filelist'])) {
                   75852:             unset($arr['filelist']);
                   75853:         }
                   75854: 
                   75855:         if (isset($arr['_lastversion'])) {
                   75856:             unset($arr['_lastversion']);
                   75857:         }
                   75858: 
                   75859:         // Fix the notes a little bit
                   75860:         if (isset($arr['notes'])) {
                   75861:             // This trims out the indenting, needs fixing
                   75862:             $arr['notes'] = "\n" . trim($arr['notes']) . "\n";
                   75863:         }
                   75864: 
                   75865:         if (isset($arr['changelog']) && !empty($arr['changelog'])) {
                   75866:             // Fix for inconsistency how the array is filled depending on the changelog release amount
                   75867:             if (!isset($arr['changelog']['release'][0])) {
                   75868:                 $release = $arr['changelog']['release'];
                   75869:                 unset($arr['changelog']['release']);
                   75870: 
                   75871:                 $arr['changelog']['release']    = array();
                   75872:                 $arr['changelog']['release'][0] = $release;
                   75873:             }
                   75874: 
                   75875:             foreach (array_keys($arr['changelog']['release']) as $key) {
                   75876:                 $c =& $arr['changelog']['release'][$key];
                   75877:                 if (isset($c['notes'])) {
                   75878:                     // This trims out the indenting, needs fixing
                   75879:                     $c['notes'] = "\n" . trim($c['notes']) . "\n";
                   75880:                 }
                   75881:             }
                   75882:         }
                   75883: 
                   75884:         if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
                   75885:             $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
                   75886:             unset($arr['contents']['dir']['file']);
                   75887:             if (isset($use['dir'])) {
                   75888:                 $arr['contents']['dir']['dir'] = $use['dir'];
                   75889:             }
                   75890:             if (isset($use['file'])) {
                   75891:                 $arr['contents']['dir']['file'] = $use['file'];
                   75892:             }
                   75893:             $this->options['beautifyFilelist'] = true;
                   75894:         }
                   75895: 
                   75896:         $arr['attribs']['packagerversion'] = '1.10.0beta1';
                   75897:         if ($this->serialize($arr, $options)) {
                   75898:             return $this->_serializedData . "\n";
                   75899:         }
                   75900: 
                   75901:         return false;
                   75902:     }
                   75903: 
                   75904: 
                   75905:     function _recursiveXmlFilelist($list)
                   75906:     {
                   75907:         $dirs = array();
                   75908:         if (isset($list['attribs'])) {
                   75909:             $file = $list['attribs']['name'];
                   75910:             unset($list['attribs']['name']);
                   75911:             $attributes = $list['attribs'];
                   75912:             $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
                   75913:         } else {
                   75914:             foreach ($list as $a) {
                   75915:                 $file = $a['attribs']['name'];
                   75916:                 $attributes = $a['attribs'];
                   75917:                 unset($a['attribs']);
                   75918:                 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
                   75919:             }
                   75920:         }
                   75921:         $this->_formatDir($dirs);
                   75922:         $this->_deFormat($dirs);
                   75923:         return $dirs;
                   75924:     }
                   75925: 
                   75926:     function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
                   75927:     {
                   75928:         if (!$tasks) {
                   75929:             $tasks = array();
                   75930:         }
                   75931:         if ($dir == array() || $dir == array('.')) {
                   75932:             $dirs['file'][basename($file)] = $tasks;
                   75933:             $attributes['name'] = basename($file);
                   75934:             $dirs['file'][basename($file)]['attribs'] = $attributes;
                   75935:             return;
                   75936:         }
                   75937:         $curdir = array_shift($dir);
                   75938:         if (!isset($dirs['dir'][$curdir])) {
                   75939:             $dirs['dir'][$curdir] = array();
                   75940:         }
                   75941:         $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
                   75942:     }
                   75943: 
                   75944:     function _formatDir(&$dirs)
                   75945:     {
                   75946:         if (!count($dirs)) {
                   75947:             return array();
                   75948:         }
                   75949:         $newdirs = array();
                   75950:         if (isset($dirs['dir'])) {
                   75951:             $newdirs['dir'] = $dirs['dir'];
                   75952:         }
                   75953:         if (isset($dirs['file'])) {
                   75954:             $newdirs['file'] = $dirs['file'];
                   75955:         }
                   75956:         $dirs = $newdirs;
                   75957:         if (isset($dirs['dir'])) {
                   75958:             uksort($dirs['dir'], 'strnatcasecmp');
                   75959:             foreach ($dirs['dir'] as $dir => $contents) {
                   75960:                 $this->_formatDir($dirs['dir'][$dir]);
                   75961:             }
                   75962:         }
                   75963:         if (isset($dirs['file'])) {
                   75964:             uksort($dirs['file'], 'strnatcasecmp');
                   75965:         };
                   75966:     }
                   75967: 
                   75968:     function _deFormat(&$dirs)
                   75969:     {
                   75970:         if (!count($dirs)) {
                   75971:             return array();
                   75972:         }
                   75973:         $newdirs = array();
                   75974:         if (isset($dirs['dir'])) {
                   75975:             foreach ($dirs['dir'] as $dir => $contents) {
                   75976:                 $newdir = array();
                   75977:                 $newdir['attribs']['name'] = $dir;
                   75978:                 $this->_deFormat($contents);
                   75979:                 foreach ($contents as $tag => $val) {
                   75980:                     $newdir[$tag] = $val;
                   75981:                 }
                   75982:                 $newdirs['dir'][] = $newdir;
                   75983:             }
                   75984:             if (count($newdirs['dir']) == 1) {
                   75985:                 $newdirs['dir'] = $newdirs['dir'][0];
                   75986:             }
                   75987:         }
                   75988:         if (isset($dirs['file'])) {
                   75989:             foreach ($dirs['file'] as $name => $file) {
                   75990:                 $newdirs['file'][] = $file;
                   75991:             }
                   75992:             if (count($newdirs['file']) == 1) {
                   75993:                 $newdirs['file'] = $newdirs['file'][0];
                   75994:             }
                   75995:         }
                   75996:         $dirs = $newdirs;
                   75997:     }
                   75998: 
                   75999:     /**
                   76000:     * reset all options to default options
                   76001:     *
                   76002:     * @access   public
                   76003:     * @see      setOption(), XML_Unserializer()
                   76004:     */
                   76005:     function resetOptions()
                   76006:     {
                   76007:         $this->options = $this->_defaultOptions;
                   76008:     }
                   76009: 
                   76010:    /**
                   76011:     * set an option
                   76012:     *
                   76013:     * You can use this method if you do not want to set all options in the constructor
                   76014:     *
                   76015:     * @access   public
                   76016:     * @see      resetOption(), XML_Serializer()
                   76017:     */
                   76018:     function setOption($name, $value)
                   76019:     {
                   76020:         $this->options[$name] = $value;
                   76021:     }
                   76022: 
                   76023:    /**
                   76024:     * sets several options at once
                   76025:     *
                   76026:     * You can use this method if you do not want to set all options in the constructor
                   76027:     *
                   76028:     * @access   public
                   76029:     * @see      resetOption(), XML_Unserializer(), setOption()
                   76030:     */
                   76031:     function setOptions($options)
                   76032:     {
                   76033:         $this->options = array_merge($this->options, $options);
                   76034:     }
                   76035: 
                   76036:    /**
                   76037:     * serialize data
                   76038:     *
                   76039:     * @access   public
                   76040:     * @param    mixed    $data data to serialize
                   76041:     * @return   boolean  true on success, pear error on failure
                   76042:     */
                   76043:     function serialize($data, $options = null)
                   76044:     {
                   76045:         // if options have been specified, use them instead
                   76046:         // of the previously defined ones
                   76047:         if (is_array($options)) {
                   76048:             $optionsBak = $this->options;
                   76049:             if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
                   76050:                 $this->options = array_merge($this->_defaultOptions, $options);
                   76051:             } else {
                   76052:                 $this->options = array_merge($this->options, $options);
                   76053:             }
                   76054:         } else {
                   76055:             $optionsBak = null;
                   76056:         }
                   76057: 
                   76058:         //  start depth is zero
                   76059:         $this->_tagDepth = 0;
                   76060:         $this->_serializedData = '';
                   76061:         // serialize an array
                   76062:         if (is_array($data)) {
                   76063:             $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
                   76064:             $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
                   76065:         }
                   76066: 
                   76067:         // add doctype declaration
                   76068:         if ($this->options['addDoctype'] === true) {
                   76069:             $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
                   76070:                                    . $this->options['linebreak']
                   76071:                                    . $this->_serializedData;
                   76072:         }
                   76073: 
                   76074:         //  build xml declaration
                   76075:         if ($this->options['addDecl']) {
                   76076:             $atts = array();
                   76077:             $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
                   76078:             $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
                   76079:                                    . $this->options['linebreak']
                   76080:                                    . $this->_serializedData;
                   76081:         }
                   76082: 
                   76083: 
                   76084:         if ($optionsBak !== null) {
                   76085:             $this->options = $optionsBak;
                   76086:         }
                   76087: 
                   76088:         return  true;
                   76089:     }
                   76090: 
                   76091:    /**
                   76092:     * get the result of the serialization
                   76093:     *
                   76094:     * @access public
                   76095:     * @return string serialized XML
                   76096:     */
                   76097:     function getSerializedData()
                   76098:     {
                   76099:         if ($this->_serializedData === null) {
                   76100:             return  $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
                   76101:         }
                   76102:         return $this->_serializedData;
                   76103:     }
                   76104: 
                   76105:    /**
                   76106:     * serialize any value
                   76107:     *
                   76108:     * This method checks for the type of the value and calls the appropriate method
                   76109:     *
                   76110:     * @access private
                   76111:     * @param  mixed     $value
                   76112:     * @param  string    $tagName
                   76113:     * @param  array     $attributes
                   76114:     * @return string
                   76115:     */
                   76116:     function _serializeValue($value, $tagName = null, $attributes = array())
                   76117:     {
                   76118:         if (is_array($value)) {
                   76119:             $xml = $this->_serializeArray($value, $tagName, $attributes);
                   76120:         } elseif (is_object($value)) {
                   76121:             $xml = $this->_serializeObject($value, $tagName);
                   76122:         } else {
                   76123:             $tag = array(
                   76124:                           'qname'      => $tagName,
                   76125:                           'attributes' => $attributes,
                   76126:                           'content'    => $value
                   76127:                         );
                   76128:             $xml = $this->_createXMLTag($tag);
                   76129:         }
                   76130:         return $xml;
                   76131:     }
                   76132: 
                   76133:    /**
                   76134:     * serialize an array
                   76135:     *
                   76136:     * @access   private
                   76137:     * @param    array   $array       array to serialize
                   76138:     * @param    string  $tagName     name of the root tag
                   76139:     * @param    array   $attributes  attributes for the root tag
                   76140:     * @return   string  $string      serialized data
                   76141:     * @uses     XML_Util::isValidName() to check, whether key has to be substituted
                   76142:     */
                   76143:     function _serializeArray(&$array, $tagName = null, $attributes = array())
                   76144:     {
                   76145:         $_content = null;
                   76146: 
                   76147:         /**
                   76148:          * check for special attributes
                   76149:          */
                   76150:         if ($this->options['attributesArray'] !== null) {
                   76151:             if (isset($array[$this->options['attributesArray']])) {
                   76152:                 $attributes = $array[$this->options['attributesArray']];
                   76153:                 unset($array[$this->options['attributesArray']]);
                   76154:             }
                   76155:             /**
                   76156:              * check for special content
                   76157:              */
                   76158:             if ($this->options['contentName'] !== null) {
                   76159:                 if (isset($array[$this->options['contentName']])) {
                   76160:                     $_content = $array[$this->options['contentName']];
                   76161:                     unset($array[$this->options['contentName']]);
                   76162:                 }
                   76163:             }
                   76164:         }
                   76165: 
                   76166:         /*
                   76167:         * if mode is set to simpleXML, check whether
                   76168:         * the array is associative or indexed
                   76169:         */
                   76170:         if (is_array($array) && $this->options['mode'] == 'simplexml') {
                   76171:             $indexed = true;
                   76172:             if (!count($array)) {
                   76173:                 $indexed = false;
                   76174:             }
                   76175:             foreach ($array as $key => $val) {
                   76176:                 if (!is_int($key)) {
                   76177:                     $indexed = false;
                   76178:                     break;
                   76179:                 }
                   76180:             }
                   76181: 
                   76182:             if ($indexed && $this->options['mode'] == 'simplexml') {
                   76183:                 $string = '';
                   76184:                 foreach ($array as $key => $val) {
                   76185:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   76186:                         if (!isset($this->_curdir)) {
                   76187:                             $this->_curdir = '';
                   76188:                         }
                   76189:                         $savedir = $this->_curdir;
                   76190:                         if (isset($val['attribs'])) {
                   76191:                             if ($val['attribs']['name'] == '/') {
                   76192:                                 $this->_curdir = '/';
                   76193:                             } else {
                   76194:                                 if ($this->_curdir == '/') {
                   76195:                                     $this->_curdir = '';
                   76196:                                 }
                   76197:                                 $this->_curdir .= '/' . $val['attribs']['name'];
                   76198:                             }
                   76199:                         }
                   76200:                     }
                   76201:                     $string .= $this->_serializeValue( $val, $tagName, $attributes);
                   76202:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   76203:                         $string .= ' <!-- ' . $this->_curdir . ' -->';
                   76204:                         if (empty($savedir)) {
                   76205:                             unset($this->_curdir);
                   76206:                         } else {
                   76207:                             $this->_curdir = $savedir;
                   76208:                         }
                   76209:                     }
                   76210: 
                   76211:                     $string .= $this->options['linebreak'];
                   76212:                     // do indentation
                   76213:                     if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   76214:                         $string .= str_repeat($this->options['indent'], $this->_tagDepth);
                   76215:                     }
                   76216:                 }
                   76217:                 return rtrim($string);
                   76218:             }
                   76219:         }
                   76220: 
                   76221:         if ($this->options['scalarAsAttributes'] === true) {
                   76222:             foreach ($array as $key => $value) {
                   76223:                 if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
                   76224:                     unset($array[$key]);
                   76225:                     $attributes[$this->options['prependAttributes'].$key] = $value;
                   76226:                 }
                   76227:             }
                   76228:         }
                   76229: 
                   76230:         // check for empty array => create empty tag
                   76231:         if (empty($array)) {
                   76232:             $tag = array(
                   76233:                             'qname'      => $tagName,
                   76234:                             'content'    => $_content,
                   76235:                             'attributes' => $attributes
                   76236:                         );
                   76237: 
                   76238:         } else {
                   76239:             $this->_tagDepth++;
                   76240:             $tmp = $this->options['linebreak'];
                   76241:             foreach ($array as $key => $value) {
                   76242:                 // do indentation
                   76243:                 if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   76244:                     $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   76245:                 }
                   76246: 
                   76247:                 // copy key
                   76248:                 $origKey = $key;
                   76249:                 // key cannot be used as tagname => use default tag
                   76250:                 $valid = XML_Util::isValidName($key);
                   76251:                 if (PEAR::isError($valid)) {
                   76252:                     if ($this->options['classAsTagName'] && is_object($value)) {
                   76253:                         $key = get_class($value);
                   76254:                     } else {
                   76255:                         $key = $this->options['defaultTagName'];
                   76256:                     }
                   76257:                 }
                   76258:                 $atts = array();
                   76259:                 if ($this->options['typeHints'] === true) {
                   76260:                     $atts[$this->options['typeAttribute']] = gettype($value);
                   76261:                     if ($key !== $origKey) {
                   76262:                         $atts[$this->options['keyAttribute']] = (string)$origKey;
                   76263:                     }
                   76264: 
                   76265:                 }
                   76266:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   76267:                     if (!isset($this->_curdir)) {
                   76268:                         $this->_curdir = '';
                   76269:                     }
                   76270:                     $savedir = $this->_curdir;
                   76271:                     if (isset($value['attribs'])) {
                   76272:                         if ($value['attribs']['name'] == '/') {
                   76273:                             $this->_curdir = '/';
                   76274:                         } else {
                   76275:                             $this->_curdir .= '/' . $value['attribs']['name'];
                   76276:                         }
                   76277:                     }
                   76278:                 }
                   76279: 
                   76280:                 if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
                   76281:                     $value .= str_repeat($this->options['indent'], $this->_tagDepth);
                   76282:                 }
                   76283:                 $tmp .= $this->_createXMLTag(array(
                   76284:                                                     'qname'      => $key,
                   76285:                                                     'attributes' => $atts,
                   76286:                                                     'content'    => $value )
                   76287:                                             );
                   76288:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   76289:                     if (isset($value['attribs'])) {
                   76290:                         $tmp .= ' <!-- ' . $this->_curdir . ' -->';
                   76291:                         if (empty($savedir)) {
                   76292:                             unset($this->_curdir);
                   76293:                         } else {
                   76294:                             $this->_curdir = $savedir;
                   76295:                         }
                   76296:                     }
                   76297:                 }
                   76298:                 $tmp .= $this->options['linebreak'];
                   76299:             }
                   76300: 
                   76301:             $this->_tagDepth--;
                   76302:             if ($this->options['indent']!==null && $this->_tagDepth>0) {
                   76303:                 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   76304:             }
                   76305: 
                   76306:             if (trim($tmp) === '') {
                   76307:                 $tmp = null;
                   76308:             }
                   76309: 
                   76310:             $tag = array(
                   76311:                 'qname'      => $tagName,
                   76312:                 'content'    => $tmp,
                   76313:                 'attributes' => $attributes
                   76314:             );
                   76315:         }
                   76316:         if ($this->options['typeHints'] === true) {
                   76317:             if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
                   76318:                 $tag['attributes'][$this->options['typeAttribute']] = 'array';
                   76319:             }
                   76320:         }
                   76321: 
                   76322:         $string = $this->_createXMLTag($tag, false);
                   76323:         return $string;
                   76324:     }
                   76325: 
                   76326:    /**
                   76327:     * create a tag from an array
                   76328:     * this method awaits an array in the following format
                   76329:     * array(
                   76330:     *       'qname'        => $tagName,
                   76331:     *       'attributes'   => array(),
                   76332:     *       'content'      => $content,      // optional
                   76333:     *       'namespace'    => $namespace     // optional
                   76334:     *       'namespaceUri' => $namespaceUri  // optional
                   76335:     *   )
                   76336:     *
                   76337:     * @access   private
                   76338:     * @param    array   $tag tag definition
                   76339:     * @param    boolean $replaceEntities whether to replace XML entities in content or not
                   76340:     * @return   string  $string XML tag
                   76341:     */
                   76342:     function _createXMLTag($tag, $replaceEntities = true)
                   76343:     {
                   76344:         if ($this->options['indentAttributes'] !== false) {
                   76345:             $multiline = true;
                   76346:             $indent    = str_repeat($this->options['indent'], $this->_tagDepth);
                   76347: 
                   76348:             if ($this->options['indentAttributes'] == '_auto') {
                   76349:                 $indent .= str_repeat(' ', (strlen($tag['qname'])+2));
                   76350: 
                   76351:             } else {
                   76352:                 $indent .= $this->options['indentAttributes'];
                   76353:             }
                   76354:         } else {
                   76355:             $indent = $multiline = false;
                   76356:         }
                   76357: 
                   76358:         if (is_array($tag['content'])) {
                   76359:             if (empty($tag['content'])) {
                   76360:                 $tag['content'] = '';
                   76361:             }
                   76362:         } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
                   76363:             $tag['content'] = '';
                   76364:         }
                   76365: 
                   76366:         if (is_scalar($tag['content']) || is_null($tag['content'])) {
                   76367:             if ($this->options['encoding'] == 'UTF-8' &&
                   76368:                   version_compare(phpversion(), '5.0.0', 'lt')
                   76369:             ) {
                   76370:                 $tag['content'] = utf8_encode($tag['content']);
                   76371:             }
                   76372: 
                   76373:             if ($replaceEntities === true) {
                   76374:                 $replaceEntities = XML_UTIL_ENTITIES_XML;
                   76375:             }
                   76376: 
                   76377:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
                   76378:         } elseif (is_array($tag['content'])) {
                   76379:             $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
                   76380:         } elseif (is_object($tag['content'])) {
                   76381:             $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
                   76382:         } elseif (is_resource($tag['content'])) {
                   76383:             settype($tag['content'], 'string');
                   76384:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities);
                   76385:         }
                   76386:         return  $tag;
                   76387:     }
                   76388: }<?php
                   76389: /**
                   76390:  * package.xml parsing class, package.xml version 1.0
                   76391:  *
                   76392:  * PHP versions 4 and 5
                   76393:  *
                   76394:  * @category   pear
                   76395:  * @package    PEAR
                   76396:  * @author     Greg Beaver <cellog@php.net>
                   76397:  * @copyright  1997-2009 The Authors
                   76398:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   76399:  * @version    CVS: $Id: v1.php 276385 2009-02-24 23:46:03Z dufuz $
                   76400:  * @link       http://pear.php.net/package/PEAR
                   76401:  * @since      File available since Release 1.4.0a1
                   76402:  */
                   76403: /**
                   76404:  * package.xml abstraction class
                   76405:  */
                   76406: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   76407: /**
                   76408:  * Parser for package.xml version 1.0
                   76409:  * @category   pear
                   76410:  * @package    PEAR
                   76411:  * @author     Greg Beaver <cellog@php.net>
                   76412:  * @copyright  1997-2009 The Authors
                   76413:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   76414:  * @version    Release: 1.10.0beta1
                   76415:  * @link       http://pear.php.net/package/PEAR
                   76416:  * @since      Class available since Release 1.4.0a1
                   76417:  */
                   76418: class PEAR_PackageFile_Parser_v1
                   76419: {
                   76420:     var $_registry;
                   76421:     var $_config;
                   76422:     var $_logger;
                   76423:     /**
                   76424:      * BC hack to allow PEAR_Common::infoFromString() to sort of
                   76425:      * work with the version 2.0 format - there's no filelist though
                   76426:      * @param PEAR_PackageFile_v2
                   76427:      */
                   76428:     function fromV2($packagefile)
                   76429:     {
                   76430:         $info = $packagefile->getArray(true);
                   76431:         $ret = new PEAR_PackageFile_v1;
                   76432:         $ret->fromArray($info['old']);
                   76433:     }
                   76434: 
                   76435:     function setConfig(&$c)
                   76436:     {
                   76437:         $this->_config = &$c;
                   76438:         $this->_registry = &$c->getRegistry();
                   76439:     }
                   76440: 
                   76441:     function setLogger(&$l)
                   76442:     {
                   76443:         $this->_logger = &$l;
                   76444:     }
                   76445: 
                   76446:     /**
                   76447:      * @param string contents of package.xml file, version 1.0
                   76448:      * @return bool success of parsing
                   76449:      */
                   76450:     function &parse($data, $file, $archive = false)
                   76451:     {
                   76452:         if (!extension_loaded('xml')) {
                   76453:             return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
                   76454:         }
                   76455:         $xp = xml_parser_create();
                   76456:         if (!$xp) {
                   76457:             $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
                   76458:             return $a;
                   76459:         }
                   76460:         xml_set_object($xp, $this);
                   76461:         xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
                   76462:         xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
                   76463:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
                   76464: 
                   76465:         $this->element_stack = array();
                   76466:         $this->_packageInfo = array('provides' => array());
                   76467:         $this->current_element = false;
                   76468:         unset($this->dir_install);
                   76469:         $this->_packageInfo['filelist'] = array();
                   76470:         $this->filelist =& $this->_packageInfo['filelist'];
                   76471:         $this->dir_names = array();
                   76472:         $this->in_changelog = false;
                   76473:         $this->d_i = 0;
                   76474:         $this->cdata = '';
                   76475:         $this->_isValid = true;
                   76476: 
                   76477:         if (!xml_parse($xp, $data, 1)) {
                   76478:             $code = xml_get_error_code($xp);
                   76479:             $line = xml_get_current_line_number($xp);
                   76480:             xml_parser_free($xp);
                   76481:             $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
                   76482:                            $str = xml_error_string($code), $line), 2);
                   76483:             return $a;
                   76484:         }
                   76485: 
                   76486:         xml_parser_free($xp);
                   76487: 
                   76488:         $pf = new PEAR_PackageFile_v1;
                   76489:         $pf->setConfig($this->_config);
                   76490:         if (isset($this->_logger)) {
                   76491:             $pf->setLogger($this->_logger);
                   76492:         }
                   76493:         $pf->setPackagefile($file, $archive);
                   76494:         $pf->fromArray($this->_packageInfo);
                   76495:         return $pf;
                   76496:     }
                   76497:     // {{{ _unIndent()
                   76498: 
                   76499:     /**
                   76500:      * Unindent given string
                   76501:      *
                   76502:      * @param string $str The string that has to be unindented.
                   76503:      * @return string
                   76504:      * @access private
                   76505:      */
                   76506:     function _unIndent($str)
                   76507:     {
                   76508:         // remove leading newlines
                   76509:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   76510:         // find whitespace at the beginning of the first line
                   76511:         $indent_len = strspn($str, " \t");
                   76512:         $indent = substr($str, 0, $indent_len);
                   76513:         $data = '';
                   76514:         // remove the same amount of whitespace from following lines
                   76515:         foreach (explode("\n", $str) as $line) {
                   76516:             if (substr($line, 0, $indent_len) == $indent) {
                   76517:                 $data .= substr($line, $indent_len) . "\n";
                   76518:             } elseif (trim(substr($line, 0, $indent_len))) {
                   76519:                 $data .= ltrim($line);
                   76520:             }
                   76521:         }
                   76522:         return $data;
                   76523:     }
                   76524: 
                   76525:     // Support for package DTD v1.0:
                   76526:     // {{{ _element_start_1_0()
                   76527: 
                   76528:     /**
                   76529:      * XML parser callback for ending elements.  Used for version 1.0
                   76530:      * packages.
                   76531:      *
                   76532:      * @param resource  $xp    XML parser resource
                   76533:      * @param string    $name  name of ending element
                   76534:      *
                   76535:      * @return void
                   76536:      *
                   76537:      * @access private
                   76538:      */
                   76539:     function _element_start_1_0($xp, $name, $attribs)
                   76540:     {
                   76541:         array_push($this->element_stack, $name);
                   76542:         $this->current_element = $name;
                   76543:         $spos = sizeof($this->element_stack) - 2;
                   76544:         $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
                   76545:         $this->current_attributes = $attribs;
                   76546:         $this->cdata = '';
                   76547:         switch ($name) {
                   76548:             case 'dir':
                   76549:                 if ($this->in_changelog) {
                   76550:                     break;
                   76551:                 }
                   76552:                 if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
                   76553:                     $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   76554:                         $attribs['name']);
                   76555:                     if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
                   76556:                         $attribs['name'] = substr($attribs['name'], 0,
                   76557:                             strlen($attribs['name']) - 1);
                   76558:                     }
                   76559:                     if (strpos($attribs['name'], '/') === 0) {
                   76560:                         $attribs['name'] = substr($attribs['name'], 1);
                   76561:                     }
                   76562:                     $this->dir_names[] = $attribs['name'];
                   76563:                 }
                   76564:                 if (isset($attribs['baseinstalldir'])) {
                   76565:                     $this->dir_install = $attribs['baseinstalldir'];
                   76566:                 }
                   76567:                 if (isset($attribs['role'])) {
                   76568:                     $this->dir_role = $attribs['role'];
                   76569:                 }
                   76570:                 break;
                   76571:             case 'file':
                   76572:                 if ($this->in_changelog) {
                   76573:                     break;
                   76574:                 }
                   76575:                 if (isset($attribs['name'])) {
                   76576:                     $path = '';
                   76577:                     if (count($this->dir_names)) {
                   76578:                         foreach ($this->dir_names as $dir) {
                   76579:                             $path .= $dir . '/';
                   76580:                         }
                   76581:                     }
                   76582:                     $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   76583:                         $attribs['name']);
                   76584:                     unset($attribs['name']);
                   76585:                     $this->current_path = $path;
                   76586:                     $this->filelist[$path] = $attribs;
                   76587:                     // Set the baseinstalldir only if the file don't have this attrib
                   76588:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   76589:                         isset($this->dir_install))
                   76590:                     {
                   76591:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   76592:                     }
                   76593:                     // Set the Role
                   76594:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   76595:                         $this->filelist[$path]['role'] = $this->dir_role;
                   76596:                     }
                   76597:                 }
                   76598:                 break;
                   76599:             case 'replace':
                   76600:                 if (!$this->in_changelog) {
                   76601:                     $this->filelist[$this->current_path]['replacements'][] = $attribs;
                   76602:                 }
                   76603:                 break;
                   76604:             case 'maintainers':
                   76605:                 $this->_packageInfo['maintainers'] = array();
                   76606:                 $this->m_i = 0; // maintainers array index
                   76607:                 break;
                   76608:             case 'maintainer':
                   76609:                 // compatibility check
                   76610:                 if (!isset($this->_packageInfo['maintainers'])) {
                   76611:                     $this->_packageInfo['maintainers'] = array();
                   76612:                     $this->m_i = 0;
                   76613:                 }
                   76614:                 $this->_packageInfo['maintainers'][$this->m_i] = array();
                   76615:                 $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
                   76616:                 break;
                   76617:             case 'changelog':
                   76618:                 $this->_packageInfo['changelog'] = array();
                   76619:                 $this->c_i = 0; // changelog array index
                   76620:                 $this->in_changelog = true;
                   76621:                 break;
                   76622:             case 'release':
                   76623:                 if ($this->in_changelog) {
                   76624:                     $this->_packageInfo['changelog'][$this->c_i] = array();
                   76625:                     $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
                   76626:                 } else {
                   76627:                     $this->current_release = &$this->_packageInfo;
                   76628:                 }
                   76629:                 break;
                   76630:             case 'deps':
                   76631:                 if (!$this->in_changelog) {
                   76632:                     $this->_packageInfo['release_deps'] = array();
                   76633:                 }
                   76634:                 break;
                   76635:             case 'dep':
                   76636:                 // dependencies array index
                   76637:                 if (!$this->in_changelog) {
                   76638:                     $this->d_i++;
                   76639:                     isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
                   76640:                     $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
                   76641:                 }
                   76642:                 break;
                   76643:             case 'configureoptions':
                   76644:                 if (!$this->in_changelog) {
                   76645:                     $this->_packageInfo['configure_options'] = array();
                   76646:                 }
                   76647:                 break;
                   76648:             case 'configureoption':
                   76649:                 if (!$this->in_changelog) {
                   76650:                     $this->_packageInfo['configure_options'][] = $attribs;
                   76651:                 }
                   76652:                 break;
                   76653:             case 'provides':
                   76654:                 if (empty($attribs['type']) || empty($attribs['name'])) {
                   76655:                     break;
                   76656:                 }
                   76657:                 $attribs['explicit'] = true;
                   76658:                 $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
                   76659:                 break;
                   76660:             case 'package' :
                   76661:                 if (isset($attribs['version'])) {
                   76662:                     $this->_packageInfo['xsdversion'] = trim($attribs['version']);
                   76663:                 } else {
                   76664:                     $this->_packageInfo['xsdversion'] = '1.0';
                   76665:                 }
                   76666:                 if (isset($attribs['packagerversion'])) {
                   76667:                     $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
                   76668:                 }
                   76669:                 break;
                   76670:         }
                   76671:     }
                   76672: 
                   76673:     // }}}
                   76674:     // {{{ _element_end_1_0()
                   76675: 
                   76676:     /**
                   76677:      * XML parser callback for ending elements.  Used for version 1.0
                   76678:      * packages.
                   76679:      *
                   76680:      * @param resource  $xp    XML parser resource
                   76681:      * @param string    $name  name of ending element
                   76682:      *
                   76683:      * @return void
                   76684:      *
                   76685:      * @access private
                   76686:      */
                   76687:     function _element_end_1_0($xp, $name)
                   76688:     {
                   76689:         $data = trim($this->cdata);
                   76690:         switch ($name) {
                   76691:             case 'name':
                   76692:                 switch ($this->prev_element) {
                   76693:                     case 'package':
                   76694:                         $this->_packageInfo['package'] = $data;
                   76695:                         break;
                   76696:                     case 'maintainer':
                   76697:                         $this->current_maintainer['name'] = $data;
                   76698:                         break;
                   76699:                 }
                   76700:                 break;
                   76701:             case 'extends' :
                   76702:                 $this->_packageInfo['extends'] = $data;
                   76703:                 break;
                   76704:             case 'summary':
                   76705:                 $this->_packageInfo['summary'] = $data;
                   76706:                 break;
                   76707:             case 'description':
                   76708:                 $data = $this->_unIndent($this->cdata);
                   76709:                 $this->_packageInfo['description'] = $data;
                   76710:                 break;
                   76711:             case 'user':
                   76712:                 $this->current_maintainer['handle'] = $data;
                   76713:                 break;
                   76714:             case 'email':
                   76715:                 $this->current_maintainer['email'] = $data;
                   76716:                 break;
                   76717:             case 'role':
                   76718:                 $this->current_maintainer['role'] = $data;
                   76719:                 break;
                   76720:             case 'version':
                   76721:                 if ($this->in_changelog) {
                   76722:                     $this->current_release['version'] = $data;
                   76723:                 } else {
                   76724:                     $this->_packageInfo['version'] = $data;
                   76725:                 }
                   76726:                 break;
                   76727:             case 'date':
                   76728:                 if ($this->in_changelog) {
                   76729:                     $this->current_release['release_date'] = $data;
                   76730:                 } else {
                   76731:                     $this->_packageInfo['release_date'] = $data;
                   76732:                 }
                   76733:                 break;
                   76734:             case 'notes':
                   76735:                 // try to "de-indent" release notes in case someone
                   76736:                 // has been over-indenting their xml ;-)
                   76737:                 // Trim only on the right side
                   76738:                 $data = rtrim($this->_unIndent($this->cdata));
                   76739:                 if ($this->in_changelog) {
                   76740:                     $this->current_release['release_notes'] = $data;
                   76741:                 } else {
                   76742:                     $this->_packageInfo['release_notes'] = $data;
                   76743:                 }
                   76744:                 break;
                   76745:             case 'warnings':
                   76746:                 if ($this->in_changelog) {
                   76747:                     $this->current_release['release_warnings'] = $data;
                   76748:                 } else {
                   76749:                     $this->_packageInfo['release_warnings'] = $data;
                   76750:                 }
                   76751:                 break;
                   76752:             case 'state':
                   76753:                 if ($this->in_changelog) {
                   76754:                     $this->current_release['release_state'] = $data;
                   76755:                 } else {
                   76756:                     $this->_packageInfo['release_state'] = $data;
                   76757:                 }
                   76758:                 break;
                   76759:             case 'license':
                   76760:                 if ($this->in_changelog) {
                   76761:                     $this->current_release['release_license'] = $data;
                   76762:                 } else {
                   76763:                     $this->_packageInfo['release_license'] = $data;
                   76764:                 }
                   76765:                 break;
                   76766:             case 'dep':
                   76767:                 if ($data && !$this->in_changelog) {
                   76768:                     $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
                   76769:                 }
                   76770:                 break;
                   76771:             case 'dir':
                   76772:                 if ($this->in_changelog) {
                   76773:                     break;
                   76774:                 }
                   76775:                 array_pop($this->dir_names);
                   76776:                 break;
                   76777:             case 'file':
                   76778:                 if ($this->in_changelog) {
                   76779:                     break;
                   76780:                 }
                   76781:                 if ($data) {
                   76782:                     $path = '';
                   76783:                     if (count($this->dir_names)) {
                   76784:                         foreach ($this->dir_names as $dir) {
                   76785:                             $path .= $dir . '/';
                   76786:                         }
                   76787:                     }
                   76788:                     $path .= $data;
                   76789:                     $this->filelist[$path] = $this->current_attributes;
                   76790:                     // Set the baseinstalldir only if the file don't have this attrib
                   76791:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   76792:                         isset($this->dir_install))
                   76793:                     {
                   76794:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   76795:                     }
                   76796:                     // Set the Role
                   76797:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   76798:                         $this->filelist[$path]['role'] = $this->dir_role;
                   76799:                     }
                   76800:                 }
                   76801:                 break;
                   76802:             case 'maintainer':
                   76803:                 if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
                   76804:                     $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
                   76805:                 }
                   76806:                 $this->m_i++;
                   76807:                 break;
                   76808:             case 'release':
                   76809:                 if ($this->in_changelog) {
                   76810:                     $this->c_i++;
                   76811:                 }
                   76812:                 break;
                   76813:             case 'changelog':
                   76814:                 $this->in_changelog = false;
                   76815:                 break;
                   76816:         }
                   76817:         array_pop($this->element_stack);
                   76818:         $spos = sizeof($this->element_stack) - 1;
                   76819:         $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
                   76820:         $this->cdata = '';
                   76821:     }
                   76822: 
                   76823:     // }}}
                   76824:     // {{{ _pkginfo_cdata_1_0()
                   76825: 
                   76826:     /**
                   76827:      * XML parser callback for character data.  Used for version 1.0
                   76828:      * packages.
                   76829:      *
                   76830:      * @param resource  $xp    XML parser resource
                   76831:      * @param string    $name  character data
                   76832:      *
                   76833:      * @return void
                   76834:      *
                   76835:      * @access private
                   76836:      */
                   76837:     function _pkginfo_cdata_1_0($xp, $data)
                   76838:     {
                   76839:         if (isset($this->cdata)) {
                   76840:             $this->cdata .= $data;
                   76841:         }
                   76842:     }
                   76843: 
                   76844:     // }}}
                   76845: }
                   76846: ?><?php
                   76847: /**
                   76848:  * package.xml parsing class, package.xml version 2.0
                   76849:  *
                   76850:  * PHP versions 4 and 5
                   76851:  *
                   76852:  * @category   pear
                   76853:  * @package    PEAR
                   76854:  * @author     Greg Beaver <cellog@php.net>
                   76855:  * @copyright  1997-2009 The Authors
                   76856:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   76857:  * @version    CVS: $Id: v2.php 276385 2009-02-24 23:46:03Z dufuz $
                   76858:  * @link       http://pear.php.net/package/PEAR
                   76859:  * @since      File available since Release 1.4.0a1
                   76860:  */
                   76861: /**
                   76862:  * base xml parser class
                   76863:  */
                   76864: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   76865: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   76866: /**
                   76867:  * Parser for package.xml version 2.0
                   76868:  * @category   pear
                   76869:  * @package    PEAR
                   76870:  * @author     Greg Beaver <cellog@php.net>
                   76871:  * @copyright  1997-2009 The Authors
                   76872:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   76873:  * @version    Release: 1.10.0beta1
                   76874:  * @link       http://pear.php.net/package/PEAR
                   76875:  * @since      Class available since Release 1.4.0a1
                   76876:  */
                   76877: class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
                   76878: {
                   76879:     var $_config;
                   76880:     var $_logger;
                   76881:     var $_registry;
                   76882: 
                   76883:     function setConfig(&$c)
                   76884:     {
                   76885:         $this->_config = &$c;
                   76886:         $this->_registry = &$c->getRegistry();
                   76887:     }
                   76888: 
                   76889:     function setLogger(&$l)
                   76890:     {
                   76891:         $this->_logger = &$l;
                   76892:     }
                   76893:     /**
                   76894:      * Unindent given string
                   76895:      *
                   76896:      * @param string $str The string that has to be unindented.
                   76897:      * @return string
                   76898:      * @access private
                   76899:      */
                   76900:     function _unIndent($str)
                   76901:     {
                   76902:         // remove leading newlines
                   76903:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   76904:         // find whitespace at the beginning of the first line
                   76905:         $indent_len = strspn($str, " \t");
                   76906:         $indent = substr($str, 0, $indent_len);
                   76907:         $data = '';
                   76908:         // remove the same amount of whitespace from following lines
                   76909:         foreach (explode("\n", $str) as $line) {
                   76910:             if (substr($line, 0, $indent_len) == $indent) {
                   76911:                 $data .= substr($line, $indent_len) . "\n";
                   76912:             } else {
                   76913:                 $data .= $line . "\n";
                   76914:             }
                   76915:         }
                   76916:         return $data;
                   76917:     }
                   76918: 
                   76919:     /**
                   76920:      * post-process data
                   76921:      *
                   76922:      * @param string $data
                   76923:      * @param string $element element name
                   76924:      */
                   76925:     function postProcess($data, $element)
                   76926:     {
                   76927:         if ($element == 'notes') {
                   76928:             return trim($this->_unIndent($data));
                   76929:         }
                   76930:         return trim($data);
                   76931:     }
                   76932: 
                   76933:     /**
                   76934:      * @param string
                   76935:      * @param string file name of the package.xml
                   76936:      * @param string|false name of the archive this package.xml came from, if any
                   76937:      * @param string class name to instantiate and return.  This must be PEAR_PackageFile_v2 or
                   76938:      *               a subclass
                   76939:      * @return PEAR_PackageFile_v2
                   76940:      */
                   76941:     function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
                   76942:     {
                   76943:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   76944:             return $err;
                   76945:         }
                   76946: 
                   76947:         $ret = new $class;
                   76948:         $ret->encoding = $this->encoding;
                   76949:         $ret->setConfig($this->_config);
                   76950:         if (isset($this->_logger)) {
                   76951:             $ret->setLogger($this->_logger);
                   76952:         }
                   76953: 
                   76954:         $ret->fromArray($this->_unserializedData);
                   76955:         $ret->setPackagefile($file, $archive);
                   76956:         return $ret;
                   76957:     }
                   76958: }<?php
                   76959: /**
                   76960:  * PEAR_PackageFile_v1, package.xml version 1.0
                   76961:  *
                   76962:  * PHP versions 4 and 5
                   76963:  *
                   76964:  * @category   pear
                   76965:  * @package    PEAR
                   76966:  * @author     Greg Beaver <cellog@php.net>
                   76967:  * @copyright  1997-2009 The Authors
                   76968:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   76969:  * @version    CVS: $Id: v1.php 276383 2009-02-24 23:39:37Z dufuz $
                   76970:  * @link       http://pear.php.net/package/PEAR
                   76971:  * @since      File available since Release 1.4.0a1
                   76972:  */
                   76973: /**
                   76974:  * For error handling
                   76975:  */
                   76976: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
                   76977: 
                   76978: /**
                   76979:  * Error code if parsing is attempted with no xml extension
                   76980:  */
                   76981: define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
                   76982: 
                   76983: /**
                   76984:  * Error code if creating the xml parser resource fails
                   76985:  */
                   76986: define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
                   76987: 
                   76988: /**
                   76989:  * Error code used for all sax xml parsing errors
                   76990:  */
                   76991: define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
                   76992: 
                   76993: /**
                   76994:  * Error code used when there is no name
                   76995:  */
                   76996: define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
                   76997: 
                   76998: /**
                   76999:  * Error code when a package name is not valid
                   77000:  */
                   77001: define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
                   77002: 
                   77003: /**
                   77004:  * Error code used when no summary is parsed
                   77005:  */
                   77006: define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
                   77007: 
                   77008: /**
                   77009:  * Error code for summaries that are more than 1 line
                   77010:  */
                   77011: define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
                   77012: 
                   77013: /**
                   77014:  * Error code used when no description is present
                   77015:  */
                   77016: define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
                   77017: 
                   77018: /**
                   77019:  * Error code used when no license is present
                   77020:  */
                   77021: define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
                   77022: 
                   77023: /**
                   77024:  * Error code used when a <version> version number is not present
                   77025:  */
                   77026: define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
                   77027: 
                   77028: /**
                   77029:  * Error code used when a <version> version number is invalid
                   77030:  */
                   77031: define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
                   77032: 
                   77033: /**
                   77034:  * Error code when release state is missing
                   77035:  */
                   77036: define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
                   77037: 
                   77038: /**
                   77039:  * Error code when release state is invalid
                   77040:  */
                   77041: define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
                   77042: 
                   77043: /**
                   77044:  * Error code when release state is missing
                   77045:  */
                   77046: define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
                   77047: 
                   77048: /**
                   77049:  * Error code when release state is invalid
                   77050:  */
                   77051: define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
                   77052: 
                   77053: /**
                   77054:  * Error code when no release notes are found
                   77055:  */
                   77056: define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
                   77057: 
                   77058: /**
                   77059:  * Error code when no maintainers are found
                   77060:  */
                   77061: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
                   77062: 
                   77063: /**
                   77064:  * Error code when a maintainer has no handle
                   77065:  */
                   77066: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
                   77067: 
                   77068: /**
                   77069:  * Error code when a maintainer has no handle
                   77070:  */
                   77071: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
                   77072: 
                   77073: /**
                   77074:  * Error code when a maintainer has no name
                   77075:  */
                   77076: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
                   77077: 
                   77078: /**
                   77079:  * Error code when a maintainer has no email
                   77080:  */
                   77081: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
                   77082: 
                   77083: /**
                   77084:  * Error code when a maintainer has no handle
                   77085:  */
                   77086: define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
                   77087: 
                   77088: /**
                   77089:  * Error code when a dependency is not a PHP dependency, but has no name
                   77090:  */
                   77091: define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
                   77092: 
                   77093: /**
                   77094:  * Error code when a dependency has no type (pkg, php, etc.)
                   77095:  */
                   77096: define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
                   77097: 
                   77098: /**
                   77099:  * Error code when a dependency has no relation (lt, ge, has, etc.)
                   77100:  */
                   77101: define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
                   77102: 
                   77103: /**
                   77104:  * Error code when a dependency is not a 'has' relation, but has no version
                   77105:  */
                   77106: define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
                   77107: 
                   77108: /**
                   77109:  * Error code when a dependency has an invalid relation
                   77110:  */
                   77111: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
                   77112: 
                   77113: /**
                   77114:  * Error code when a dependency has an invalid type
                   77115:  */
                   77116: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
                   77117: 
                   77118: /**
                   77119:  * Error code when a dependency has an invalid optional option
                   77120:  */
                   77121: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
                   77122: 
                   77123: /**
                   77124:  * Error code when a dependency is a pkg dependency, and has an invalid package name
                   77125:  */
                   77126: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
                   77127: 
                   77128: /**
                   77129:  * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
                   77130:  */
                   77131: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
                   77132: 
                   77133: /**
                   77134:  * Error code when rel="has" and version attribute is present.
                   77135:  */
                   77136: define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
                   77137: 
                   77138: /**
                   77139:  * Error code when type="php" and dependency name is present
                   77140:  */
                   77141: define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
                   77142: 
                   77143: /**
                   77144:  * Error code when a configure option has no name
                   77145:  */
                   77146: define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
                   77147: 
                   77148: /**
                   77149:  * Error code when a configure option has no name
                   77150:  */
                   77151: define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
                   77152: 
                   77153: /**
                   77154:  * Error code when a file in the filelist has an invalid role
                   77155:  */
                   77156: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
                   77157: 
                   77158: /**
                   77159:  * Error code when a file in the filelist has no role
                   77160:  */
                   77161: define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
                   77162: 
                   77163: /**
                   77164:  * Error code when analyzing a php source file that has parse errors
                   77165:  */
                   77166: define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
                   77167: 
                   77168: /**
                   77169:  * Error code when analyzing a php source file reveals a source element
                   77170:  * without a package name prefix
                   77171:  */
                   77172: define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
                   77173: 
                   77174: /**
                   77175:  * Error code when an unknown channel is specified
                   77176:  */
                   77177: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
                   77178: 
                   77179: /**
                   77180:  * Error code when no files are found in the filelist
                   77181:  */
                   77182: define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
                   77183: 
                   77184: /**
                   77185:  * Error code when a file is not valid php according to _analyzeSourceCode()
                   77186:  */
                   77187: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
                   77188: 
                   77189: /**
                   77190:  * Error code when the channel validator returns an error or warning
                   77191:  */
                   77192: define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
                   77193: 
                   77194: /**
                   77195:  * Error code when a php5 package is packaged in php4 (analysis doesn't work)
                   77196:  */
                   77197: define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
                   77198: 
                   77199: /**
                   77200:  * Error code when a file is listed in package.xml but does not exist
                   77201:  */
                   77202: define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
                   77203: 
                   77204: /**
                   77205:  * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
                   77206:  */
                   77207: define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
                   77208: 
                   77209: /**
                   77210:  * Error code when a package.xml contains non-ISO-8859-1 characters
                   77211:  */
                   77212: define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
                   77213: 
                   77214: /**
                   77215:  * Error code when a dependency is not a 'has' relation, but has no version
                   77216:  */
                   77217: define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
                   77218: 
                   77219: /**
                   77220:  * Error code when a package has no lead developer
                   77221:  */
                   77222: define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
                   77223: 
                   77224: /**
                   77225:  * Error code when a filename begins with "."
                   77226:  */
                   77227: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
                   77228: /**
                   77229:  * package.xml encapsulator
                   77230:  * @category   pear
                   77231:  * @package    PEAR
                   77232:  * @author     Greg Beaver <cellog@php.net>
                   77233:  * @copyright  1997-2009 The Authors
                   77234:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   77235:  * @version    Release: 1.10.0beta1
                   77236:  * @link       http://pear.php.net/package/PEAR
                   77237:  * @since      Class available since Release 1.4.0a1
                   77238:  */
                   77239: class PEAR_PackageFile_v1
                   77240: {
                   77241:     /**
                   77242:      * @access private
                   77243:      * @var PEAR_ErrorStack
                   77244:      * @access private
                   77245:      */
                   77246:     var $_stack;
                   77247: 
                   77248:     /**
                   77249:      * A registry object, used to access the package name validation regex for non-standard channels
                   77250:      * @var PEAR_Registry
                   77251:      * @access private
                   77252:      */
                   77253:     var $_registry;
                   77254: 
                   77255:     /**
                   77256:      * An object that contains a log method that matches PEAR_Common::log's signature
                   77257:      * @var object
                   77258:      * @access private
                   77259:      */
                   77260:     var $_logger;
                   77261: 
                   77262:     /**
                   77263:      * Parsed package information
                   77264:      * @var array
                   77265:      * @access private
                   77266:      */
                   77267:     var $_packageInfo;
                   77268: 
                   77269:     /**
                   77270:      * path to package.xml
                   77271:      * @var string
                   77272:      * @access private
                   77273:      */
                   77274:     var $_packageFile;
                   77275: 
                   77276:     /**
                   77277:      * path to package .tgz or false if this is a local/extracted package.xml
                   77278:      * @var string
                   77279:      * @access private
                   77280:      */
                   77281:     var $_archiveFile;
                   77282: 
                   77283:     /**
                   77284:      * @var int
                   77285:      * @access private
                   77286:      */
                   77287:     var $_isValid = 0;
                   77288: 
                   77289:     /**
                   77290:      * Determines whether this packagefile was initialized only with partial package info
                   77291:      *
                   77292:      * If this package file was constructed via parsing REST, it will only contain
                   77293:      *
                   77294:      * - package name
                   77295:      * - channel name
                   77296:      * - dependencies
                   77297:      * @var boolean
                   77298:      * @access private
                   77299:      */
                   77300:     var $_incomplete = true;
                   77301: 
                   77302:     /**
                   77303:      * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
                   77304:      * @param string Name of Error Stack class to use.
                   77305:      */
                   77306:     function PEAR_PackageFile_v1()
                   77307:     {
                   77308:         $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
                   77309:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   77310:         $this->_isValid = 0;
                   77311:     }
                   77312: 
                   77313:     function installBinary($installer)
                   77314:     {
                   77315:         return false;
                   77316:     }
                   77317: 
                   77318:     function isExtension($name)
                   77319:     {
                   77320:         return false;
                   77321:     }
                   77322: 
                   77323:     function setConfig(&$config)
                   77324:     {
                   77325:         $this->_config = &$config;
                   77326:         $this->_registry = &$config->getRegistry();
                   77327:     }
                   77328: 
                   77329:     function setRequestedGroup()
                   77330:     {
                   77331:         // placeholder
                   77332:     }
                   77333: 
                   77334:     /**
                   77335:      * For saving in the registry.
                   77336:      *
                   77337:      * Set the last version that was installed
                   77338:      * @param string
                   77339:      */
                   77340:     function setLastInstalledVersion($version)
                   77341:     {
                   77342:         $this->_packageInfo['_lastversion'] = $version;
                   77343:     }
                   77344: 
                   77345:     /**
                   77346:      * @return string|false
                   77347:      */
                   77348:     function getLastInstalledVersion()
                   77349:     {
                   77350:         if (isset($this->_packageInfo['_lastversion'])) {
                   77351:             return $this->_packageInfo['_lastversion'];
                   77352:         }
                   77353:         return false;
                   77354:     }
                   77355: 
                   77356:     function getInstalledBinary()
                   77357:     {
                   77358:         return false;
                   77359:     }
                   77360: 
                   77361:     function listPostinstallScripts()
                   77362:     {
                   77363:         return false;
                   77364:     }
                   77365: 
                   77366:     function initPostinstallScripts()
                   77367:     {
                   77368:         return false;
                   77369:     }
                   77370: 
                   77371:     function setLogger(&$logger)
                   77372:     {
                   77373:         if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
                   77374:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   77375:         }
                   77376:         $this->_logger = &$logger;
                   77377:     }
                   77378: 
                   77379:     function setPackagefile($file, $archive = false)
                   77380:     {
                   77381:         $this->_packageFile = $file;
                   77382:         $this->_archiveFile = $archive ? $archive : $file;
                   77383:     }
                   77384: 
                   77385:     function getPackageFile()
                   77386:     {
                   77387:         return isset($this->_packageFile) ? $this->_packageFile : false;
                   77388:     }
                   77389: 
                   77390:     function getPackageType()
                   77391:     {
                   77392:         return 'php';
                   77393:     }
                   77394: 
                   77395:     function getArchiveFile()
                   77396:     {
                   77397:         return $this->_archiveFile;
                   77398:     }
                   77399: 
                   77400:     function packageInfo($field)
                   77401:     {
                   77402:         if (!is_string($field) || empty($field) ||
                   77403:             !isset($this->_packageInfo[$field])) {
                   77404:             return false;
                   77405:         }
                   77406:         return $this->_packageInfo[$field];
                   77407:     }
                   77408: 
                   77409:     function setDirtree($path)
                   77410:     {
                   77411:         if (!isset($this->_packageInfo['dirtree'])) {
                   77412:             $this->_packageInfo['dirtree'] = array();
                   77413:         }
                   77414:         $this->_packageInfo['dirtree'][$path] = true;
                   77415:     }
                   77416: 
                   77417:     function getDirtree()
                   77418:     {
                   77419:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   77420:             return $this->_packageInfo['dirtree'];
                   77421:         }
                   77422:         return false;
                   77423:     }
                   77424: 
                   77425:     function resetDirtree()
                   77426:     {
                   77427:         unset($this->_packageInfo['dirtree']);
                   77428:     }
                   77429: 
                   77430:     function fromArray($pinfo)
                   77431:     {
                   77432:         $this->_incomplete = false;
                   77433:         $this->_packageInfo = $pinfo;
                   77434:     }
                   77435: 
                   77436:     function isIncomplete()
                   77437:     {
                   77438:         return $this->_incomplete;
                   77439:     }
                   77440: 
                   77441:     function getChannel()
                   77442:     {
                   77443:         return 'pear.php.net';
                   77444:     }
                   77445: 
                   77446:     function getUri()
                   77447:     {
                   77448:         return false;
                   77449:     }
                   77450: 
                   77451:     function getTime()
                   77452:     {
                   77453:         return false;
                   77454:     }
                   77455: 
                   77456:     function getExtends()
                   77457:     {
                   77458:         if (isset($this->_packageInfo['extends'])) {
                   77459:             return $this->_packageInfo['extends'];
                   77460:         }
                   77461:         return false;
                   77462:     }
                   77463: 
                   77464:     /**
                   77465:      * @return array
                   77466:      */
                   77467:     function toArray()
                   77468:     {
                   77469:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   77470:             return false;
                   77471:         }
                   77472:         return $this->getArray();
                   77473:     }
                   77474: 
                   77475:     function getArray()
                   77476:     {
                   77477:         return $this->_packageInfo;
                   77478:     }
                   77479: 
                   77480:     function getName()
                   77481:     {
                   77482:         return $this->getPackage();
                   77483:     }
                   77484: 
                   77485:     function getPackage()
                   77486:     {
                   77487:         if (isset($this->_packageInfo['package'])) {
                   77488:             return $this->_packageInfo['package'];
                   77489:         }
                   77490:         return false;
                   77491:     }
                   77492: 
                   77493:     /**
                   77494:      * WARNING - don't use this unless you know what you are doing
                   77495:      */
                   77496:     function setRawPackage($package)
                   77497:     {
                   77498:         $this->_packageInfo['package'] = $package;
                   77499:     }
                   77500: 
                   77501:     function setPackage($package)
                   77502:     {
                   77503:         $this->_packageInfo['package'] = $package;
                   77504:         $this->_isValid = false;
                   77505:     }
                   77506: 
                   77507:     function getVersion()
                   77508:     {
                   77509:         if (isset($this->_packageInfo['version'])) {
                   77510:             return $this->_packageInfo['version'];
                   77511:         }
                   77512:         return false;
                   77513:     }
                   77514: 
                   77515:     function setVersion($version)
                   77516:     {
                   77517:         $this->_packageInfo['version'] = $version;
                   77518:         $this->_isValid = false;
                   77519:     }
                   77520: 
                   77521:     function clearMaintainers()
                   77522:     {
                   77523:         unset($this->_packageInfo['maintainers']);
                   77524:     }
                   77525: 
                   77526:     function getMaintainers()
                   77527:     {
                   77528:         if (isset($this->_packageInfo['maintainers'])) {
                   77529:             return $this->_packageInfo['maintainers'];
                   77530:         }
                   77531:         return false;
                   77532:     }
                   77533: 
                   77534:     /**
                   77535:      * Adds a new maintainer - no checking of duplicates is performed, use
                   77536:      * updatemaintainer for that purpose.
                   77537:      */
                   77538:     function addMaintainer($role, $handle, $name, $email)
                   77539:     {
                   77540:         $this->_packageInfo['maintainers'][] =
                   77541:             array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
                   77542:         $this->_isValid = false;
                   77543:     }
                   77544: 
                   77545:     function updateMaintainer($role, $handle, $name, $email)
                   77546:     {
                   77547:         $found = false;
                   77548:         if (!isset($this->_packageInfo['maintainers']) ||
                   77549:               !is_array($this->_packageInfo['maintainers'])) {
                   77550:             return $this->addMaintainer($role, $handle, $name, $email);
                   77551:         }
                   77552:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   77553:             if ($maintainer['handle'] == $handle) {
                   77554:                 $found = $i;
                   77555:                 break;
                   77556:             }
                   77557:         }
                   77558:         if ($found !== false) {
                   77559:             unset($this->_packageInfo['maintainers'][$found]);
                   77560:             $this->_packageInfo['maintainers'] =
                   77561:                 array_values($this->_packageInfo['maintainers']);
                   77562:         }
                   77563:         $this->addMaintainer($role, $handle, $name, $email);
                   77564:     }
                   77565: 
                   77566:     function deleteMaintainer($handle)
                   77567:     {
                   77568:         $found = false;
                   77569:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   77570:             if ($maintainer['handle'] == $handle) {
                   77571:                 $found = $i;
                   77572:                 break;
                   77573:             }
                   77574:         }
                   77575:         if ($found !== false) {
                   77576:             unset($this->_packageInfo['maintainers'][$found]);
                   77577:             $this->_packageInfo['maintainers'] =
                   77578:                 array_values($this->_packageInfo['maintainers']);
                   77579:             return true;
                   77580:         }
                   77581:         return false;
                   77582:     }
                   77583: 
                   77584:     function getState()
                   77585:     {
                   77586:         if (isset($this->_packageInfo['release_state'])) {
                   77587:             return $this->_packageInfo['release_state'];
                   77588:         }
                   77589:         return false;
                   77590:     }
                   77591: 
                   77592:     function setRawState($state)
                   77593:     {
                   77594:         $this->_packageInfo['release_state'] = $state;
                   77595:     }
                   77596: 
                   77597:     function setState($state)
                   77598:     {
                   77599:         $this->_packageInfo['release_state'] = $state;
                   77600:         $this->_isValid = false;
                   77601:     }
                   77602: 
                   77603:     function getDate()
                   77604:     {
                   77605:         if (isset($this->_packageInfo['release_date'])) {
                   77606:             return $this->_packageInfo['release_date'];
                   77607:         }
                   77608:         return false;
                   77609:     }
                   77610: 
                   77611:     function setDate($date)
                   77612:     {
                   77613:         $this->_packageInfo['release_date'] = $date;
                   77614:         $this->_isValid = false;
                   77615:     }
                   77616: 
                   77617:     function getLicense()
                   77618:     {
                   77619:         if (isset($this->_packageInfo['release_license'])) {
                   77620:             return $this->_packageInfo['release_license'];
                   77621:         }
                   77622:         return false;
                   77623:     }
                   77624: 
                   77625:     function setLicense($date)
                   77626:     {
                   77627:         $this->_packageInfo['release_license'] = $date;
                   77628:         $this->_isValid = false;
                   77629:     }
                   77630: 
                   77631:     function getSummary()
                   77632:     {
                   77633:         if (isset($this->_packageInfo['summary'])) {
                   77634:             return $this->_packageInfo['summary'];
                   77635:         }
                   77636:         return false;
                   77637:     }
                   77638: 
                   77639:     function setSummary($summary)
                   77640:     {
                   77641:         $this->_packageInfo['summary'] = $summary;
                   77642:         $this->_isValid = false;
                   77643:     }
                   77644: 
                   77645:     function getDescription()
                   77646:     {
                   77647:         if (isset($this->_packageInfo['description'])) {
                   77648:             return $this->_packageInfo['description'];
                   77649:         }
                   77650:         return false;
                   77651:     }
                   77652: 
                   77653:     function setDescription($desc)
                   77654:     {
                   77655:         $this->_packageInfo['description'] = $desc;
                   77656:         $this->_isValid = false;
                   77657:     }
                   77658: 
                   77659:     function getNotes()
                   77660:     {
                   77661:         if (isset($this->_packageInfo['release_notes'])) {
                   77662:             return $this->_packageInfo['release_notes'];
                   77663:         }
                   77664:         return false;
                   77665:     }
                   77666: 
                   77667:     function setNotes($notes)
                   77668:     {
                   77669:         $this->_packageInfo['release_notes'] = $notes;
                   77670:         $this->_isValid = false;
                   77671:     }
                   77672: 
                   77673:     function getDeps()
                   77674:     {
                   77675:         if (isset($this->_packageInfo['release_deps'])) {
                   77676:             return $this->_packageInfo['release_deps'];
                   77677:         }
                   77678:         return false;
                   77679:     }
                   77680: 
                   77681:     /**
                   77682:      * Reset dependencies prior to adding new ones
                   77683:      */
                   77684:     function clearDeps()
                   77685:     {
                   77686:         unset($this->_packageInfo['release_deps']);
                   77687:     }
                   77688: 
                   77689:     function addPhpDep($version, $rel)
                   77690:     {
                   77691:         $this->_isValid = false;
                   77692:         $this->_packageInfo['release_deps'][] =
                   77693:             array('type' => 'php',
                   77694:                   'rel' => $rel,
                   77695:                   'version' => $version);
                   77696:     }
                   77697: 
                   77698:     function addPackageDep($name, $version, $rel, $optional = 'no')
                   77699:     {
                   77700:         $this->_isValid = false;
                   77701:         $dep =
                   77702:             array('type' => 'pkg',
                   77703:                   'name' => $name,
                   77704:                   'rel' => $rel,
                   77705:                   'optional' => $optional);
                   77706:         if ($rel != 'has' && $rel != 'not') {
                   77707:             $dep['version'] = $version;
                   77708:         }
                   77709:         $this->_packageInfo['release_deps'][] = $dep;
                   77710:     }
                   77711: 
                   77712:     function addExtensionDep($name, $version, $rel, $optional = 'no')
                   77713:     {
                   77714:         $this->_isValid = false;
                   77715:         $this->_packageInfo['release_deps'][] =
                   77716:             array('type' => 'ext',
                   77717:                   'name' => $name,
                   77718:                   'rel' => $rel,
                   77719:                   'version' => $version,
                   77720:                   'optional' => $optional);
                   77721:     }
                   77722: 
                   77723:     /**
                   77724:      * WARNING - do not use this function directly unless you know what you're doing
                   77725:      */
                   77726:     function setDeps($deps)
                   77727:     {
                   77728:         $this->_packageInfo['release_deps'] = $deps;
                   77729:     }
                   77730: 
                   77731:     function hasDeps()
                   77732:     {
                   77733:         return isset($this->_packageInfo['release_deps']) &&
                   77734:             count($this->_packageInfo['release_deps']);
                   77735:     }
                   77736: 
                   77737:     function getDependencyGroup($group)
                   77738:     {
                   77739:         return false;
                   77740:     }
                   77741: 
                   77742:     function isCompatible($pf)
                   77743:     {
                   77744:         return false;
                   77745:     }
                   77746: 
                   77747:     function isSubpackageOf($p)
                   77748:     {
                   77749:         return $p->isSubpackage($this);
                   77750:     }
                   77751: 
                   77752:     function isSubpackage($p)
                   77753:     {
                   77754:         return false;
                   77755:     }
                   77756: 
                   77757:     function dependsOn($package, $channel)
                   77758:     {
                   77759:         if (strtolower($channel) != 'pear.php.net') {
                   77760:             return false;
                   77761:         }
                   77762:         if (!($deps = $this->getDeps())) {
                   77763:             return false;
                   77764:         }
                   77765:         foreach ($deps as $dep) {
                   77766:             if ($dep['type'] != 'pkg') {
                   77767:                 continue;
                   77768:             }
                   77769:             if (strtolower($dep['name']) == strtolower($package)) {
                   77770:                 return true;
                   77771:             }
                   77772:         }
                   77773:         return false;
                   77774:     }
                   77775: 
                   77776:     function getConfigureOptions()
                   77777:     {
                   77778:         if (isset($this->_packageInfo['configure_options'])) {
                   77779:             return $this->_packageInfo['configure_options'];
                   77780:         }
                   77781:         return false;
                   77782:     }
                   77783: 
                   77784:     function hasConfigureOptions()
                   77785:     {
                   77786:         return isset($this->_packageInfo['configure_options']) &&
                   77787:             count($this->_packageInfo['configure_options']);
                   77788:     }
                   77789: 
                   77790:     function addConfigureOption($name, $prompt, $default = false)
                   77791:     {
                   77792:         $o = array('name' => $name, 'prompt' => $prompt);
                   77793:         if ($default !== false) {
                   77794:             $o['default'] = $default;
                   77795:         }
                   77796:         if (!isset($this->_packageInfo['configure_options'])) {
                   77797:             $this->_packageInfo['configure_options'] = array();
                   77798:         }
                   77799:         $this->_packageInfo['configure_options'][] = $o;
                   77800:     }
                   77801: 
                   77802:     function clearConfigureOptions()
                   77803:     {
                   77804:         unset($this->_packageInfo['configure_options']);
                   77805:     }
                   77806: 
                   77807:     function getProvides()
                   77808:     {
                   77809:         if (isset($this->_packageInfo['provides'])) {
                   77810:             return $this->_packageInfo['provides'];
                   77811:         }
                   77812:         return false;
                   77813:     }
                   77814: 
                   77815:     function getProvidesExtension()
                   77816:     {
                   77817:         return false;
                   77818:     }
                   77819: 
                   77820:     function addFile($dir, $file, $attrs)
                   77821:     {
                   77822:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
                   77823:         if ($dir == '/' || $dir == '') {
                   77824:             $dir = '';
                   77825:         } else {
                   77826:             $dir .= '/';
                   77827:         }
                   77828:         $file = $dir . $file;
                   77829:         $file = preg_replace('![\\/]+!', '/', $file);
                   77830:         $this->_packageInfo['filelist'][$file] = $attrs;
                   77831:     }
                   77832: 
                   77833:     function getInstallationFilelist()
                   77834:     {
                   77835:         return $this->getFilelist();
                   77836:     }
                   77837: 
                   77838:     function getFilelist()
                   77839:     {
                   77840:         if (isset($this->_packageInfo['filelist'])) {
                   77841:             return $this->_packageInfo['filelist'];
                   77842:         }
                   77843:         return false;
                   77844:     }
                   77845: 
                   77846:     function setFileAttribute($file, $attr, $value)
                   77847:     {
                   77848:         $this->_packageInfo['filelist'][$file][$attr] = $value;
                   77849:     }
                   77850: 
                   77851:     function resetFilelist()
                   77852:     {
                   77853:         $this->_packageInfo['filelist'] = array();
                   77854:     }
                   77855: 
                   77856:     function setInstalledAs($file, $path)
                   77857:     {
                   77858:         if ($path) {
                   77859:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   77860:         }
                   77861:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   77862:     }
                   77863: 
                   77864:     function installedFile($file, $atts)
                   77865:     {
                   77866:         if (isset($this->_packageInfo['filelist'][$file])) {
                   77867:             $this->_packageInfo['filelist'][$file] =
                   77868:                 array_merge($this->_packageInfo['filelist'][$file], $atts);
                   77869:         } else {
                   77870:             $this->_packageInfo['filelist'][$file] = $atts;
                   77871:         }
                   77872:     }
                   77873: 
                   77874:     function getChangelog()
                   77875:     {
                   77876:         if (isset($this->_packageInfo['changelog'])) {
                   77877:             return $this->_packageInfo['changelog'];
                   77878:         }
                   77879:         return false;
                   77880:     }
                   77881: 
                   77882:     function getPackagexmlVersion()
                   77883:     {
                   77884:         return '1.0';
                   77885:     }
                   77886: 
                   77887:     /**
                   77888:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   77889:      * @param boolean determines whether to purge the error stack after retrieving
                   77890:      * @return array
                   77891:      */
                   77892:     function getValidationWarnings($purge = true)
                   77893:     {
                   77894:         return $this->_stack->getErrors($purge);
                   77895:     }
                   77896: 
                   77897:     // }}}
                   77898:     /**
                   77899:      * Validation error.  Also marks the object contents as invalid
                   77900:      * @param error code
                   77901:      * @param array error information
                   77902:      * @access private
                   77903:      */
                   77904:     function _validateError($code, $params = array())
                   77905:     {
                   77906:         $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
                   77907:         $this->_isValid = false;
                   77908:     }
                   77909: 
                   77910:     /**
                   77911:      * Validation warning.  Does not mark the object contents invalid.
                   77912:      * @param error code
                   77913:      * @param array error information
                   77914:      * @access private
                   77915:      */
                   77916:     function _validateWarning($code, $params = array())
                   77917:     {
                   77918:         $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
                   77919:     }
                   77920: 
                   77921:     /**
                   77922:      * @param integer error code
                   77923:      * @access protected
                   77924:      */
                   77925:     function _getErrorMessage()
                   77926:     {
                   77927:         return array(
                   77928:                 PEAR_PACKAGEFILE_ERROR_NO_NAME =>
                   77929:                     'Missing Package Name',
                   77930:                 PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
                   77931:                     'No summary found',
                   77932:                 PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
                   77933:                     'Summary should be on one line',
                   77934:                 PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
                   77935:                     'Missing description',
                   77936:                 PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
                   77937:                     'Missing license',
                   77938:                 PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
                   77939:                     'No release version found',
                   77940:                 PEAR_PACKAGEFILE_ERROR_NO_STATE =>
                   77941:                     'No release state found',
                   77942:                 PEAR_PACKAGEFILE_ERROR_NO_DATE =>
                   77943:                     'No release date found',
                   77944:                 PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
                   77945:                     'No release notes found',
                   77946:                 PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
                   77947:                     'Package must have at least one lead maintainer',
                   77948:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
                   77949:                     'No maintainers found, at least one must be defined',
                   77950:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
                   77951:                     'Maintainer %index% has no handle (user ID at channel server)',
                   77952:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
                   77953:                     'Maintainer %index% has no role',
                   77954:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
                   77955:                     'Maintainer %index% has no name',
                   77956:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
                   77957:                     'Maintainer %index% has no email',
                   77958:                 PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
                   77959:                     'Dependency %index% is not a php dependency, and has no name',
                   77960:                 PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
                   77961:                     'Dependency %index% has no relation (rel)',
                   77962:                 PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
                   77963:                     'Dependency %index% has no type',
                   77964:                 PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
                   77965:                     'PHP Dependency %index% has a name attribute of "%name%" which will be' .
                   77966:                         ' ignored!',
                   77967:                 PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
                   77968:                     'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
                   77969:                         'and has no version',
                   77970:                 PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
                   77971:                     'Dependency %index% is a type="php" dependency, ' .
                   77972:                         'and has no version',
                   77973:                 PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
                   77974:                     'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
                   77975:                 PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
                   77976:                     'Dependency %index% has invalid optional value "%opt%", should be yes or no',
                   77977:                 PEAR_PACKAGEFILE_PHP_NO_NOT =>
                   77978:                     'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
                   77979:                         ' to exclude specific versions',
                   77980:                 PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
                   77981:                     'Configure Option %index% has no name',
                   77982:                 PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
                   77983:                     'Configure Option %index% has no prompt',
                   77984:                 PEAR_PACKAGEFILE_ERROR_NO_FILES =>
                   77985:                     'No files in <filelist> section of package.xml',
                   77986:                 PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
                   77987:                     'File "%file%" has no role, expecting one of "%roles%"',
                   77988:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
                   77989:                     'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
                   77990:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
                   77991:                     'File "%file%" cannot start with ".", cannot package or install',
                   77992:                 PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
                   77993:                     'Parser error: invalid PHP found in file "%file%"',
                   77994:                 PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
                   77995:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"',
                   77996:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
                   77997:                     'Parser error: invalid PHP file "%file%"',
                   77998:                 PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
                   77999:                     'Channel validator error: field "%field%" - %reason%',
                   78000:                 PEAR_PACKAGEFILE_ERROR_PHP5 =>
                   78001:                     'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
                   78002:                 PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
                   78003:                     'File "%file%" in package.xml does not exist',
                   78004:                 PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
                   78005:                     'Package.xml contains non-ISO-8859-1 characters, and may not validate',
                   78006:             );
                   78007:     }
                   78008: 
                   78009:     /**
                   78010:      * Validate XML package definition file.
                   78011:      *
                   78012:      * @access public
                   78013:      * @return boolean
                   78014:      */
                   78015:     function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
                   78016:     {
                   78017:         if (($this->_isValid & $state) == $state) {
                   78018:             return true;
                   78019:         }
                   78020:         $this->_isValid = true;
                   78021:         $info = $this->_packageInfo;
                   78022:         if (empty($info['package'])) {
                   78023:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
                   78024:             $this->_packageName = $pn = 'unknown';
                   78025:         } else {
                   78026:             $this->_packageName = $pn = $info['package'];
                   78027:         }
                   78028: 
                   78029:         if (empty($info['summary'])) {
                   78030:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
                   78031:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   78032:             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
                   78033:                 array('summary' => $info['summary']));
                   78034:         }
                   78035:         if (empty($info['description'])) {
                   78036:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
                   78037:         }
                   78038:         if (empty($info['release_license'])) {
                   78039:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
                   78040:         }
                   78041:         if (empty($info['version'])) {
                   78042:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
                   78043:         }
                   78044:         if (empty($info['release_state'])) {
                   78045:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
                   78046:         }
                   78047:         if (empty($info['release_date'])) {
                   78048:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
                   78049:         }
                   78050:         if (empty($info['release_notes'])) {
                   78051:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
                   78052:         }
                   78053:         if (empty($info['maintainers'])) {
                   78054:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
                   78055:         } else {
                   78056:             $haslead = false;
                   78057:             $i = 1;
                   78058:             foreach ($info['maintainers'] as $m) {
                   78059:                 if (empty($m['handle'])) {
                   78060:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
                   78061:                         array('index' => $i));
                   78062:                 }
                   78063:                 if (empty($m['role'])) {
                   78064:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
                   78065:                         array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
                   78066:                 } elseif ($m['role'] == 'lead') {
                   78067:                     $haslead = true;
                   78068:                 }
                   78069:                 if (empty($m['name'])) {
                   78070:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
                   78071:                         array('index' => $i));
                   78072:                 }
                   78073:                 if (empty($m['email'])) {
                   78074:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
                   78075:                         array('index' => $i));
                   78076:                 }
                   78077:                 $i++;
                   78078:             }
                   78079:             if (!$haslead) {
                   78080:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
                   78081:             }
                   78082:         }
                   78083:         if (!empty($info['release_deps'])) {
                   78084:             $i = 1;
                   78085:             foreach ($info['release_deps'] as $d) {
                   78086:                 if (!isset($d['type']) || empty($d['type'])) {
                   78087:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
                   78088:                         array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
                   78089:                     continue;
                   78090:                 }
                   78091:                 if (!isset($d['rel']) || empty($d['rel'])) {
                   78092:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
                   78093:                         array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
                   78094:                     continue;
                   78095:                 }
                   78096:                 if (!empty($d['optional'])) {
                   78097:                     if (!in_array($d['optional'], array('yes', 'no'))) {
                   78098:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
                   78099:                             array('index' => $i, 'opt' => $d['optional']));
                   78100:                     }
                   78101:                 }
                   78102:                 if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
                   78103:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
                   78104:                         array('index' => $i));
                   78105:                 } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
                   78106:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
                   78107:                         array('index' => $i, 'rel' => $d['rel']));
                   78108:                 }
                   78109:                 if ($d['type'] == 'php' && !empty($d['name'])) {
                   78110:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
                   78111:                         array('index' => $i, 'name' => $d['name']));
                   78112:                 } elseif ($d['type'] != 'php' && empty($d['name'])) {
                   78113:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
                   78114:                         array('index' => $i));
                   78115:                 }
                   78116:                 if ($d['type'] == 'php' && empty($d['version'])) {
                   78117:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
                   78118:                         array('index' => $i));
                   78119:                 }
                   78120:                 if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
                   78121:                     $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
                   78122:                         array('index' => $i));
                   78123:                 }
                   78124:                 $i++;
                   78125:             }
                   78126:         }
                   78127:         if (!empty($info['configure_options'])) {
                   78128:             $i = 1;
                   78129:             foreach ($info['configure_options'] as $c) {
                   78130:                 if (empty($c['name'])) {
                   78131:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
                   78132:                         array('index' => $i));
                   78133:                 }
                   78134:                 if (empty($c['prompt'])) {
                   78135:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
                   78136:                         array('index' => $i));
                   78137:                 }
                   78138:                 $i++;
                   78139:             }
                   78140:         }
                   78141:         if (empty($info['filelist'])) {
                   78142:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
                   78143:             $errors[] = 'no files';
                   78144:         } else {
                   78145:             foreach ($info['filelist'] as $file => $fa) {
                   78146:                 if (empty($fa['role'])) {
                   78147:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
                   78148:                         array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
                   78149:                     continue;
                   78150:                 } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
                   78151:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
                   78152:                         array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
                   78153:                 }
                   78154:                 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
                   78155:                     // file contains .. parent directory or . cur directory references
                   78156:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   78157:                         array('file' => $file));
                   78158:                 }
                   78159:                 if (isset($fa['install-as']) &&
                   78160:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   78161:                                  str_replace('\\', '/', $fa['install-as']))) {
                   78162:                     // install-as contains .. parent directory or . cur directory references
                   78163:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   78164:                         array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
                   78165:                 }
                   78166:                 if (isset($fa['baseinstalldir']) &&
                   78167:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   78168:                                  str_replace('\\', '/', $fa['baseinstalldir']))) {
                   78169:                     // install-as contains .. parent directory or . cur directory references
                   78170:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   78171:                         array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
                   78172:                 }
                   78173:             }
                   78174:         }
                   78175:         if (isset($this->_registry) && $this->_isValid) {
                   78176:             $chan = $this->_registry->getChannel('pear.php.net');
                   78177:             if (PEAR::isError($chan)) {
                   78178:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
                   78179:                 return $this->_isValid = 0;
                   78180:             }
                   78181:             $validator = $chan->getValidationObject();
                   78182:             $validator->setPackageFile($this);
                   78183:             $validator->validate($state);
                   78184:             $failures = $validator->getFailures();
                   78185:             foreach ($failures['errors'] as $error) {
                   78186:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
                   78187:             }
                   78188:             foreach ($failures['warnings'] as $warning) {
                   78189:                 $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
                   78190:             }
                   78191:         }
                   78192:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
                   78193:             if ($this->_analyzePhpFiles()) {
                   78194:                 $this->_isValid = true;
                   78195:             }
                   78196:         }
                   78197:         if ($this->_isValid) {
                   78198:             return $this->_isValid = $state;
                   78199:         }
                   78200:         return $this->_isValid = 0;
                   78201:     }
                   78202: 
                   78203:     function _analyzePhpFiles()
                   78204:     {
                   78205:         if (!$this->_isValid) {
                   78206:             return false;
                   78207:         }
                   78208:         if (!isset($this->_packageFile)) {
                   78209:             return false;
                   78210:         }
                   78211:         $dir_prefix = dirname($this->_packageFile);
                   78212:         $common = new PEAR_Common;
                   78213:         $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
                   78214:             array($common, 'log');
                   78215:         $info = $this->getFilelist();
                   78216:         foreach ($info as $file => $fa) {
                   78217:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   78218:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
                   78219:                     array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
                   78220:                 continue;
                   78221:             }
                   78222:             if ($fa['role'] == 'php' && $dir_prefix) {
                   78223:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   78224:                 $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   78225:                 if ($srcinfo) {
                   78226:                     $this->_buildProvidesArray($srcinfo);
                   78227:                 }
                   78228:             }
                   78229:         }
                   78230:         $this->_packageName = $pn = $this->getPackage();
                   78231:         $pnl = strlen($pn);
                   78232:         if (isset($this->_packageInfo['provides'])) {
                   78233:             foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
                   78234:                 if (isset($what['explicit'])) {
                   78235:                     // skip conformance checks if the provides entry is
                   78236:                     // specified in the package.xml file
                   78237:                     continue;
                   78238:                 }
                   78239:                 extract($what);
                   78240:                 if ($type == 'class') {
                   78241:                     if (!strncasecmp($name, $pn, $pnl)) {
                   78242:                         continue;
                   78243:                     }
                   78244:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   78245:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   78246:                 } elseif ($type == 'function') {
                   78247:                     if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   78248:                         continue;
                   78249:                     }
                   78250:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   78251:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   78252:                 }
                   78253:             }
                   78254:         }
                   78255:         return $this->_isValid;
                   78256:     }
                   78257: 
                   78258:     /**
                   78259:      * Get the default xml generator object
                   78260:      *
                   78261:      * @return PEAR_PackageFile_Generator_v1
                   78262:      */
                   78263:     function &getDefaultGenerator()
                   78264:     {
                   78265:         if (!class_exists('PEAR_PackageFile_Generator_v1')) {
                   78266:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v1.php';
                   78267:         }
                   78268:         $a = &new PEAR_PackageFile_Generator_v1($this);
                   78269:         return $a;
                   78270:     }
                   78271: 
                   78272:     /**
                   78273:      * Get the contents of a file listed within the package.xml
                   78274:      * @param string
                   78275:      * @return string
                   78276:      */
                   78277:     function getFileContents($file)
                   78278:     {
                   78279:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   78280:             $dir = dirname($this->_packageFile);
                   78281:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   78282:             $file = str_replace(array('/', '\\'),
                   78283:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   78284:             if (file_exists($file) && is_readable($file)) {
                   78285:                 return implode('', file($file));
                   78286:             }
                   78287:         } else { // tgz
                   78288:             if (!class_exists('Archive_Tar')) {
                   78289:                 require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
                   78290:             }
                   78291:             $tar = &new Archive_Tar($this->_archiveFile);
                   78292:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   78293:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   78294:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   78295:             }
                   78296:             $file = $tar->extractInString($file);
                   78297:             $tar->popErrorHandling();
                   78298:             if (PEAR::isError($file)) {
                   78299:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   78300:             }
                   78301:             return $file;
                   78302:         }
                   78303:     }
                   78304: 
                   78305:     // {{{ analyzeSourceCode()
                   78306:     /**
                   78307:      * Analyze the source code of the given PHP file
                   78308:      *
                   78309:      * @param  string Filename of the PHP file
                   78310:      * @return mixed
                   78311:      * @access private
                   78312:      */
                   78313:     function _analyzeSourceCode($file)
                   78314:     {
                   78315:         if (!function_exists("token_get_all")) {
                   78316:             return false;
                   78317:         }
                   78318:         if (!defined('T_DOC_COMMENT')) {
                   78319:             define('T_DOC_COMMENT', T_COMMENT);
                   78320:         }
                   78321:         if (!defined('T_INTERFACE')) {
                   78322:             define('T_INTERFACE', -1);
                   78323:         }
                   78324:         if (!defined('T_IMPLEMENTS')) {
                   78325:             define('T_IMPLEMENTS', -1);
                   78326:         }
                   78327:         if (!$fp = @fopen($file, "r")) {
                   78328:             return false;
                   78329:         }
                   78330:         fclose($fp);
                   78331:         $contents = file_get_contents($file);
                   78332:         $tokens = token_get_all($contents);
                   78333: /*
                   78334:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   78335:             @list($token, $data) = $tokens[$i];
                   78336:             if (is_string($token)) {
                   78337:                 var_dump($token);
                   78338:             } else {
                   78339:                 print token_name($token) . ' ';
                   78340:                 var_dump(rtrim($data));
                   78341:             }
                   78342:         }
                   78343: */
                   78344:         $look_for = 0;
                   78345:         $paren_level = 0;
                   78346:         $bracket_level = 0;
                   78347:         $brace_level = 0;
                   78348:         $lastphpdoc = '';
                   78349:         $current_class = '';
                   78350:         $current_interface = '';
                   78351:         $current_class_level = -1;
                   78352:         $current_function = '';
                   78353:         $current_function_level = -1;
                   78354:         $declared_classes = array();
                   78355:         $declared_interfaces = array();
                   78356:         $declared_functions = array();
                   78357:         $declared_methods = array();
                   78358:         $used_classes = array();
                   78359:         $used_functions = array();
                   78360:         $extends = array();
                   78361:         $implements = array();
                   78362:         $nodeps = array();
                   78363:         $inquote = false;
                   78364:         $interface = false;
                   78365:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   78366:             if (is_array($tokens[$i])) {
                   78367:                 list($token, $data) = $tokens[$i];
                   78368:             } else {
                   78369:                 $token = $tokens[$i];
                   78370:                 $data = '';
                   78371:             }
                   78372:             if ($inquote) {
                   78373:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   78374:                     continue;
                   78375:                 } else {
                   78376:                     $inquote = false;
                   78377:                     continue;
                   78378:                 }
                   78379:             }
                   78380:             switch ($token) {
                   78381:                 case T_WHITESPACE :
                   78382:                     continue;
                   78383:                 case ';':
                   78384:                     if ($interface) {
                   78385:                         $current_function = '';
                   78386:                         $current_function_level = -1;
                   78387:                     }
                   78388:                     break;
                   78389:                 case '"':
                   78390:                 case T_START_HEREDOC:
                   78391:                     $inquote = true;
                   78392:                     break;
                   78393:                 case T_CURLY_OPEN:
                   78394:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   78395:                 case '{': $brace_level++; continue 2;
                   78396:                 case '}':
                   78397:                     $brace_level--;
                   78398:                     if ($current_class_level == $brace_level) {
                   78399:                         $current_class = '';
                   78400:                         $current_class_level = -1;
                   78401:                     }
                   78402:                     if ($current_function_level == $brace_level) {
                   78403:                         $current_function = '';
                   78404:                         $current_function_level = -1;
                   78405:                     }
                   78406:                     continue 2;
                   78407:                 case '[': $bracket_level++; continue 2;
                   78408:                 case ']': $bracket_level--; continue 2;
                   78409:                 case '(': $paren_level++;   continue 2;
                   78410:                 case ')': $paren_level--;   continue 2;
                   78411:                 case T_INTERFACE:
                   78412:                     $interface = true;
                   78413:                 case T_CLASS:
                   78414:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   78415:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   78416:                             array('file' => $file));
                   78417:                         return false;
                   78418:                     }
                   78419:                 case T_FUNCTION:
                   78420:                 case T_NEW:
                   78421:                 case T_EXTENDS:
                   78422:                 case T_IMPLEMENTS:
                   78423:                     $look_for = $token;
                   78424:                     continue 2;
                   78425:                 case T_STRING:
                   78426:                     if (version_compare(zend_version(), '2.0', '<')) {
                   78427:                         if (in_array(strtolower($data),
                   78428:                             array('public', 'private', 'protected', 'abstract',
                   78429:                                   'interface', 'implements', 'throw')
                   78430:                                  )) {
                   78431:                             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
                   78432:                                 array($file));
                   78433:                         }
                   78434:                     }
                   78435:                     if ($look_for == T_CLASS) {
                   78436:                         $current_class = $data;
                   78437:                         $current_class_level = $brace_level;
                   78438:                         $declared_classes[] = $current_class;
                   78439:                     } elseif ($look_for == T_INTERFACE) {
                   78440:                         $current_interface = $data;
                   78441:                         $current_class_level = $brace_level;
                   78442:                         $declared_interfaces[] = $current_interface;
                   78443:                     } elseif ($look_for == T_IMPLEMENTS) {
                   78444:                         $implements[$current_class] = $data;
                   78445:                     } elseif ($look_for == T_EXTENDS) {
                   78446:                         $extends[$current_class] = $data;
                   78447:                     } elseif ($look_for == T_FUNCTION) {
                   78448:                         if ($current_class) {
                   78449:                             $current_function = "$current_class::$data";
                   78450:                             $declared_methods[$current_class][] = $data;
                   78451:                         } elseif ($current_interface) {
                   78452:                             $current_function = "$current_interface::$data";
                   78453:                             $declared_methods[$current_interface][] = $data;
                   78454:                         } else {
                   78455:                             $current_function = $data;
                   78456:                             $declared_functions[] = $current_function;
                   78457:                         }
                   78458:                         $current_function_level = $brace_level;
                   78459:                         $m = array();
                   78460:                     } elseif ($look_for == T_NEW) {
                   78461:                         $used_classes[$data] = true;
                   78462:                     }
                   78463:                     $look_for = 0;
                   78464:                     continue 2;
                   78465:                 case T_VARIABLE:
                   78466:                     $look_for = 0;
                   78467:                     continue 2;
                   78468:                 case T_DOC_COMMENT:
                   78469:                 case T_COMMENT:
                   78470:                     if (preg_match('!^/\*\*\s!', $data)) {
                   78471:                         $lastphpdoc = $data;
                   78472:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   78473:                             $nodeps = array_merge($nodeps, $m[1]);
                   78474:                         }
                   78475:                     }
                   78476:                     continue 2;
                   78477:                 case T_DOUBLE_COLON:
                   78478:                     if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
                   78479:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   78480:                             array('file' => $file));
                   78481:                         return false;
                   78482:                     }
                   78483:                     $class = $tokens[$i - 1][1];
                   78484:                     if (strtolower($class) != 'parent') {
                   78485:                         $used_classes[$class] = true;
                   78486:                     }
                   78487:                     continue 2;
                   78488:             }
                   78489:         }
                   78490:         return array(
                   78491:             "source_file" => $file,
                   78492:             "declared_classes" => $declared_classes,
                   78493:             "declared_interfaces" => $declared_interfaces,
                   78494:             "declared_methods" => $declared_methods,
                   78495:             "declared_functions" => $declared_functions,
                   78496:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   78497:             "inheritance" => $extends,
                   78498:             "implements" => $implements,
                   78499:             );
                   78500:     }
                   78501: 
                   78502:     /**
                   78503:      * Build a "provides" array from data returned by
                   78504:      * analyzeSourceCode().  The format of the built array is like
                   78505:      * this:
                   78506:      *
                   78507:      *  array(
                   78508:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   78509:      *    ...
                   78510:      *  )
                   78511:      *
                   78512:      *
                   78513:      * @param array $srcinfo array with information about a source file
                   78514:      * as returned by the analyzeSourceCode() method.
                   78515:      *
                   78516:      * @return void
                   78517:      *
                   78518:      * @access private
                   78519:      *
                   78520:      */
                   78521:     function _buildProvidesArray($srcinfo)
                   78522:     {
                   78523:         if (!$this->_isValid) {
                   78524:             return false;
                   78525:         }
                   78526:         $file = basename($srcinfo['source_file']);
                   78527:         $pn = $this->getPackage();
                   78528:         $pnl = strlen($pn);
                   78529:         foreach ($srcinfo['declared_classes'] as $class) {
                   78530:             $key = "class;$class";
                   78531:             if (isset($this->_packageInfo['provides'][$key])) {
                   78532:                 continue;
                   78533:             }
                   78534:             $this->_packageInfo['provides'][$key] =
                   78535:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   78536:             if (isset($srcinfo['inheritance'][$class])) {
                   78537:                 $this->_packageInfo['provides'][$key]['extends'] =
                   78538:                     $srcinfo['inheritance'][$class];
                   78539:             }
                   78540:         }
                   78541:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   78542:             foreach ($methods as $method) {
                   78543:                 $function = "$class::$method";
                   78544:                 $key = "function;$function";
                   78545:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   78546:                     isset($this->_packageInfo['provides'][$key])) {
                   78547:                     continue;
                   78548:                 }
                   78549:                 $this->_packageInfo['provides'][$key] =
                   78550:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   78551:             }
                   78552:         }
                   78553: 
                   78554:         foreach ($srcinfo['declared_functions'] as $function) {
                   78555:             $key = "function;$function";
                   78556:             if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
                   78557:                 continue;
                   78558:             }
                   78559:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   78560:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   78561:             }
                   78562:             $this->_packageInfo['provides'][$key] =
                   78563:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   78564:         }
                   78565:     }
                   78566: 
                   78567:     // }}}
                   78568: }
                   78569: ?>
                   78570: <?php
                   78571: /**
                   78572:  * PEAR_PackageFile_v2, package.xml version 2.0
                   78573:  *
                   78574:  * PHP versions 4 and 5
                   78575:  *
                   78576:  * @category   pear
                   78577:  * @package    PEAR
                   78578:  * @author     Greg Beaver <cellog@php.net>
                   78579:  * @copyright  1997-2009 The Authors
                   78580:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   78581:  * @version    CVS: $Id: v2.php 309461 2011-03-20 03:57:29Z dufuz $
                   78582:  * @link       http://pear.php.net/package/PEAR
                   78583:  * @since      File available since Release 1.4.0a1
                   78584:  */
                   78585: /**
                   78586:  * For error handling
                   78587:  */
                   78588: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
                   78589: /**
                   78590:  * @category   pear
                   78591:  * @package    PEAR
                   78592:  * @author     Greg Beaver <cellog@php.net>
                   78593:  * @copyright  1997-2009 The Authors
                   78594:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   78595:  * @version    Release: 1.10.0beta1
                   78596:  * @link       http://pear.php.net/package/PEAR
                   78597:  * @since      Class available since Release 1.4.0a1
                   78598:  */
                   78599: class PEAR_PackageFile_v2
                   78600: {
                   78601: 
                   78602:     /**
                   78603:      * Parsed package information
                   78604:      * @var array
                   78605:      * @access private
                   78606:      */
                   78607:     var $_packageInfo = array();
                   78608: 
                   78609:     /**
                   78610:      * path to package .tgz or false if this is a local/extracted package.xml
                   78611:      * @var string|false
                   78612:      * @access private
                   78613:      */
                   78614:     var $_archiveFile;
                   78615: 
                   78616:     /**
                   78617:      * path to package .xml or false if this is an abstract parsed-from-string xml
                   78618:      * @var string|false
                   78619:      * @access private
                   78620:      */
                   78621:     var $_packageFile;
                   78622: 
                   78623:     /**
                   78624:      * This is used by file analysis routines to log progress information
                   78625:      * @var PEAR_Common
                   78626:      * @access protected
                   78627:      */
                   78628:     var $_logger;
                   78629: 
                   78630:     /**
                   78631:      * This is set to the highest validation level that has been validated
                   78632:      *
                   78633:      * If the package.xml is invalid or unknown, this is set to 0.  If
                   78634:      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
                   78635:      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
                   78636:      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
                   78637:      * "caching" to occur, which is particularly important for package validation, so
                   78638:      * that PHP files are not validated twice
                   78639:      * @var int
                   78640:      * @access private
                   78641:      */
                   78642:     var $_isValid = 0;
                   78643: 
                   78644:     /**
                   78645:      * True if the filelist has been validated
                   78646:      * @param bool
                   78647:      */
                   78648:     var $_filesValid = false;
                   78649: 
                   78650:     /**
                   78651:      * @var PEAR_Registry
                   78652:      * @access protected
                   78653:      */
                   78654:     var $_registry;
                   78655: 
                   78656:     /**
                   78657:      * @var PEAR_Config
                   78658:      * @access protected
                   78659:      */
                   78660:     var $_config;
                   78661: 
                   78662:     /**
                   78663:      * Optional Dependency group requested for installation
                   78664:      * @var string
                   78665:      * @access private
                   78666:      */
                   78667:     var $_requestedGroup = false;
                   78668: 
                   78669:     /**
                   78670:      * @var PEAR_ErrorStack
                   78671:      * @access protected
                   78672:      */
                   78673:     var $_stack;
                   78674: 
                   78675:     /**
                   78676:      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
                   78677:      */
                   78678:     var $_tasksNs;
                   78679: 
                   78680:     /**
                   78681:      * Determines whether this packagefile was initialized only with partial package info
                   78682:      *
                   78683:      * If this package file was constructed via parsing REST, it will only contain
                   78684:      *
                   78685:      * - package name
                   78686:      * - channel name
                   78687:      * - dependencies
                   78688:      * @var boolean
                   78689:      * @access private
                   78690:      */
                   78691:     var $_incomplete = true;
                   78692: 
                   78693:     /**
                   78694:      * @var PEAR_PackageFile_v2_Validator
                   78695:      */
                   78696:     var $_v2Validator;
                   78697: 
                   78698:     /**
                   78699:      * The constructor merely sets up the private error stack
                   78700:      */
                   78701:     function PEAR_PackageFile_v2()
                   78702:     {
                   78703:         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
                   78704:         $this->_isValid = false;
                   78705:     }
                   78706: 
                   78707:     /**
                   78708:      * To make unit-testing easier
                   78709:      * @param PEAR_Frontend_*
                   78710:      * @param array options
                   78711:      * @param PEAR_Config
                   78712:      * @return PEAR_Downloader
                   78713:      * @access protected
                   78714:      */
                   78715:     function &getPEARDownloader(&$i, $o, &$c)
                   78716:     {
                   78717:         $z = &new PEAR_Downloader($i, $o, $c);
                   78718:         return $z;
                   78719:     }
                   78720: 
                   78721:     /**
                   78722:      * To make unit-testing easier
                   78723:      * @param PEAR_Config
                   78724:      * @param array options
                   78725:      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
                   78726:      * @param int PEAR_VALIDATE_* constant
                   78727:      * @return PEAR_Dependency2
                   78728:      * @access protected
                   78729:      */
                   78730:     function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
                   78731:     {
                   78732:         if (!class_exists('PEAR_Dependency2')) {
                   78733:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
                   78734:         }
                   78735:         $z = &new PEAR_Dependency2($c, $o, $p, $s);
                   78736:         return $z;
                   78737:     }
                   78738: 
                   78739:     function getInstalledBinary()
                   78740:     {
                   78741:         return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
                   78742:             false;
                   78743:     }
                   78744: 
                   78745:     /**
                   78746:      * Installation of source package has failed, attempt to download and install the
                   78747:      * binary version of this package.
                   78748:      * @param PEAR_Installer
                   78749:      * @return array|false
                   78750:      */
                   78751:     function installBinary(&$installer)
                   78752:     {
                   78753:         if (!OS_WINDOWS) {
                   78754:             $a = false;
                   78755:             return $a;
                   78756:         }
                   78757:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   78758:             $releasetype = $this->getPackageType() . 'release';
                   78759:             if (!is_array($installer->getInstallPackages())) {
                   78760:                 $a = false;
                   78761:                 return $a;
                   78762:             }
                   78763:             foreach ($installer->getInstallPackages() as $p) {
                   78764:                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
                   78765:                     if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
                   78766:                         $a = false;
                   78767:                         return $a; // the user probably downloaded it separately
                   78768:                     }
                   78769:                 }
                   78770:             }
                   78771:             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
                   78772:                 $installer->log(0, 'Attempting to download binary version of extension "' .
                   78773:                     $this->_packageInfo['providesextension'] . '"');
                   78774:                 $params = $this->_packageInfo[$releasetype]['binarypackage'];
                   78775:                 if (!is_array($params) || !isset($params[0])) {
                   78776:                     $params = array($params);
                   78777:                 }
                   78778:                 if (isset($this->_packageInfo['channel'])) {
                   78779:                     foreach ($params as $i => $param) {
                   78780:                         $params[$i] = array('channel' => $this->_packageInfo['channel'],
                   78781:                             'package' => $param, 'version' => $this->getVersion());
                   78782:                     }
                   78783:                 }
                   78784:                 $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
                   78785:                     $installer->config);
                   78786:                 $verbose = $dl->config->get('verbose');
                   78787:                 $dl->config->set('verbose', -1);
                   78788:                 foreach ($params as $param) {
                   78789:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   78790:                     $ret = $dl->download(array($param));
                   78791:                     PEAR::popErrorHandling();
                   78792:                     if (is_array($ret) && count($ret)) {
                   78793:                         break;
                   78794:                     }
                   78795:                 }
                   78796:                 $dl->config->set('verbose', $verbose);
                   78797:                 if (is_array($ret)) {
                   78798:                     if (count($ret) == 1) {
                   78799:                         $pf = $ret[0]->getPackageFile();
                   78800:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   78801:                         $err = $installer->install($ret[0]);
                   78802:                         PEAR::popErrorHandling();
                   78803:                         if (is_array($err)) {
                   78804:                             $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
                   78805:                             // "install" self, so all dependencies will work transparently
                   78806:                             $this->_registry->addPackage2($this);
                   78807:                             $installer->log(0, 'Download and install of binary extension "' .
                   78808:                                 $this->_registry->parsedPackageNameToString(
                   78809:                                     array('channel' => $pf->getChannel(),
                   78810:                                           'package' => $pf->getPackage()), true) . '" successful');
                   78811:                             $a = array($ret[0], $err);
                   78812:                             return $a;
                   78813:                         }
                   78814:                         $installer->log(0, 'Download and install of binary extension "' .
                   78815:                             $this->_registry->parsedPackageNameToString(
                   78816:                                     array('channel' => $pf->getChannel(),
                   78817:                                           'package' => $pf->getPackage()), true) . '" failed');
                   78818:                     }
                   78819:                 }
                   78820:             }
                   78821:         }
                   78822:         $a = false;
                   78823:         return $a;
                   78824:     }
                   78825: 
                   78826:     /**
                   78827:      * @return string|false Extension name
                   78828:      */
                   78829:     function getProvidesExtension()
                   78830:     {
                   78831:         if (in_array($this->getPackageType(),
                   78832:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   78833:             if (isset($this->_packageInfo['providesextension'])) {
                   78834:                 return $this->_packageInfo['providesextension'];
                   78835:             }
                   78836:         }
                   78837:         return false;
                   78838:     }
                   78839: 
                   78840:     /**
                   78841:      * @param string Extension name
                   78842:      * @return bool
                   78843:      */
                   78844:     function isExtension($extension)
                   78845:     {
                   78846:         if (in_array($this->getPackageType(),
                   78847:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   78848:             return $this->_packageInfo['providesextension'] == $extension;
                   78849:         }
                   78850:         return false;
                   78851:     }
                   78852: 
                   78853:     /**
                   78854:      * Tests whether every part of the package.xml 1.0 is represented in
                   78855:      * this package.xml 2.0
                   78856:      * @param PEAR_PackageFile_v1
                   78857:      * @return bool
                   78858:      */
                   78859:     function isEquivalent($pf1)
                   78860:     {
                   78861:         if (!$pf1) {
                   78862:             return true;
                   78863:         }
                   78864:         if ($this->getPackageType() == 'bundle') {
                   78865:             return false;
                   78866:         }
                   78867:         $this->_stack->getErrors(true);
                   78868:         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
                   78869:             return false;
                   78870:         }
                   78871:         $pass = true;
                   78872:         if ($pf1->getPackage() != $this->getPackage()) {
                   78873:             $this->_differentPackage($pf1->getPackage());
                   78874:             $pass = false;
                   78875:         }
                   78876:         if ($pf1->getVersion() != $this->getVersion()) {
                   78877:             $this->_differentVersion($pf1->getVersion());
                   78878:             $pass = false;
                   78879:         }
                   78880:         if (trim($pf1->getSummary()) != $this->getSummary()) {
                   78881:             $this->_differentSummary($pf1->getSummary());
                   78882:             $pass = false;
                   78883:         }
                   78884:         if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
                   78885:               preg_replace('/\s+/', '', $this->getDescription())) {
                   78886:             $this->_differentDescription($pf1->getDescription());
                   78887:             $pass = false;
                   78888:         }
                   78889:         if ($pf1->getState() != $this->getState()) {
                   78890:             $this->_differentState($pf1->getState());
                   78891:             $pass = false;
                   78892:         }
                   78893:         if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
                   78894:               preg_replace('/\s+/', '', $pf1->getNotes()))) {
                   78895:             $this->_differentNotes($pf1->getNotes());
                   78896:             $pass = false;
                   78897:         }
                   78898:         $mymaintainers = $this->getMaintainers();
                   78899:         $yourmaintainers = $pf1->getMaintainers();
                   78900:         for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
                   78901:             $reset = false;
                   78902:             for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
                   78903:                 if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
                   78904:                     if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
                   78905:                         $this->_differentRole($mymaintainers[$i2]['handle'],
                   78906:                             $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
                   78907:                         $pass = false;
                   78908:                     }
                   78909:                     if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
                   78910:                         $this->_differentEmail($mymaintainers[$i2]['handle'],
                   78911:                             $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
                   78912:                         $pass = false;
                   78913:                     }
                   78914:                     if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
                   78915:                         $this->_differentName($mymaintainers[$i2]['handle'],
                   78916:                             $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
                   78917:                         $pass = false;
                   78918:                     }
                   78919:                     unset($mymaintainers[$i2]);
                   78920:                     $mymaintainers = array_values($mymaintainers);
                   78921:                     unset($yourmaintainers[$i1]);
                   78922:                     $yourmaintainers = array_values($yourmaintainers);
                   78923:                     $reset = true;
                   78924:                     break;
                   78925:                 }
                   78926:             }
                   78927:             if ($reset) {
                   78928:                 $i1 = -1;
                   78929:             }
                   78930:         }
                   78931:         $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
                   78932:         $filelist = $this->getFilelist();
                   78933:         foreach ($pf1->getFilelist() as $file => $atts) {
                   78934:             if (!isset($filelist[$file])) {
                   78935:                 $this->_missingFile($file);
                   78936:                 $pass = false;
                   78937:             }
                   78938:         }
                   78939:         return $pass;
                   78940:     }
                   78941: 
                   78942:     function _differentPackage($package)
                   78943:     {
                   78944:         $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
                   78945:             'self' => $this->getPackage()),
                   78946:             'package.xml 1.0 package "%package%" does not match "%self%"');
                   78947:     }
                   78948: 
                   78949:     function _differentVersion($version)
                   78950:     {
                   78951:         $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
                   78952:             'self' => $this->getVersion()),
                   78953:             'package.xml 1.0 version "%version%" does not match "%self%"');
                   78954:     }
                   78955: 
                   78956:     function _differentState($state)
                   78957:     {
                   78958:         $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
                   78959:             'self' => $this->getState()),
                   78960:             'package.xml 1.0 state "%state%" does not match "%self%"');
                   78961:     }
                   78962: 
                   78963:     function _differentRole($handle, $role, $selfrole)
                   78964:     {
                   78965:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   78966:             'role' => $role, 'self' => $selfrole),
                   78967:             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
                   78968:     }
                   78969: 
                   78970:     function _differentEmail($handle, $email, $selfemail)
                   78971:     {
                   78972:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   78973:             'email' => $email, 'self' => $selfemail),
                   78974:             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
                   78975:     }
                   78976: 
                   78977:     function _differentName($handle, $name, $selfname)
                   78978:     {
                   78979:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   78980:             'name' => $name, 'self' => $selfname),
                   78981:             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
                   78982:     }
                   78983: 
                   78984:     function _unmatchedMaintainers($my, $yours)
                   78985:     {
                   78986:         if ($my) {
                   78987:             array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
                   78988:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
                   78989:                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
                   78990:         }
                   78991:         if ($yours) {
                   78992:             array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
                   78993:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
                   78994:                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
                   78995:         }
                   78996:     }
                   78997: 
                   78998:     function _differentNotes($notes)
                   78999:     {
                   79000:         $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
                   79001:         $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
                   79002:             substr($this->getNotes(), 0, 24) . '...';
                   79003:         $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
                   79004:             'self' => $truncmynotes),
                   79005:             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
                   79006:     }
                   79007: 
                   79008:     function _differentSummary($summary)
                   79009:     {
                   79010:         $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
                   79011:         $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
                   79012:             substr($this->getsummary(), 0, 24) . '...';
                   79013:         $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
                   79014:             'self' => $truncmysummary),
                   79015:             'package.xml 1.0 summary "%summary%" does not match "%self%"');
                   79016:     }
                   79017: 
                   79018:     function _differentDescription($description)
                   79019:     {
                   79020:         $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
                   79021:         $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
                   79022:             substr($this->getdescription(), 0, 24) . '...');
                   79023:         $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
                   79024:             'self' => $truncmydescription),
                   79025:             'package.xml 1.0 description "%description%" does not match "%self%"');
                   79026:     }
                   79027: 
                   79028:     function _missingFile($file)
                   79029:     {
                   79030:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   79031:             'package.xml 1.0 file "%file%" is not present in <contents>');
                   79032:     }
                   79033: 
                   79034:     /**
                   79035:      * WARNING - do not use this function unless you know what you're doing
                   79036:      */
                   79037:     function setRawState($state)
                   79038:     {
                   79039:         if (!isset($this->_packageInfo['stability'])) {
                   79040:             $this->_packageInfo['stability'] = array();
                   79041:         }
                   79042:         $this->_packageInfo['stability']['release'] = $state;
                   79043:     }
                   79044: 
                   79045:     /**
                   79046:      * WARNING - do not use this function unless you know what you're doing
                   79047:      */
                   79048:     function setRawCompatible($compatible)
                   79049:     {
                   79050:         $this->_packageInfo['compatible'] = $compatible;
                   79051:     }
                   79052: 
                   79053:     /**
                   79054:      * WARNING - do not use this function unless you know what you're doing
                   79055:      */
                   79056:     function setRawPackage($package)
                   79057:     {
                   79058:         $this->_packageInfo['name'] = $package;
                   79059:     }
                   79060: 
                   79061:     /**
                   79062:      * WARNING - do not use this function unless you know what you're doing
                   79063:      */
                   79064:     function setRawChannel($channel)
                   79065:     {
                   79066:         $this->_packageInfo['channel'] = $channel;
                   79067:     }
                   79068: 
                   79069:     function setRequestedGroup($group)
                   79070:     {
                   79071:         $this->_requestedGroup = $group;
                   79072:     }
                   79073: 
                   79074:     function getRequestedGroup()
                   79075:     {
                   79076:         if (isset($this->_requestedGroup)) {
                   79077:             return $this->_requestedGroup;
                   79078:         }
                   79079:         return false;
                   79080:     }
                   79081: 
                   79082:     /**
                   79083:      * For saving in the registry.
                   79084:      *
                   79085:      * Set the last version that was installed
                   79086:      * @param string
                   79087:      */
                   79088:     function setLastInstalledVersion($version)
                   79089:     {
                   79090:         $this->_packageInfo['_lastversion'] = $version;
                   79091:     }
                   79092: 
                   79093:     /**
                   79094:      * @return string|false
                   79095:      */
                   79096:     function getLastInstalledVersion()
                   79097:     {
                   79098:         if (isset($this->_packageInfo['_lastversion'])) {
                   79099:             return $this->_packageInfo['_lastversion'];
                   79100:         }
                   79101:         return false;
                   79102:     }
                   79103: 
                   79104:     /**
                   79105:      * Determines whether this package.xml has post-install scripts or not
                   79106:      * @return array|false
                   79107:      */
                   79108:     function listPostinstallScripts()
                   79109:     {
                   79110:         $filelist = $this->getFilelist();
                   79111:         $contents = $this->getContents();
                   79112:         $contents = $contents['dir']['file'];
                   79113:         if (!is_array($contents) || !isset($contents[0])) {
                   79114:             $contents = array($contents);
                   79115:         }
                   79116:         $taskfiles = array();
                   79117:         foreach ($contents as $file) {
                   79118:             $atts = $file['attribs'];
                   79119:             unset($file['attribs']);
                   79120:             if (count($file)) {
                   79121:                 $taskfiles[$atts['name']] = $file;
                   79122:             }
                   79123:         }
                   79124:         $common = new PEAR_Common;
                   79125:         $common->debug = $this->_config->get('verbose');
                   79126:         $this->_scripts = array();
                   79127:         $ret = array();
                   79128:         foreach ($taskfiles as $name => $tasks) {
                   79129:             if (!isset($filelist[$name])) {
                   79130:                 // ignored files will not be in the filelist
                   79131:                 continue;
                   79132:             }
                   79133:             $atts = $filelist[$name];
                   79134:             foreach ($tasks as $tag => $raw) {
                   79135:                 $task = $this->getTask($tag);
                   79136:                 $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
                   79137:                 if ($task->isScript()) {
                   79138:                     $ret[] = $filelist[$name]['installed_as'];
                   79139:                 }
                   79140:             }
                   79141:         }
                   79142:         if (count($ret)) {
                   79143:             return $ret;
                   79144:         }
                   79145:         return false;
                   79146:     }
                   79147: 
                   79148:     /**
                   79149:      * Initialize post-install scripts for running
                   79150:      *
                   79151:      * This method can be used to detect post-install scripts, as the return value
                   79152:      * indicates whether any exist
                   79153:      * @return bool
                   79154:      */
                   79155:     function initPostinstallScripts()
                   79156:     {
                   79157:         $filelist = $this->getFilelist();
                   79158:         $contents = $this->getContents();
                   79159:         $contents = $contents['dir']['file'];
                   79160:         if (!is_array($contents) || !isset($contents[0])) {
                   79161:             $contents = array($contents);
                   79162:         }
                   79163:         $taskfiles = array();
                   79164:         foreach ($contents as $file) {
                   79165:             $atts = $file['attribs'];
                   79166:             unset($file['attribs']);
                   79167:             if (count($file)) {
                   79168:                 $taskfiles[$atts['name']] = $file;
                   79169:             }
                   79170:         }
                   79171:         $common = new PEAR_Common;
                   79172:         $common->debug = $this->_config->get('verbose');
                   79173:         $this->_scripts = array();
                   79174:         foreach ($taskfiles as $name => $tasks) {
                   79175:             if (!isset($filelist[$name])) {
                   79176:                 // file was not installed due to installconditions
                   79177:                 continue;
                   79178:             }
                   79179:             $atts = $filelist[$name];
                   79180:             foreach ($tasks as $tag => $raw) {
                   79181:                 $taskname = $this->getTask($tag);
                   79182:                 $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
                   79183:                 if (!$task->isScript()) {
                   79184:                     continue; // scripts are only handled after installation
                   79185:                 }
                   79186:                 $lastversion = isset($this->_packageInfo['_lastversion']) ?
                   79187:                     $this->_packageInfo['_lastversion'] : null;
                   79188:                 $task->init($raw, $atts, $lastversion);
                   79189:                 $res = $task->startSession($this, $atts['installed_as']);
                   79190:                 if (!$res) {
                   79191:                     continue; // skip this file
                   79192:                 }
                   79193:                 if (PEAR::isError($res)) {
                   79194:                     return $res;
                   79195:                 }
                   79196:                 $assign = &$task;
                   79197:                 $this->_scripts[] = &$assign;
                   79198:             }
                   79199:         }
                   79200:         if (count($this->_scripts)) {
                   79201:             return true;
                   79202:         }
                   79203:         return false;
                   79204:     }
                   79205: 
                   79206:     function runPostinstallScripts()
                   79207:     {
                   79208:         if ($this->initPostinstallScripts()) {
                   79209:             $ui = &PEAR_Frontend::singleton();
                   79210:             if ($ui) {
                   79211:                 $ui->runPostinstallScripts($this->_scripts, $this);
                   79212:             }
                   79213:         }
                   79214:     }
                   79215: 
                   79216: 
                   79217:     /**
                   79218:      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
                   79219:      * <file> tags.
                   79220:      */
                   79221:     function flattenFilelist()
                   79222:     {
                   79223:         if (isset($this->_packageInfo['bundle'])) {
                   79224:             return;
                   79225:         }
                   79226:         $filelist = array();
                   79227:         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
                   79228:             $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
                   79229:             if (!isset($filelist[1])) {
                   79230:                 $filelist = $filelist[0];
                   79231:             }
                   79232:             $this->_packageInfo['contents']['dir']['file'] = $filelist;
                   79233:             unset($this->_packageInfo['contents']['dir']['dir']);
                   79234:         } else {
                   79235:             // else already flattened but check for baseinstalldir propagation
                   79236:             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
                   79237:                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
                   79238:                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
                   79239:                         if (isset($file['attribs']['baseinstalldir'])) {
                   79240:                             continue;
                   79241:                         }
                   79242:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
                   79243:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   79244:                     }
                   79245:                 } else {
                   79246:                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
                   79247:                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
                   79248:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   79249:                     }
                   79250:                 }
                   79251:             }
                   79252:         }
                   79253:     }
                   79254: 
                   79255:     /**
                   79256:      * @param array the final flattened file list
                   79257:      * @param array the current directory being processed
                   79258:      * @param string|false any recursively inherited baeinstalldir attribute
                   79259:      * @param string private recursion variable
                   79260:      * @return array
                   79261:      * @access protected
                   79262:      */
                   79263:     function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
                   79264:     {
                   79265:         if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
                   79266:             $baseinstall = $dir['attribs']['baseinstalldir'];
                   79267:         }
                   79268:         if (isset($dir['dir'])) {
                   79269:             if (!isset($dir['dir'][0])) {
                   79270:                 $dir['dir'] = array($dir['dir']);
                   79271:             }
                   79272:             foreach ($dir['dir'] as $subdir) {
                   79273:                 if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
                   79274:                     $name = '*unknown*';
                   79275:                 } else {
                   79276:                     $name = $subdir['attribs']['name'];
                   79277:                 }
                   79278:                 $newpath = empty($path) ? $name :
                   79279:                     $path . '/' . $name;
                   79280:                 $this->_getFlattenedFilelist($files, $subdir,
                   79281:                     $baseinstall, $newpath);
                   79282:             }
                   79283:         }
                   79284:         if (isset($dir['file'])) {
                   79285:             if (!isset($dir['file'][0])) {
                   79286:                 $dir['file'] = array($dir['file']);
                   79287:             }
                   79288:             foreach ($dir['file'] as $file) {
                   79289:                 $attrs = $file['attribs'];
                   79290:                 $name = $attrs['name'];
                   79291:                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
                   79292:                     $attrs['baseinstalldir'] = $baseinstall;
                   79293:                 }
                   79294:                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
                   79295:                 $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   79296:                     $attrs['name']);
                   79297:                 $file['attribs'] = $attrs;
                   79298:                 $files[] = $file;
                   79299:             }
                   79300:         }
                   79301:     }
                   79302: 
                   79303:     function setConfig(&$config)
                   79304:     {
                   79305:         $this->_config = &$config;
                   79306:         $this->_registry = &$config->getRegistry();
                   79307:     }
                   79308: 
                   79309:     function setLogger(&$logger)
                   79310:     {
                   79311:         if (!is_object($logger) || !method_exists($logger, 'log')) {
                   79312:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   79313:         }
                   79314:         $this->_logger = &$logger;
                   79315:     }
                   79316: 
                   79317:     /**
                   79318:      * WARNING - do not use this function directly unless you know what you're doing
                   79319:      */
                   79320:     function setDeps($deps)
                   79321:     {
                   79322:         $this->_packageInfo['dependencies'] = $deps;
                   79323:     }
                   79324: 
                   79325:     /**
                   79326:      * WARNING - do not use this function directly unless you know what you're doing
                   79327:      */
                   79328:     function setCompatible($compat)
                   79329:     {
                   79330:         $this->_packageInfo['compatible'] = $compat;
                   79331:     }
                   79332: 
                   79333:     function setPackagefile($file, $archive = false)
                   79334:     {
                   79335:         $this->_packageFile = $file;
                   79336:         $this->_archiveFile = $archive ? $archive : $file;
                   79337:     }
                   79338: 
                   79339:     /**
                   79340:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   79341:      * @param boolean determines whether to purge the error stack after retrieving
                   79342:      * @return array
                   79343:      */
                   79344:     function getValidationWarnings($purge = true)
                   79345:     {
                   79346:         return $this->_stack->getErrors($purge);
                   79347:     }
                   79348: 
                   79349:     function getPackageFile()
                   79350:     {
                   79351:         return $this->_packageFile;
                   79352:     }
                   79353: 
                   79354:     function getArchiveFile()
                   79355:     {
                   79356:         return $this->_archiveFile;
                   79357:     }
                   79358: 
                   79359: 
                   79360:     /**
                   79361:      * Directly set the array that defines this packagefile
                   79362:      *
                   79363:      * WARNING: no validation.  This should only be performed by internal methods
                   79364:      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
                   79365:      * @param array
                   79366:      */
                   79367:     function fromArray($pinfo)
                   79368:     {
                   79369:         unset($pinfo['old']);
                   79370:         unset($pinfo['xsdversion']);
                   79371:         // If the changelog isn't an array then it was passed in as an empty tag
                   79372:         if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
                   79373:           unset($pinfo['changelog']);
                   79374:         }
                   79375:         $this->_incomplete = false;
                   79376:         $this->_packageInfo = $pinfo;
                   79377:     }
                   79378: 
                   79379:     function isIncomplete()
                   79380:     {
                   79381:         return $this->_incomplete;
                   79382:     }
                   79383: 
                   79384:     /**
                   79385:      * @return array
                   79386:      */
                   79387:     function toArray($forreg = false)
                   79388:     {
                   79389:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   79390:             return false;
                   79391:         }
                   79392:         return $this->getArray($forreg);
                   79393:     }
                   79394: 
                   79395:     function getArray($forReg = false)
                   79396:     {
                   79397:         if ($forReg) {
                   79398:             $arr = $this->_packageInfo;
                   79399:             $arr['old'] = array();
                   79400:             $arr['old']['version'] = $this->getVersion();
                   79401:             $arr['old']['release_date'] = $this->getDate();
                   79402:             $arr['old']['release_state'] = $this->getState();
                   79403:             $arr['old']['release_license'] = $this->getLicense();
                   79404:             $arr['old']['release_notes'] = $this->getNotes();
                   79405:             $arr['old']['release_deps'] = $this->getDeps();
                   79406:             $arr['old']['maintainers'] = $this->getMaintainers();
                   79407:             $arr['xsdversion'] = '2.0';
                   79408:             return $arr;
                   79409:         } else {
                   79410:             $info = $this->_packageInfo;
                   79411:             unset($info['dirtree']);
                   79412:             if (isset($info['_lastversion'])) {
                   79413:                 unset($info['_lastversion']);
                   79414:             }
                   79415:             if (isset($info['#binarypackage'])) {
                   79416:                 unset($info['#binarypackage']);
                   79417:             }
                   79418:             return $info;
                   79419:         }
                   79420:     }
                   79421: 
                   79422:     function packageInfo($field)
                   79423:     {
                   79424:         $arr = $this->getArray(true);
                   79425:         if ($field == 'state') {
                   79426:             return $arr['stability']['release'];
                   79427:         }
                   79428:         if ($field == 'api-version') {
                   79429:             return $arr['version']['api'];
                   79430:         }
                   79431:         if ($field == 'api-state') {
                   79432:             return $arr['stability']['api'];
                   79433:         }
                   79434:         if (isset($arr['old'][$field])) {
                   79435:             if (!is_string($arr['old'][$field])) {
                   79436:                 return null;
                   79437:             }
                   79438:             return $arr['old'][$field];
                   79439:         }
                   79440:         if (isset($arr[$field])) {
                   79441:             if (!is_string($arr[$field])) {
                   79442:                 return null;
                   79443:             }
                   79444:             return $arr[$field];
                   79445:         }
                   79446:         return null;
                   79447:     }
                   79448: 
                   79449:     function getName()
                   79450:     {
                   79451:         return $this->getPackage();
                   79452:     }
                   79453: 
                   79454:     function getPackage()
                   79455:     {
                   79456:         if (isset($this->_packageInfo['name'])) {
                   79457:             return $this->_packageInfo['name'];
                   79458:         }
                   79459:         return false;
                   79460:     }
                   79461: 
                   79462:     function getChannel()
                   79463:     {
                   79464:         if (isset($this->_packageInfo['uri'])) {
                   79465:             return '__uri';
                   79466:         }
                   79467:         if (isset($this->_packageInfo['channel'])) {
                   79468:             return strtolower($this->_packageInfo['channel']);
                   79469:         }
                   79470:         return false;
                   79471:     }
                   79472: 
                   79473:     function getUri()
                   79474:     {
                   79475:         if (isset($this->_packageInfo['uri'])) {
                   79476:             return $this->_packageInfo['uri'];
                   79477:         }
                   79478:         return false;
                   79479:     }
                   79480: 
                   79481:     function getExtends()
                   79482:     {
                   79483:         if (isset($this->_packageInfo['extends'])) {
                   79484:             return $this->_packageInfo['extends'];
                   79485:         }
                   79486:         return false;
                   79487:     }
                   79488: 
                   79489:     function getSummary()
                   79490:     {
                   79491:         if (isset($this->_packageInfo['summary'])) {
                   79492:             return $this->_packageInfo['summary'];
                   79493:         }
                   79494:         return false;
                   79495:     }
                   79496: 
                   79497:     function getDescription()
                   79498:     {
                   79499:         if (isset($this->_packageInfo['description'])) {
                   79500:             return $this->_packageInfo['description'];
                   79501:         }
                   79502:         return false;
                   79503:     }
                   79504: 
                   79505:     function getMaintainers($raw = false)
                   79506:     {
                   79507:         if (!isset($this->_packageInfo['lead'])) {
                   79508:             return false;
                   79509:         }
                   79510:         if ($raw) {
                   79511:             $ret = array('lead' => $this->_packageInfo['lead']);
                   79512:             (isset($this->_packageInfo['developer'])) ?
                   79513:                 $ret['developer'] = $this->_packageInfo['developer'] :null;
                   79514:             (isset($this->_packageInfo['contributor'])) ?
                   79515:                 $ret['contributor'] = $this->_packageInfo['contributor'] :null;
                   79516:             (isset($this->_packageInfo['helper'])) ?
                   79517:                 $ret['helper'] = $this->_packageInfo['helper'] :null;
                   79518:             return $ret;
                   79519:         } else {
                   79520:             $ret = array();
                   79521:             $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
                   79522:                 array($this->_packageInfo['lead']);
                   79523:             foreach ($leads as $lead) {
                   79524:                 $s = $lead;
                   79525:                 $s['handle'] = $s['user'];
                   79526:                 unset($s['user']);
                   79527:                 $s['role'] = 'lead';
                   79528:                 $ret[] = $s;
                   79529:             }
                   79530:             if (isset($this->_packageInfo['developer'])) {
                   79531:                 $leads = isset($this->_packageInfo['developer'][0]) ?
                   79532:                     $this->_packageInfo['developer'] :
                   79533:                     array($this->_packageInfo['developer']);
                   79534:                 foreach ($leads as $maintainer) {
                   79535:                     $s = $maintainer;
                   79536:                     $s['handle'] = $s['user'];
                   79537:                     unset($s['user']);
                   79538:                     $s['role'] = 'developer';
                   79539:                     $ret[] = $s;
                   79540:                 }
                   79541:             }
                   79542:             if (isset($this->_packageInfo['contributor'])) {
                   79543:                 $leads = isset($this->_packageInfo['contributor'][0]) ?
                   79544:                     $this->_packageInfo['contributor'] :
                   79545:                     array($this->_packageInfo['contributor']);
                   79546:                 foreach ($leads as $maintainer) {
                   79547:                     $s = $maintainer;
                   79548:                     $s['handle'] = $s['user'];
                   79549:                     unset($s['user']);
                   79550:                     $s['role'] = 'contributor';
                   79551:                     $ret[] = $s;
                   79552:                 }
                   79553:             }
                   79554:             if (isset($this->_packageInfo['helper'])) {
                   79555:                 $leads = isset($this->_packageInfo['helper'][0]) ?
                   79556:                     $this->_packageInfo['helper'] :
                   79557:                     array($this->_packageInfo['helper']);
                   79558:                 foreach ($leads as $maintainer) {
                   79559:                     $s = $maintainer;
                   79560:                     $s['handle'] = $s['user'];
                   79561:                     unset($s['user']);
                   79562:                     $s['role'] = 'helper';
                   79563:                     $ret[] = $s;
                   79564:                 }
                   79565:             }
                   79566:             return $ret;
                   79567:         }
                   79568:         return false;
                   79569:     }
                   79570: 
                   79571:     function getLeads()
                   79572:     {
                   79573:         if (isset($this->_packageInfo['lead'])) {
                   79574:             return $this->_packageInfo['lead'];
                   79575:         }
                   79576:         return false;
                   79577:     }
                   79578: 
                   79579:     function getDevelopers()
                   79580:     {
                   79581:         if (isset($this->_packageInfo['developer'])) {
                   79582:             return $this->_packageInfo['developer'];
                   79583:         }
                   79584:         return false;
                   79585:     }
                   79586: 
                   79587:     function getContributors()
                   79588:     {
                   79589:         if (isset($this->_packageInfo['contributor'])) {
                   79590:             return $this->_packageInfo['contributor'];
                   79591:         }
                   79592:         return false;
                   79593:     }
                   79594: 
                   79595:     function getHelpers()
                   79596:     {
                   79597:         if (isset($this->_packageInfo['helper'])) {
                   79598:             return $this->_packageInfo['helper'];
                   79599:         }
                   79600:         return false;
                   79601:     }
                   79602: 
                   79603:     function setDate($date)
                   79604:     {
                   79605:         if (!isset($this->_packageInfo['date'])) {
                   79606:             // ensure that the extends tag is set up in the right location
                   79607:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   79608:                 array('time', 'version',
                   79609:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   79610:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   79611:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   79612:                     'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
                   79613:         }
                   79614:         $this->_packageInfo['date'] = $date;
                   79615:         $this->_isValid = 0;
                   79616:     }
                   79617: 
                   79618:     function setTime($time)
                   79619:     {
                   79620:         $this->_isValid = 0;
                   79621:         if (!isset($this->_packageInfo['time'])) {
                   79622:             // ensure that the time tag is set up in the right location
                   79623:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   79624:                     array('version',
                   79625:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   79626:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   79627:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   79628:                     'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
                   79629:         }
                   79630:         $this->_packageInfo['time'] = $time;
                   79631:     }
                   79632: 
                   79633:     function getDate()
                   79634:     {
                   79635:         if (isset($this->_packageInfo['date'])) {
                   79636:             return $this->_packageInfo['date'];
                   79637:         }
                   79638:         return false;
                   79639:     }
                   79640: 
                   79641:     function getTime()
                   79642:     {
                   79643:         if (isset($this->_packageInfo['time'])) {
                   79644:             return $this->_packageInfo['time'];
                   79645:         }
                   79646:         return false;
                   79647:     }
                   79648: 
                   79649:     /**
                   79650:      * @param package|api version category to return
                   79651:      */
                   79652:     function getVersion($key = 'release')
                   79653:     {
                   79654:         if (isset($this->_packageInfo['version'][$key])) {
                   79655:             return $this->_packageInfo['version'][$key];
                   79656:         }
                   79657:         return false;
                   79658:     }
                   79659: 
                   79660:     function getStability()
                   79661:     {
                   79662:         if (isset($this->_packageInfo['stability'])) {
                   79663:             return $this->_packageInfo['stability'];
                   79664:         }
                   79665:         return false;
                   79666:     }
                   79667: 
                   79668:     function getState($key = 'release')
                   79669:     {
                   79670:         if (isset($this->_packageInfo['stability'][$key])) {
                   79671:             return $this->_packageInfo['stability'][$key];
                   79672:         }
                   79673:         return false;
                   79674:     }
                   79675: 
                   79676:     function getLicense($raw = false)
                   79677:     {
                   79678:         if (isset($this->_packageInfo['license'])) {
                   79679:             if ($raw) {
                   79680:                 return $this->_packageInfo['license'];
                   79681:             }
                   79682:             if (is_array($this->_packageInfo['license'])) {
                   79683:                 return $this->_packageInfo['license']['_content'];
                   79684:             } else {
                   79685:                 return $this->_packageInfo['license'];
                   79686:             }
                   79687:         }
                   79688:         return false;
                   79689:     }
                   79690: 
                   79691:     function getLicenseLocation()
                   79692:     {
                   79693:         if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
                   79694:             return false;
                   79695:         }
                   79696:         return $this->_packageInfo['license']['attribs'];
                   79697:     }
                   79698: 
                   79699:     function getNotes()
                   79700:     {
                   79701:         if (isset($this->_packageInfo['notes'])) {
                   79702:             return $this->_packageInfo['notes'];
                   79703:         }
                   79704:         return false;
                   79705:     }
                   79706: 
                   79707:     /**
                   79708:      * Return the <usesrole> tag contents, if any
                   79709:      * @return array|false
                   79710:      */
                   79711:     function getUsesrole()
                   79712:     {
                   79713:         if (isset($this->_packageInfo['usesrole'])) {
                   79714:             return $this->_packageInfo['usesrole'];
                   79715:         }
                   79716:         return false;
                   79717:     }
                   79718: 
                   79719:     /**
                   79720:      * Return the <usestask> tag contents, if any
                   79721:      * @return array|false
                   79722:      */
                   79723:     function getUsestask()
                   79724:     {
                   79725:         if (isset($this->_packageInfo['usestask'])) {
                   79726:             return $this->_packageInfo['usestask'];
                   79727:         }
                   79728:         return false;
                   79729:     }
                   79730: 
                   79731:     /**
                   79732:      * This should only be used to retrieve filenames and install attributes
                   79733:      */
                   79734:     function getFilelist($preserve = false)
                   79735:     {
                   79736:         if (isset($this->_packageInfo['filelist']) && !$preserve) {
                   79737:             return $this->_packageInfo['filelist'];
                   79738:         }
                   79739: 
                   79740:         $this->flattenFilelist();
                   79741:         if ($contents = $this->getContents()) {
                   79742:             $ret = array();
                   79743:             if (!isset($contents['dir'])) {
                   79744:                 return false;
                   79745:             }
                   79746: 
                   79747:             if (!isset($contents['dir']['file'][0])) {
                   79748:                 $contents['dir']['file'] = array($contents['dir']['file']);
                   79749:             }
                   79750: 
                   79751:             foreach ($contents['dir']['file'] as $file) {
                   79752:                 $name = $file['attribs']['name'];
                   79753:                 if (!$preserve) {
                   79754:                     $file = $file['attribs'];
                   79755:                 }
                   79756:                 $ret[$name] = $file;
                   79757:             }
                   79758: 
                   79759:             if (!$preserve) {
                   79760:                 $this->_packageInfo['filelist'] = $ret;
                   79761:             }
                   79762: 
                   79763:             return $ret;
                   79764:         }
                   79765: 
                   79766:         return false;
                   79767:     }
                   79768: 
                   79769:     /**
                   79770:      * Return configure options array, if any
                   79771:      *
                   79772:      * @return array|false
                   79773:      */
                   79774:     function getConfigureOptions()
                   79775:     {
                   79776:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   79777:             return false;
                   79778:         }
                   79779: 
                   79780:         $releases = $this->getReleases();
                   79781:         if (isset($releases[0])) {
                   79782:             $releases = $releases[0];
                   79783:         }
                   79784: 
                   79785:         if (isset($releases['configureoption'])) {
                   79786:             if (!isset($releases['configureoption'][0])) {
                   79787:                 $releases['configureoption'] = array($releases['configureoption']);
                   79788:             }
                   79789: 
                   79790:             for ($i = 0; $i < count($releases['configureoption']); $i++) {
                   79791:                 $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
                   79792:             }
                   79793: 
                   79794:             return $releases['configureoption'];
                   79795:         }
                   79796: 
                   79797:         return false;
                   79798:     }
                   79799: 
                   79800:     /**
                   79801:      * This is only used at install-time, after all serialization
                   79802:      * is over.
                   79803:      */
                   79804:     function resetFilelist()
                   79805:     {
                   79806:         $this->_packageInfo['filelist'] = array();
                   79807:     }
                   79808: 
                   79809:     /**
                   79810:      * Retrieve a list of files that should be installed on this computer
                   79811:      * @return array
                   79812:      */
                   79813:     function getInstallationFilelist($forfilecheck = false)
                   79814:     {
                   79815:         $contents = $this->getFilelist(true);
                   79816:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
                   79817:             $base = $contents['dir']['attribs']['baseinstalldir'];
                   79818:         }
                   79819: 
                   79820:         if (isset($this->_packageInfo['bundle'])) {
                   79821:             return PEAR::raiseError(
                   79822:                 'Exception: bundles should be handled in download code only');
                   79823:         }
                   79824: 
                   79825:         $release = $this->getReleases();
                   79826:         if ($release) {
                   79827:             if (!isset($release[0])) {
                   79828:                 if (!isset($release['installconditions']) && !isset($release['filelist'])) {
                   79829:                     if ($forfilecheck) {
                   79830:                         return $this->getFilelist();
                   79831:                     }
                   79832: 
                   79833:                     return $contents;
                   79834:                 }
                   79835:                 $release = array($release);
                   79836:             }
                   79837: 
                   79838:             $depchecker = &$this->getPEARDependency2($this->_config, array(),
                   79839:                 array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
                   79840:                 PEAR_VALIDATE_INSTALLING);
                   79841:             foreach ($release as $instance) {
                   79842:                 if (isset($instance['installconditions'])) {
                   79843:                     $installconditions = $instance['installconditions'];
                   79844:                     if (is_array($installconditions)) {
                   79845:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   79846:                         foreach ($installconditions as $type => $conditions) {
                   79847:                             if (!isset($conditions[0])) {
                   79848:                                 $conditions = array($conditions);
                   79849:                             }
                   79850: 
                   79851:                             foreach ($conditions as $condition) {
                   79852:                                 $ret = $depchecker->{"validate{$type}Dependency"}($condition);
                   79853:                                 if (PEAR::isError($ret)) {
                   79854:                                     PEAR::popErrorHandling();
                   79855:                                     continue 3; // skip this release
                   79856:                                 }
                   79857:                             }
                   79858:                         }
                   79859: 
                   79860:                         PEAR::popErrorHandling();
                   79861:                     }
                   79862:                 }
                   79863: 
                   79864:                 // this is the release to use
                   79865:                 if (isset($instance['filelist'])) {
                   79866:                     // ignore files
                   79867:                     if (isset($instance['filelist']['ignore'])) {
                   79868:                         $ignore = isset($instance['filelist']['ignore'][0]) ?
                   79869:                             $instance['filelist']['ignore'] :
                   79870:                             array($instance['filelist']['ignore']);
                   79871:                         foreach ($ignore as $ig) {
                   79872:                             unset ($contents[$ig['attribs']['name']]);
                   79873:                         }
                   79874:                     }
                   79875: 
                   79876:                     // install files as this name
                   79877:                     if (isset($instance['filelist']['install'])) {
                   79878:                         $installas = isset($instance['filelist']['install'][0]) ?
                   79879:                             $instance['filelist']['install'] :
                   79880:                             array($instance['filelist']['install']);
                   79881:                         foreach ($installas as $as) {
                   79882:                             $contents[$as['attribs']['name']]['attribs']['install-as'] =
                   79883:                                 $as['attribs']['as'];
                   79884:                         }
                   79885:                     }
                   79886:                 }
                   79887: 
                   79888:                 if ($forfilecheck) {
                   79889:                     foreach ($contents as $file => $attrs) {
                   79890:                         $contents[$file] = $attrs['attribs'];
                   79891:                     }
                   79892:                 }
                   79893: 
                   79894:                 return $contents;
                   79895:             }
                   79896:         } else { // simple release - no installconditions or install-as
                   79897:             if ($forfilecheck) {
                   79898:                 return $this->getFilelist();
                   79899:             }
                   79900: 
                   79901:             return $contents;
                   79902:         }
                   79903: 
                   79904:         // no releases matched
                   79905:         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
                   79906:             'system, extensions installed, or architecture, cannot install');
                   79907:     }
                   79908: 
                   79909:     /**
                   79910:      * This is only used at install-time, after all serialization
                   79911:      * is over.
                   79912:      * @param string file name
                   79913:      * @param string installed path
                   79914:      */
                   79915:     function setInstalledAs($file, $path)
                   79916:     {
                   79917:         if ($path) {
                   79918:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   79919:         }
                   79920:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   79921:     }
                   79922: 
                   79923:     function getInstalledLocation($file)
                   79924:     {
                   79925:         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
                   79926:             return $this->_packageInfo['filelist'][$file]['installed_as'];
                   79927:         }
                   79928:         return false;
                   79929:     }
                   79930: 
                   79931:     /**
                   79932:      * This is only used at install-time, after all serialization
                   79933:      * is over.
                   79934:      */
                   79935:     function installedFile($file, $atts)
                   79936:     {
                   79937:         if (isset($this->_packageInfo['filelist'][$file])) {
                   79938:             $this->_packageInfo['filelist'][$file] =
                   79939:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
                   79940:         } else {
                   79941:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
                   79942:         }
                   79943:     }
                   79944: 
                   79945:     /**
                   79946:      * Retrieve the contents tag
                   79947:      */
                   79948:     function getContents()
                   79949:     {
                   79950:         if (isset($this->_packageInfo['contents'])) {
                   79951:             return $this->_packageInfo['contents'];
                   79952:         }
                   79953:         return false;
                   79954:     }
                   79955: 
                   79956:     /**
                   79957:      * @param string full path to file
                   79958:      * @param string attribute name
                   79959:      * @param string attribute value
                   79960:      * @param int risky but fast - use this to choose a file based on its position in the list
                   79961:      *            of files.  Index is zero-based like PHP arrays.
                   79962:      * @return bool success of operation
                   79963:      */
                   79964:     function setFileAttribute($filename, $attr, $value, $index = false)
                   79965:     {
                   79966:         $this->_isValid = 0;
                   79967:         if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
                   79968:             $this->_filesValid = false;
                   79969:         }
                   79970:         if ($index !== false &&
                   79971:               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
                   79972:             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
                   79973:             return true;
                   79974:         }
                   79975:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
                   79976:             return false;
                   79977:         }
                   79978:         $files = $this->_packageInfo['contents']['dir']['file'];
                   79979:         if (!isset($files[0])) {
                   79980:             $files = array($files);
                   79981:             $ind = false;
                   79982:         } else {
                   79983:             $ind = true;
                   79984:         }
                   79985:         foreach ($files as $i => $file) {
                   79986:             if (isset($file['attribs'])) {
                   79987:                 if ($file['attribs']['name'] == $filename) {
                   79988:                     if ($ind) {
                   79989:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
                   79990:                     } else {
                   79991:                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
                   79992:                     }
                   79993:                     return true;
                   79994:                 }
                   79995:             }
                   79996:         }
                   79997:         return false;
                   79998:     }
                   79999: 
                   80000:     function setDirtree($path)
                   80001:     {
                   80002:         if (!isset($this->_packageInfo['dirtree'])) {
                   80003:             $this->_packageInfo['dirtree'] = array();
                   80004:         }
                   80005:         $this->_packageInfo['dirtree'][$path] = true;
                   80006:     }
                   80007: 
                   80008:     function getDirtree()
                   80009:     {
                   80010:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   80011:             return $this->_packageInfo['dirtree'];
                   80012:         }
                   80013:         return false;
                   80014:     }
                   80015: 
                   80016:     function resetDirtree()
                   80017:     {
                   80018:         unset($this->_packageInfo['dirtree']);
                   80019:     }
                   80020: 
                   80021:     /**
                   80022:      * Determines whether this package claims it is compatible with the version of
                   80023:      * the package that has a recommended version dependency
                   80024:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
                   80025:      * @return boolean
                   80026:      */
                   80027:     function isCompatible($pf)
                   80028:     {
                   80029:         if (!isset($this->_packageInfo['compatible'])) {
                   80030:             return false;
                   80031:         }
                   80032:         if (!isset($this->_packageInfo['channel'])) {
                   80033:             return false;
                   80034:         }
                   80035:         $me = $pf->getVersion();
                   80036:         $compatible = $this->_packageInfo['compatible'];
                   80037:         if (!isset($compatible[0])) {
                   80038:             $compatible = array($compatible);
                   80039:         }
                   80040:         $found = false;
                   80041:         foreach ($compatible as $info) {
                   80042:             if (strtolower($info['name']) == strtolower($pf->getPackage())) {
                   80043:                 if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
                   80044:                     $found = true;
                   80045:                     break;
                   80046:                 }
                   80047:             }
                   80048:         }
                   80049:         if (!$found) {
                   80050:             return false;
                   80051:         }
                   80052:         if (isset($info['exclude'])) {
                   80053:             if (!isset($info['exclude'][0])) {
                   80054:                 $info['exclude'] = array($info['exclude']);
                   80055:             }
                   80056:             foreach ($info['exclude'] as $exclude) {
                   80057:                 if (version_compare($me, $exclude, '==')) {
                   80058:                     return false;
                   80059:                 }
                   80060:             }
                   80061:         }
                   80062:         if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
                   80063:             return true;
                   80064:         }
                   80065:         return false;
                   80066:     }
                   80067: 
                   80068:     /**
                   80069:      * @return array|false
                   80070:      */
                   80071:     function getCompatible()
                   80072:     {
                   80073:         if (isset($this->_packageInfo['compatible'])) {
                   80074:             return $this->_packageInfo['compatible'];
                   80075:         }
                   80076:         return false;
                   80077:     }
                   80078: 
                   80079:     function getDependencies()
                   80080:     {
                   80081:         if (isset($this->_packageInfo['dependencies'])) {
                   80082:             return $this->_packageInfo['dependencies'];
                   80083:         }
                   80084:         return false;
                   80085:     }
                   80086: 
                   80087:     function isSubpackageOf($p)
                   80088:     {
                   80089:         return $p->isSubpackage($this);
                   80090:     }
                   80091: 
                   80092:     /**
                   80093:      * Determines whether the passed in package is a subpackage of this package.
                   80094:      *
                   80095:      * No version checking is done, only name verification.
                   80096:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   80097:      * @return bool
                   80098:      */
                   80099:     function isSubpackage($p)
                   80100:     {
                   80101:         $sub = array();
                   80102:         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
                   80103:             $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
                   80104:             if (!isset($sub[0])) {
                   80105:                 $sub = array($sub);
                   80106:             }
                   80107:         }
                   80108:         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
                   80109:             $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
                   80110:             if (!isset($sub1[0])) {
                   80111:                 $sub1 = array($sub1);
                   80112:             }
                   80113:             $sub = array_merge($sub, $sub1);
                   80114:         }
                   80115:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   80116:             $group = $this->_packageInfo['dependencies']['group'];
                   80117:             if (!isset($group[0])) {
                   80118:                 $group = array($group);
                   80119:             }
                   80120:             foreach ($group as $deps) {
                   80121:                 if (isset($deps['subpackage'])) {
                   80122:                     $sub2 = $deps['subpackage'];
                   80123:                     if (!isset($sub2[0])) {
                   80124:                         $sub2 = array($sub2);
                   80125:                     }
                   80126:                     $sub = array_merge($sub, $sub2);
                   80127:                 }
                   80128:             }
                   80129:         }
                   80130:         foreach ($sub as $dep) {
                   80131:             if (strtolower($dep['name']) == strtolower($p->getPackage())) {
                   80132:                 if (isset($dep['channel'])) {
                   80133:                     if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
                   80134:                         return true;
                   80135:                     }
                   80136:                 } else {
                   80137:                     if ($dep['uri'] == $p->getURI()) {
                   80138:                         return true;
                   80139:                     }
                   80140:                 }
                   80141:             }
                   80142:         }
                   80143:         return false;
                   80144:     }
                   80145: 
                   80146:     function dependsOn($package, $channel)
                   80147:     {
                   80148:         if (!($deps = $this->getDependencies())) {
                   80149:             return false;
                   80150:         }
                   80151:         foreach (array('package', 'subpackage') as $type) {
                   80152:             foreach (array('required', 'optional') as $needed) {
                   80153:                 if (isset($deps[$needed][$type])) {
                   80154:                     if (!isset($deps[$needed][$type][0])) {
                   80155:                         $deps[$needed][$type] = array($deps[$needed][$type]);
                   80156:                     }
                   80157:                     foreach ($deps[$needed][$type] as $dep) {
                   80158:                         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   80159:                         if (strtolower($dep['name']) == strtolower($package) &&
                   80160:                               $depchannel == $channel) {
                   80161:                             return true;
                   80162:                         }
                   80163:                     }
                   80164:                 }
                   80165:             }
                   80166:             if (isset($deps['group'])) {
                   80167:                 if (!isset($deps['group'][0])) {
                   80168:                     $dep['group'] = array($deps['group']);
                   80169:                 }
                   80170:                 foreach ($deps['group'] as $group) {
                   80171:                     if (isset($group[$type])) {
                   80172:                         if (!is_array($group[$type])) {
                   80173:                             $group[$type] = array($group[$type]);
                   80174:                         }
                   80175:                         foreach ($group[$type] as $dep) {
                   80176:                             $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   80177:                             if (strtolower($dep['name']) == strtolower($package) &&
                   80178:                                   $depchannel == $channel) {
                   80179:                                 return true;
                   80180:                             }
                   80181:                         }
                   80182:                     }
                   80183:                 }
                   80184:             }
                   80185:         }
                   80186:         return false;
                   80187:     }
                   80188: 
                   80189:     /**
                   80190:      * Get the contents of a dependency group
                   80191:      * @param string
                   80192:      * @return array|false
                   80193:      */
                   80194:     function getDependencyGroup($name)
                   80195:     {
                   80196:         $name = strtolower($name);
                   80197:         if (!isset($this->_packageInfo['dependencies']['group'])) {
                   80198:             return false;
                   80199:         }
                   80200:         $groups = $this->_packageInfo['dependencies']['group'];
                   80201:         if (!isset($groups[0])) {
                   80202:             $groups = array($groups);
                   80203:         }
                   80204:         foreach ($groups as $group) {
                   80205:             if (strtolower($group['attribs']['name']) == $name) {
                   80206:                 return $group;
                   80207:             }
                   80208:         }
                   80209:         return false;
                   80210:     }
                   80211: 
                   80212:     /**
                   80213:      * Retrieve a partial package.xml 1.0 representation of dependencies
                   80214:      *
                   80215:      * a very limited representation of dependencies is returned by this method.
                   80216:      * The <exclude> tag for excluding certain versions of a dependency is
                   80217:      * completely ignored.  In addition, dependency groups are ignored, with the
                   80218:      * assumption that all dependencies in dependency groups are also listed in
                   80219:      * the optional group that work with all dependency groups
                   80220:      * @param boolean return package.xml 2.0 <dependencies> tag
                   80221:      * @return array|false
                   80222:      */
                   80223:     function getDeps($raw = false, $nopearinstaller = false)
                   80224:     {
                   80225:         if (isset($this->_packageInfo['dependencies'])) {
                   80226:             if ($raw) {
                   80227:                 return $this->_packageInfo['dependencies'];
                   80228:             }
                   80229:             $ret = array();
                   80230:             $map = array(
                   80231:                 'php' => 'php',
                   80232:                 'package' => 'pkg',
                   80233:                 'subpackage' => 'pkg',
                   80234:                 'extension' => 'ext',
                   80235:                 'os' => 'os',
                   80236:                 'pearinstaller' => 'pkg',
                   80237:                 );
                   80238:             foreach (array('required', 'optional') as $type) {
                   80239:                 $optional = ($type == 'optional') ? 'yes' : 'no';
                   80240:                 if (!isset($this->_packageInfo['dependencies'][$type])
                   80241:                     || empty($this->_packageInfo['dependencies'][$type])) {
                   80242:                     continue;
                   80243:                 }
                   80244:                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
                   80245:                     if ($dtype == 'pearinstaller' && $nopearinstaller) {
                   80246:                         continue;
                   80247:                     }
                   80248:                     if (!isset($deps[0])) {
                   80249:                         $deps = array($deps);
                   80250:                     }
                   80251:                     foreach ($deps as $dep) {
                   80252:                         if (!isset($map[$dtype])) {
                   80253:                             // no support for arch type
                   80254:                             continue;
                   80255:                         }
                   80256:                         if ($dtype == 'pearinstaller') {
                   80257:                             $dep['name'] = 'PEAR';
                   80258:                             $dep['channel'] = 'pear.php.net';
                   80259:                         }
                   80260:                         $s = array('type' => $map[$dtype]);
                   80261:                         if (isset($dep['channel'])) {
                   80262:                             $s['channel'] = $dep['channel'];
                   80263:                         }
                   80264:                         if (isset($dep['uri'])) {
                   80265:                             $s['uri'] = $dep['uri'];
                   80266:                         }
                   80267:                         if (isset($dep['name'])) {
                   80268:                             $s['name'] = $dep['name'];
                   80269:                         }
                   80270:                         if (isset($dep['conflicts'])) {
                   80271:                             $s['rel'] = 'not';
                   80272:                         } else {
                   80273:                             if (!isset($dep['min']) &&
                   80274:                                   !isset($dep['max'])) {
                   80275:                                 $s['rel'] = 'has';
                   80276:                                 $s['optional'] = $optional;
                   80277:                             } elseif (isset($dep['min']) &&
                   80278:                                   isset($dep['max'])) {
                   80279:                                 $s['rel'] = 'ge';
                   80280:                                 $s1 = $s;
                   80281:                                 $s1['rel'] = 'le';
                   80282:                                 $s['version'] = $dep['min'];
                   80283:                                 $s1['version'] = $dep['max'];
                   80284:                                 if (isset($dep['channel'])) {
                   80285:                                     $s1['channel'] = $dep['channel'];
                   80286:                                 }
                   80287:                                 if ($dtype != 'php') {
                   80288:                                     $s['name'] = $dep['name'];
                   80289:                                     $s1['name'] = $dep['name'];
                   80290:                                 }
                   80291:                                 $s['optional'] = $optional;
                   80292:                                 $s1['optional'] = $optional;
                   80293:                                 $ret[] = $s1;
                   80294:                             } elseif (isset($dep['min'])) {
                   80295:                                 if (isset($dep['exclude']) &&
                   80296:                                       $dep['exclude'] == $dep['min']) {
                   80297:                                     $s['rel'] = 'gt';
                   80298:                                 } else {
                   80299:                                     $s['rel'] = 'ge';
                   80300:                                 }
                   80301:                                 $s['version'] = $dep['min'];
                   80302:                                 $s['optional'] = $optional;
                   80303:                                 if ($dtype != 'php') {
                   80304:                                     $s['name'] = $dep['name'];
                   80305:                                 }
                   80306:                             } elseif (isset($dep['max'])) {
                   80307:                                 if (isset($dep['exclude']) &&
                   80308:                                       $dep['exclude'] == $dep['max']) {
                   80309:                                     $s['rel'] = 'lt';
                   80310:                                 } else {
                   80311:                                     $s['rel'] = 'le';
                   80312:                                 }
                   80313:                                 $s['version'] = $dep['max'];
                   80314:                                 $s['optional'] = $optional;
                   80315:                                 if ($dtype != 'php') {
                   80316:                                     $s['name'] = $dep['name'];
                   80317:                                 }
                   80318:                             }
                   80319:                         }
                   80320:                         $ret[] = $s;
                   80321:                     }
                   80322:                 }
                   80323:             }
                   80324:             if (count($ret)) {
                   80325:                 return $ret;
                   80326:             }
                   80327:         }
                   80328:         return false;
                   80329:     }
                   80330: 
                   80331:     /**
                   80332:      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
                   80333:      */
                   80334:     function getPackageType()
                   80335:     {
                   80336:         if (isset($this->_packageInfo['phprelease'])) {
                   80337:             return 'php';
                   80338:         }
                   80339:         if (isset($this->_packageInfo['extsrcrelease'])) {
                   80340:             return 'extsrc';
                   80341:         }
                   80342:         if (isset($this->_packageInfo['extbinrelease'])) {
                   80343:             return 'extbin';
                   80344:         }
                   80345:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   80346:             return 'zendextsrc';
                   80347:         }
                   80348:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   80349:             return 'zendextbin';
                   80350:         }
                   80351:         if (isset($this->_packageInfo['bundle'])) {
                   80352:             return 'bundle';
                   80353:         }
                   80354:         return false;
                   80355:     }
                   80356: 
                   80357:     /**
                   80358:      * @return array|false
                   80359:      */
                   80360:     function getReleases()
                   80361:     {
                   80362:         $type = $this->getPackageType();
                   80363:         if ($type != 'bundle') {
                   80364:             $type .= 'release';
                   80365:         }
                   80366:         if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
                   80367:             return $this->_packageInfo[$type];
                   80368:         }
                   80369:         return false;
                   80370:     }
                   80371: 
                   80372:     /**
                   80373:      * @return array
                   80374:      */
                   80375:     function getChangelog()
                   80376:     {
                   80377:         if (isset($this->_packageInfo['changelog'])) {
                   80378:             return $this->_packageInfo['changelog'];
                   80379:         }
                   80380:         return false;
                   80381:     }
                   80382: 
                   80383:     function hasDeps()
                   80384:     {
                   80385:         return isset($this->_packageInfo['dependencies']);
                   80386:     }
                   80387: 
                   80388:     function getPackagexmlVersion()
                   80389:     {
                   80390:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   80391:             return '2.1';
                   80392:         }
                   80393:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   80394:             return '2.1';
                   80395:         }
                   80396:         return '2.0';
                   80397:     }
                   80398: 
                   80399:     /**
                   80400:      * @return array|false
                   80401:      */
                   80402:     function getSourcePackage()
                   80403:     {
                   80404:         if (isset($this->_packageInfo['extbinrelease']) ||
                   80405:               isset($this->_packageInfo['zendextbinrelease'])) {
                   80406:             return array('channel' => $this->_packageInfo['srcchannel'],
                   80407:                          'package' => $this->_packageInfo['srcpackage']);
                   80408:         }
                   80409:         return false;
                   80410:     }
                   80411: 
                   80412:     function getBundledPackages()
                   80413:     {
                   80414:         if (isset($this->_packageInfo['bundle'])) {
                   80415:             return $this->_packageInfo['contents']['bundledpackage'];
                   80416:         }
                   80417:         return false;
                   80418:     }
                   80419: 
                   80420:     function getLastModified()
                   80421:     {
                   80422:         if (isset($this->_packageInfo['_lastmodified'])) {
                   80423:             return $this->_packageInfo['_lastmodified'];
                   80424:         }
                   80425:         return false;
                   80426:     }
                   80427: 
                   80428:     /**
                   80429:      * Get the contents of a file listed within the package.xml
                   80430:      * @param string
                   80431:      * @return string
                   80432:      */
                   80433:     function getFileContents($file)
                   80434:     {
                   80435:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   80436:             $dir = dirname($this->_packageFile);
                   80437:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   80438:             $file = str_replace(array('/', '\\'),
                   80439:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   80440:             if (file_exists($file) && is_readable($file)) {
                   80441:                 return implode('', file($file));
                   80442:             }
                   80443:         } else { // tgz
                   80444:             $tar = &new Archive_Tar($this->_archiveFile);
                   80445:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   80446:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   80447:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   80448:             }
                   80449:             $file = $tar->extractInString($file);
                   80450:             $tar->popErrorHandling();
                   80451:             if (PEAR::isError($file)) {
                   80452:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   80453:             }
                   80454:             return $file;
                   80455:         }
                   80456:     }
                   80457: 
                   80458:     function &getRW()
                   80459:     {
                   80460:         if (!class_exists('PEAR_PackageFile_v2_rw')) {
                   80461:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/rw.php';
                   80462:         }
                   80463:         $a = new PEAR_PackageFile_v2_rw;
                   80464:         foreach (get_object_vars($this) as $name => $unused) {
                   80465:             if (!isset($this->$name)) {
                   80466:                 continue;
                   80467:             }
                   80468:             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
                   80469:                   $name == '_stack') {
                   80470:                 $a->$name = &$this->$name;
                   80471:             } else {
                   80472:                 $a->$name = $this->$name;
                   80473:             }
                   80474:         }
                   80475:         return $a;
                   80476:     }
                   80477: 
                   80478:     function &getDefaultGenerator()
                   80479:     {
                   80480:         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
                   80481:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v2.php';
                   80482:         }
                   80483:         $a = &new PEAR_PackageFile_Generator_v2($this);
                   80484:         return $a;
                   80485:     }
                   80486: 
                   80487:     function analyzeSourceCode($file, $string = false)
                   80488:     {
                   80489:         if (!isset($this->_v2Validator) ||
                   80490:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   80491:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   80492:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
                   80493:             }
                   80494:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   80495:         }
                   80496:         return $this->_v2Validator->analyzeSourceCode($file, $string);
                   80497:     }
                   80498: 
                   80499:     function validate($state = PEAR_VALIDATE_NORMAL)
                   80500:     {
                   80501:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   80502:             return false;
                   80503:         }
                   80504:         if (!isset($this->_v2Validator) ||
                   80505:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   80506:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   80507:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
                   80508:             }
                   80509:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   80510:         }
                   80511:         if (isset($this->_packageInfo['xsdversion'])) {
                   80512:             unset($this->_packageInfo['xsdversion']);
                   80513:         }
                   80514:         return $this->_v2Validator->validate($this, $state);
                   80515:     }
                   80516: 
                   80517:     function getTasksNs()
                   80518:     {
                   80519:         if (!isset($this->_tasksNs)) {
                   80520:             if (isset($this->_packageInfo['attribs'])) {
                   80521:                 foreach ($this->_packageInfo['attribs'] as $name => $value) {
                   80522:                     if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
                   80523:                         $this->_tasksNs = str_replace('xmlns:', '', $name);
                   80524:                         break;
                   80525:                     }
                   80526:                 }
                   80527:             }
                   80528:         }
                   80529:         return $this->_tasksNs;
                   80530:     }
                   80531: 
                   80532:     /**
                   80533:      * Determine whether a task name is a valid task.  Custom tasks may be defined
                   80534:      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
                   80535:      *
                   80536:      * Note that this method will auto-load the task class file and test for the existence
                   80537:      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
                   80538:      * PEAR_Task_mycustom_task
                   80539:      * @param string
                   80540:      * @return boolean
                   80541:      */
                   80542:     function getTask($task)
                   80543:     {
                   80544:         $this->getTasksNs();
                   80545:         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
                   80546:         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
                   80547:         $taskfile = str_replace(' ', '/', ucwords($task));
                   80548:         $task = str_replace(array(' ', '/'), '_', ucwords($task));
                   80549:         if (class_exists("PEAR_Task_$task")) {
                   80550:             return "PEAR_Task_$task";
                   80551:         }
                   80552:         $fp = @fopen("phar://install-pear-nozlib.phar/PEAR/Task/$taskfile.php", 'r', true);
                   80553:         if ($fp) {
                   80554:             fclose($fp);
                   80555:             require_once  'phar://install-pear-nozlib.phar/' . "PEAR/Task/$taskfile.php";
                   80556:             return "PEAR_Task_$task";
                   80557:         }
                   80558:         return false;
                   80559:     }
                   80560: 
                   80561:     /**
                   80562:      * Key-friendly array_splice
                   80563:      * @param tagname to splice a value in before
                   80564:      * @param mixed the value to splice in
                   80565:      * @param string the new tag name
                   80566:      */
                   80567:     function _ksplice($array, $key, $value, $newkey)
                   80568:     {
                   80569:         $offset = array_search($key, array_keys($array));
                   80570:         $after = array_slice($array, $offset);
                   80571:         $before = array_slice($array, 0, $offset);
                   80572:         $before[$newkey] = $value;
                   80573:         return array_merge($before, $after);
                   80574:     }
                   80575: 
                   80576:     /**
                   80577:      * @param array a list of possible keys, in the order they may occur
                   80578:      * @param mixed contents of the new package.xml tag
                   80579:      * @param string tag name
                   80580:      * @access private
                   80581:      */
                   80582:     function _insertBefore($array, $keys, $contents, $newkey)
                   80583:     {
                   80584:         foreach ($keys as $key) {
                   80585:             if (isset($array[$key])) {
                   80586:                 return $array = $this->_ksplice($array, $key, $contents, $newkey);
                   80587:             }
                   80588:         }
                   80589:         $array[$newkey] = $contents;
                   80590:         return $array;
                   80591:     }
                   80592: 
                   80593:     /**
                   80594:      * @param subsection of {@link $_packageInfo}
                   80595:      * @param array|string tag contents
                   80596:      * @param array format:
                   80597:      * <pre>
                   80598:      * array(
                   80599:      *   tagname => array(list of tag names that follow this one),
                   80600:      *   childtagname => array(list of child tag names that follow this one),
                   80601:      * )
                   80602:      * </pre>
                   80603:      *
                   80604:      * This allows construction of nested tags
                   80605:      * @access private
                   80606:      */
                   80607:     function _mergeTag($manip, $contents, $order)
                   80608:     {
                   80609:         if (count($order)) {
                   80610:             foreach ($order as $tag => $curorder) {
                   80611:                 if (!isset($manip[$tag])) {
                   80612:                     // ensure that the tag is set up
                   80613:                     $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
                   80614:                 }
                   80615:                 if (count($order) > 1) {
                   80616:                     $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
                   80617:                     return $manip;
                   80618:                 }
                   80619:             }
                   80620:         } else {
                   80621:             return $manip;
                   80622:         }
                   80623:         if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
                   80624:             $manip[$tag][] = $contents;
                   80625:         } else {
                   80626:             if (!count($manip[$tag])) {
                   80627:                 $manip[$tag] = $contents;
                   80628:             } else {
                   80629:                 $manip[$tag] = array($manip[$tag]);
                   80630:                 $manip[$tag][] = $contents;
                   80631:             }
                   80632:         }
                   80633:         return $manip;
                   80634:     }
                   80635: }
                   80636: ?>
                   80637: <?php
                   80638: /**
                   80639:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
                   80640:  *
                   80641:  * PHP versions 4 and 5
                   80642:  *
                   80643:  * @category   pear
                   80644:  * @package    PEAR
                   80645:  * @author     Greg Beaver <cellog@php.net>
                   80646:  * @copyright  1997-2009 The Authors
                   80647:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   80648:  * @version    CVS: $Id: Validator.php 308728 2011-02-27 18:58:02Z dufuz $
                   80649:  * @link       http://pear.php.net/package/PEAR
                   80650:  * @since      File available since Release 1.4.0a8
                   80651:  */
                   80652: /**
                   80653:  * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
                   80654:  * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
                   80655:  * @category   pear
                   80656:  * @package    PEAR
                   80657:  * @author     Greg Beaver <cellog@php.net>
                   80658:  * @copyright  1997-2009 The Authors
                   80659:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   80660:  * @version    Release: 1.10.0beta1
                   80661:  * @link       http://pear.php.net/package/PEAR
                   80662:  * @since      Class available since Release 1.4.0a8
                   80663:  * @access private
                   80664:  */
                   80665: class PEAR_PackageFile_v2_Validator
                   80666: {
                   80667:     /**
                   80668:      * @var array
                   80669:      */
                   80670:     var $_packageInfo;
                   80671:     /**
                   80672:      * @var PEAR_PackageFile_v2
                   80673:      */
                   80674:     var $_pf;
                   80675:     /**
                   80676:      * @var PEAR_ErrorStack
                   80677:      */
                   80678:     var $_stack;
                   80679:     /**
                   80680:      * @var int
                   80681:      */
                   80682:     var $_isValid = 0;
                   80683:     /**
                   80684:      * @var int
                   80685:      */
                   80686:     var $_filesValid = 0;
                   80687:     /**
                   80688:      * @var int
                   80689:      */
                   80690:     var $_curState = 0;
                   80691:     /**
                   80692:      * @param PEAR_PackageFile_v2
                   80693:      * @param int
                   80694:      */
                   80695:     function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
                   80696:     {
                   80697:         $this->_pf = &$pf;
                   80698:         $this->_curState = $state;
                   80699:         $this->_packageInfo = $this->_pf->getArray();
                   80700:         $this->_isValid = $this->_pf->_isValid;
                   80701:         $this->_filesValid = $this->_pf->_filesValid;
                   80702:         $this->_stack = &$pf->_stack;
                   80703:         $this->_stack->getErrors(true);
                   80704:         if (($this->_isValid & $state) == $state) {
                   80705:             return true;
                   80706:         }
                   80707:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   80708:             return false;
                   80709:         }
                   80710:         if (!isset($this->_packageInfo['attribs']['version']) ||
                   80711:               ($this->_packageInfo['attribs']['version'] != '2.0' &&
                   80712:                $this->_packageInfo['attribs']['version'] != '2.1')
                   80713:         ) {
                   80714:             $this->_noPackageVersion();
                   80715:         }
                   80716:         $structure =
                   80717:         array(
                   80718:             'name',
                   80719:             'channel|uri',
                   80720:             '*extends', // can't be multiple, but this works fine
                   80721:             'summary',
                   80722:             'description',
                   80723:             '+lead', // these all need content checks
                   80724:             '*developer',
                   80725:             '*contributor',
                   80726:             '*helper',
                   80727:             'date',
                   80728:             '*time',
                   80729:             'version',
                   80730:             'stability',
                   80731:             'license->?uri->?filesource',
                   80732:             'notes',
                   80733:             'contents', //special validation needed
                   80734:             '*compatible',
                   80735:             'dependencies', //special validation needed
                   80736:             '*usesrole',
                   80737:             '*usestask', // reserve these for 1.4.0a1 to implement
                   80738:                          // this will allow a package.xml to gracefully say it
                   80739:                          // needs a certain package installed in order to implement a role or task
                   80740:             '*providesextension',
                   80741:             '*srcpackage|*srcuri',
                   80742:             '+phprelease|+extsrcrelease|+extbinrelease|' .
                   80743:                 '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
                   80744:             '*changelog',
                   80745:         );
                   80746:         $test = $this->_packageInfo;
                   80747:         if (isset($test['dependencies']) &&
                   80748:               isset($test['dependencies']['required']) &&
                   80749:               isset($test['dependencies']['required']['pearinstaller']) &&
                   80750:               isset($test['dependencies']['required']['pearinstaller']['min']) &&
                   80751:               version_compare('1.10.0beta1',
                   80752:                 $test['dependencies']['required']['pearinstaller']['min'], '<')
                   80753:         ) {
                   80754:             $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
                   80755:             return false;
                   80756:         }
                   80757:         // ignore post-installation array fields
                   80758:         if (array_key_exists('filelist', $test)) {
                   80759:             unset($test['filelist']);
                   80760:         }
                   80761:         if (array_key_exists('_lastmodified', $test)) {
                   80762:             unset($test['_lastmodified']);
                   80763:         }
                   80764:         if (array_key_exists('#binarypackage', $test)) {
                   80765:             unset($test['#binarypackage']);
                   80766:         }
                   80767:         if (array_key_exists('old', $test)) {
                   80768:             unset($test['old']);
                   80769:         }
                   80770:         if (array_key_exists('_lastversion', $test)) {
                   80771:             unset($test['_lastversion']);
                   80772:         }
                   80773:         if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
                   80774:             return false;
                   80775:         }
                   80776:         if (empty($this->_packageInfo['name'])) {
                   80777:             $this->_tagCannotBeEmpty('name');
                   80778:         }
                   80779:         $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
                   80780:         if (empty($this->_packageInfo[$test])) {
                   80781:             $this->_tagCannotBeEmpty($test);
                   80782:         }
                   80783:         if (is_array($this->_packageInfo['license']) &&
                   80784:               (!isset($this->_packageInfo['license']['_content']) ||
                   80785:               empty($this->_packageInfo['license']['_content']))) {
                   80786:             $this->_tagCannotBeEmpty('license');
                   80787:         } elseif (empty($this->_packageInfo['license'])) {
                   80788:             $this->_tagCannotBeEmpty('license');
                   80789:         }
                   80790:         if (empty($this->_packageInfo['summary'])) {
                   80791:             $this->_tagCannotBeEmpty('summary');
                   80792:         }
                   80793:         if (empty($this->_packageInfo['description'])) {
                   80794:             $this->_tagCannotBeEmpty('description');
                   80795:         }
                   80796:         if (empty($this->_packageInfo['date'])) {
                   80797:             $this->_tagCannotBeEmpty('date');
                   80798:         }
                   80799:         if (empty($this->_packageInfo['notes'])) {
                   80800:             $this->_tagCannotBeEmpty('notes');
                   80801:         }
                   80802:         if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
                   80803:             $this->_tagCannotBeEmpty('time');
                   80804:         }
                   80805:         if (isset($this->_packageInfo['dependencies'])) {
                   80806:             $this->_validateDependencies();
                   80807:         }
                   80808:         if (isset($this->_packageInfo['compatible'])) {
                   80809:             $this->_validateCompatible();
                   80810:         }
                   80811:         if (!isset($this->_packageInfo['bundle'])) {
                   80812:             if (empty($this->_packageInfo['contents'])) {
                   80813:                 $this->_tagCannotBeEmpty('contents');
                   80814:             }
                   80815:             if (!isset($this->_packageInfo['contents']['dir'])) {
                   80816:                 $this->_filelistMustContainDir('contents');
                   80817:                 return false;
                   80818:             }
                   80819:             if (isset($this->_packageInfo['contents']['file'])) {
                   80820:                 $this->_filelistCannotContainFile('contents');
                   80821:                 return false;
                   80822:             }
                   80823:         }
                   80824:         $this->_validateMaintainers();
                   80825:         $this->_validateStabilityVersion();
                   80826:         $fail = false;
                   80827:         if (array_key_exists('usesrole', $this->_packageInfo)) {
                   80828:             $roles = $this->_packageInfo['usesrole'];
                   80829:             if (!is_array($roles) || !isset($roles[0])) {
                   80830:                 $roles = array($roles);
                   80831:             }
                   80832:             foreach ($roles as $role) {
                   80833:                 if (!isset($role['role'])) {
                   80834:                     $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
                   80835:                     $fail = true;
                   80836:                 } else {
                   80837:                     if (!isset($role['channel'])) {
                   80838:                         if (!isset($role['uri'])) {
                   80839:                             $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
                   80840:                             $fail = true;
                   80841:                         }
                   80842:                     } elseif (!isset($role['package'])) {
                   80843:                         $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
                   80844:                         $fail = true;
                   80845:                     }
                   80846:                 }
                   80847:             }
                   80848:         }
                   80849:         if (array_key_exists('usestask', $this->_packageInfo)) {
                   80850:             $roles = $this->_packageInfo['usestask'];
                   80851:             if (!is_array($roles) || !isset($roles[0])) {
                   80852:                 $roles = array($roles);
                   80853:             }
                   80854:             foreach ($roles as $role) {
                   80855:                 if (!isset($role['task'])) {
                   80856:                     $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
                   80857:                     $fail = true;
                   80858:                 } else {
                   80859:                     if (!isset($role['channel'])) {
                   80860:                         if (!isset($role['uri'])) {
                   80861:                             $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
                   80862:                             $fail = true;
                   80863:                         }
                   80864:                     } elseif (!isset($role['package'])) {
                   80865:                         $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
                   80866:                         $fail = true;
                   80867:                     }
                   80868:                 }
                   80869:             }
                   80870:         }
                   80871: 
                   80872:         if ($fail) {
                   80873:             return false;
                   80874:         }
                   80875: 
                   80876:         $list = $this->_packageInfo['contents'];
                   80877:         if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
                   80878:             $this->_multipleToplevelDirNotAllowed();
                   80879:             return $this->_isValid = 0;
                   80880:         }
                   80881: 
                   80882:         $this->_validateFilelist();
                   80883:         $this->_validateRelease();
                   80884:         if (!$this->_stack->hasErrors()) {
                   80885:             $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
                   80886:             if (PEAR::isError($chan)) {
                   80887:                 $this->_unknownChannel($this->_pf->getChannel());
                   80888:             } else {
                   80889:                 $valpack = $chan->getValidationPackage();
                   80890:                 // for channel validator packages, always use the default PEAR validator.
                   80891:                 // otherwise, they can't be installed or packaged
                   80892:                 $validator = $chan->getValidationObject($this->_pf->getPackage());
                   80893:                 if (!$validator) {
                   80894:                     $this->_stack->push(__FUNCTION__, 'error',
                   80895:                             array('channel' => $chan->getName(),
                   80896:                               'package' => $this->_pf->getPackage(),
                   80897:                               'name'    => $valpack['_content'],
                   80898:                               'version' => $valpack['attribs']['version']),
                   80899:                         'package "%channel%/%package%" cannot be properly validated without ' .
                   80900:                         'validation package "%channel%/%name%-%version%"');
                   80901:                     return $this->_isValid = 0;
                   80902:                 }
                   80903:                 $validator->setPackageFile($this->_pf);
                   80904:                 $validator->validate($state);
                   80905:                 $failures = $validator->getFailures();
                   80906:                 foreach ($failures['errors'] as $error) {
                   80907:                     $this->_stack->push(__FUNCTION__, 'error', $error,
                   80908:                         'Channel validator error: field "%field%" - %reason%');
                   80909:                 }
                   80910:                 foreach ($failures['warnings'] as $warning) {
                   80911:                     $this->_stack->push(__FUNCTION__, 'warning', $warning,
                   80912:                         'Channel validator warning: field "%field%" - %reason%');
                   80913:                 }
                   80914:             }
                   80915:         }
                   80916: 
                   80917:         $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
                   80918:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
                   80919:             if ($this->_pf->getPackageType() == 'bundle') {
                   80920:                 if ($this->_analyzeBundledPackages()) {
                   80921:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   80922:                 } else {
                   80923:                     $this->_pf->_isValid = $this->_isValid = 0;
                   80924:                 }
                   80925:             } else {
                   80926:                 if (!$this->_analyzePhpFiles()) {
                   80927:                     $this->_pf->_isValid = $this->_isValid = 0;
                   80928:                 } else {
                   80929:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   80930:                 }
                   80931:             }
                   80932:         }
                   80933: 
                   80934:         if ($this->_isValid) {
                   80935:             return $this->_pf->_isValid = $this->_isValid = $state;
                   80936:         }
                   80937: 
                   80938:         return $this->_pf->_isValid = $this->_isValid = 0;
                   80939:     }
                   80940: 
                   80941:     function _stupidSchemaValidate($structure, $xml, $root)
                   80942:     {
                   80943:         if (!is_array($xml)) {
                   80944:             $xml = array();
                   80945:         }
                   80946:         $keys = array_keys($xml);
                   80947:         reset($keys);
                   80948:         $key = current($keys);
                   80949:         while ($key == 'attribs' || $key == '_contents') {
                   80950:             $key = next($keys);
                   80951:         }
                   80952:         $unfoundtags = $optionaltags = array();
                   80953:         $ret = true;
                   80954:         $mismatch = false;
                   80955:         foreach ($structure as $struc) {
                   80956:             if ($key) {
                   80957:                 $tag = $xml[$key];
                   80958:             }
                   80959:             $test = $this->_processStructure($struc);
                   80960:             if (isset($test['choices'])) {
                   80961:                 $loose = true;
                   80962:                 foreach ($test['choices'] as $choice) {
                   80963:                     if ($key == $choice['tag']) {
                   80964:                         $key = next($keys);
                   80965:                         while ($key == 'attribs' || $key == '_contents') {
                   80966:                             $key = next($keys);
                   80967:                         }
                   80968:                         $unfoundtags = $optionaltags = array();
                   80969:                         $mismatch = false;
                   80970:                         if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
                   80971:                             $unfoundtags[] = $choice['tag'];
                   80972:                             $optionaltags[] = $choice['tag'];
                   80973:                             if ($key) {
                   80974:                                 $mismatch = true;
                   80975:                             }
                   80976:                         }
                   80977:                         $ret &= $this->_processAttribs($choice, $tag, $root);
                   80978:                         continue 2;
                   80979:                     } else {
                   80980:                         $unfoundtags[] = $choice['tag'];
                   80981:                         $mismatch = true;
                   80982:                     }
                   80983:                     if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
                   80984:                         $loose = false;
                   80985:                     } else {
                   80986:                         $optionaltags[] = $choice['tag'];
                   80987:                     }
                   80988:                 }
                   80989:                 if (!$loose) {
                   80990:                     $this->_invalidTagOrder($unfoundtags, $key, $root);
                   80991:                     return false;
                   80992:                 }
                   80993:             } else {
                   80994:                 if ($key != $test['tag']) {
                   80995:                     if (isset($test['multiple']) && $test['multiple'] != '*') {
                   80996:                         $unfoundtags[] = $test['tag'];
                   80997:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   80998:                         return false;
                   80999:                     } else {
                   81000:                         if ($key) {
                   81001:                             $mismatch = true;
                   81002:                         }
                   81003:                         $unfoundtags[] = $test['tag'];
                   81004:                         $optionaltags[] = $test['tag'];
                   81005:                     }
                   81006:                     if (!isset($test['multiple'])) {
                   81007:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   81008:                         return false;
                   81009:                     }
                   81010:                     continue;
                   81011:                 } else {
                   81012:                     $unfoundtags = $optionaltags = array();
                   81013:                     $mismatch = false;
                   81014:                 }
                   81015:                 $key = next($keys);
                   81016:                 while ($key == 'attribs' || $key == '_contents') {
                   81017:                     $key = next($keys);
                   81018:                 }
                   81019:                 if ($key && $key != $test['tag'] && isset($test['multiple'])) {
                   81020:                     $unfoundtags[] = $test['tag'];
                   81021:                     $optionaltags[] = $test['tag'];
                   81022:                     $mismatch = true;
                   81023:                 }
                   81024:                 $ret &= $this->_processAttribs($test, $tag, $root);
                   81025:                 continue;
                   81026:             }
                   81027:         }
                   81028:         if (!$mismatch && count($optionaltags)) {
                   81029:             // don't error out on any optional tags
                   81030:             $unfoundtags = array_diff($unfoundtags, $optionaltags);
                   81031:         }
                   81032:         if (count($unfoundtags)) {
                   81033:             $this->_invalidTagOrder($unfoundtags, $key, $root);
                   81034:         } elseif ($key) {
                   81035:             // unknown tags
                   81036:             $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   81037:             while ($key = next($keys)) {
                   81038:                 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   81039:             }
                   81040:         }
                   81041:         return $ret;
                   81042:     }
                   81043: 
                   81044:     function _processAttribs($choice, $tag, $context)
                   81045:     {
                   81046:         if (isset($choice['attribs'])) {
                   81047:             if (!is_array($tag)) {
                   81048:                 $tag = array($tag);
                   81049:             }
                   81050:             $tags = $tag;
                   81051:             if (!isset($tags[0])) {
                   81052:                 $tags = array($tags);
                   81053:             }
                   81054:             $ret = true;
                   81055:             foreach ($tags as $i => $tag) {
                   81056:                 if (!is_array($tag) || !isset($tag['attribs'])) {
                   81057:                     foreach ($choice['attribs'] as $attrib) {
                   81058:                         if ($attrib{0} != '?') {
                   81059:                             $ret &= $this->_tagHasNoAttribs($choice['tag'],
                   81060:                                 $context);
                   81061:                             continue 2;
                   81062:                         }
                   81063:                     }
                   81064:                 }
                   81065:                 foreach ($choice['attribs'] as $attrib) {
                   81066:                     if ($attrib{0} != '?') {
                   81067:                         if (!isset($tag['attribs'][$attrib])) {
                   81068:                             $ret &= $this->_tagMissingAttribute($choice['tag'],
                   81069:                                 $attrib, $context);
                   81070:                         }
                   81071:                     }
                   81072:                 }
                   81073:             }
                   81074:             return $ret;
                   81075:         }
                   81076:         return true;
                   81077:     }
                   81078: 
                   81079:     function _processStructure($key)
                   81080:     {
                   81081:         $ret = array();
                   81082:         if (count($pieces = explode('|', $key)) > 1) {
                   81083:             $ret['choices'] = array();
                   81084:             foreach ($pieces as $piece) {
                   81085:                 $ret['choices'][] = $this->_processStructure($piece);
                   81086:             }
                   81087:             return $ret;
                   81088:         }
                   81089:         $multi = $key{0};
                   81090:         if ($multi == '+' || $multi == '*') {
                   81091:             $ret['multiple'] = $key{0};
                   81092:             $key = substr($key, 1);
                   81093:         }
                   81094:         if (count($attrs = explode('->', $key)) > 1) {
                   81095:             $ret['tag'] = array_shift($attrs);
                   81096:             $ret['attribs'] = $attrs;
                   81097:         } else {
                   81098:             $ret['tag'] = $key;
                   81099:         }
                   81100:         return $ret;
                   81101:     }
                   81102: 
                   81103:     function _validateStabilityVersion()
                   81104:     {
                   81105:         $structure = array('release', 'api');
                   81106:         $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
                   81107:         $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
                   81108:         if ($a) {
                   81109:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81110:                   $this->_packageInfo['version']['release'])) {
                   81111:                 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
                   81112:             }
                   81113:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81114:                   $this->_packageInfo['version']['api'])) {
                   81115:                 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
                   81116:             }
                   81117:             if (!in_array($this->_packageInfo['stability']['release'],
                   81118:                   array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
                   81119:                 $this->_invalidState('release', $this->_packageInfo['stability']['release']);
                   81120:             }
                   81121:             if (!in_array($this->_packageInfo['stability']['api'],
                   81122:                   array('devel', 'alpha', 'beta', 'stable'))) {
                   81123:                 $this->_invalidState('api', $this->_packageInfo['stability']['api']);
                   81124:             }
                   81125:         }
                   81126:     }
                   81127: 
                   81128:     function _validateMaintainers()
                   81129:     {
                   81130:         $structure =
                   81131:             array(
                   81132:                 'name',
                   81133:                 'user',
                   81134:                 'email',
                   81135:                 'active',
                   81136:             );
                   81137:         foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
                   81138:             if (!isset($this->_packageInfo[$type])) {
                   81139:                 continue;
                   81140:             }
                   81141:             if (isset($this->_packageInfo[$type][0])) {
                   81142:                 foreach ($this->_packageInfo[$type] as $lead) {
                   81143:                     $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
                   81144:                 }
                   81145:             } else {
                   81146:                 $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
                   81147:                     '<' . $type . '>');
                   81148:             }
                   81149:         }
                   81150:     }
                   81151: 
                   81152:     function _validatePhpDep($dep, $installcondition = false)
                   81153:     {
                   81154:         $structure = array(
                   81155:             'min',
                   81156:             '*max',
                   81157:             '*exclude',
                   81158:         );
                   81159:         $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
                   81160:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   81161:         if (isset($dep['min'])) {
                   81162:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   81163:                   $dep['min'])) {
                   81164:                 $this->_invalidVersion($type . '<min>', $dep['min']);
                   81165:             }
                   81166:         }
                   81167:         if (isset($dep['max'])) {
                   81168:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   81169:                   $dep['max'])) {
                   81170:                 $this->_invalidVersion($type . '<max>', $dep['max']);
                   81171:             }
                   81172:         }
                   81173:         if (isset($dep['exclude'])) {
                   81174:             if (!is_array($dep['exclude'])) {
                   81175:                 $dep['exclude'] = array($dep['exclude']);
                   81176:             }
                   81177:             foreach ($dep['exclude'] as $exclude) {
                   81178:                 if (!preg_match(
                   81179:                      '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   81180:                      $exclude)) {
                   81181:                     $this->_invalidVersion($type . '<exclude>', $exclude);
                   81182:                 }
                   81183:             }
                   81184:         }
                   81185:     }
                   81186: 
                   81187:     function _validatePearinstallerDep($dep)
                   81188:     {
                   81189:         $structure = array(
                   81190:             'min',
                   81191:             '*max',
                   81192:             '*recommended',
                   81193:             '*exclude',
                   81194:         );
                   81195:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
                   81196:         if (isset($dep['min'])) {
                   81197:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81198:                   $dep['min'])) {
                   81199:                 $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
                   81200:                     $dep['min']);
                   81201:             }
                   81202:         }
                   81203:         if (isset($dep['max'])) {
                   81204:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81205:                   $dep['max'])) {
                   81206:                 $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
                   81207:                     $dep['max']);
                   81208:             }
                   81209:         }
                   81210:         if (isset($dep['recommended'])) {
                   81211:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81212:                   $dep['recommended'])) {
                   81213:                 $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
                   81214:                     $dep['recommended']);
                   81215:             }
                   81216:         }
                   81217:         if (isset($dep['exclude'])) {
                   81218:             if (!is_array($dep['exclude'])) {
                   81219:                 $dep['exclude'] = array($dep['exclude']);
                   81220:             }
                   81221:             foreach ($dep['exclude'] as $exclude) {
                   81222:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81223:                       $exclude)) {
                   81224:                     $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
                   81225:                         $exclude);
                   81226:                 }
                   81227:             }
                   81228:         }
                   81229:     }
                   81230: 
                   81231:     function _validatePackageDep($dep, $group, $type = '<package>')
                   81232:     {
                   81233:         if (isset($dep['uri'])) {
                   81234:             if (isset($dep['conflicts'])) {
                   81235:                 $structure = array(
                   81236:                     'name',
                   81237:                     'uri',
                   81238:                     'conflicts',
                   81239:                     '*providesextension',
                   81240:                 );
                   81241:             } else {
                   81242:                 $structure = array(
                   81243:                     'name',
                   81244:                     'uri',
                   81245:                     '*providesextension',
                   81246:                 );
                   81247:             }
                   81248:         } else {
                   81249:             if (isset($dep['conflicts'])) {
                   81250:                 $structure = array(
                   81251:                     'name',
                   81252:                     'channel',
                   81253:                     '*min',
                   81254:                     '*max',
                   81255:                     '*exclude',
                   81256:                     'conflicts',
                   81257:                     '*providesextension',
                   81258:                 );
                   81259:             } else {
                   81260:                 $structure = array(
                   81261:                     'name',
                   81262:                     'channel',
                   81263:                     '*min',
                   81264:                     '*max',
                   81265:                     '*recommended',
                   81266:                     '*exclude',
                   81267:                     '*nodefault',
                   81268:                     '*providesextension',
                   81269:                 );
                   81270:             }
                   81271:         }
                   81272:         if (isset($dep['name'])) {
                   81273:             $type .= '<name>' . $dep['name'] . '</name>';
                   81274:         }
                   81275:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
                   81276:         if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
                   81277:               isset($dep['recommended']) || isset($dep['exclude']))) {
                   81278:             $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
                   81279:         }
                   81280:         if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
                   81281:             $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
                   81282:         }
                   81283:         if (isset($dep['min'])) {
                   81284:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81285:                   $dep['min'])) {
                   81286:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
                   81287:             }
                   81288:         }
                   81289:         if (isset($dep['max'])) {
                   81290:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81291:                   $dep['max'])) {
                   81292:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
                   81293:             }
                   81294:         }
                   81295:         if (isset($dep['recommended'])) {
                   81296:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81297:                   $dep['recommended'])) {
                   81298:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
                   81299:                     $dep['recommended']);
                   81300:             }
                   81301:         }
                   81302:         if (isset($dep['exclude'])) {
                   81303:             if (!is_array($dep['exclude'])) {
                   81304:                 $dep['exclude'] = array($dep['exclude']);
                   81305:             }
                   81306:             foreach ($dep['exclude'] as $exclude) {
                   81307:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81308:                       $exclude)) {
                   81309:                     $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
                   81310:                         $exclude);
                   81311:                 }
                   81312:             }
                   81313:         }
                   81314:     }
                   81315: 
                   81316:     function _validateSubpackageDep($dep, $group)
                   81317:     {
                   81318:         $this->_validatePackageDep($dep, $group, '<subpackage>');
                   81319:         if (isset($dep['providesextension'])) {
                   81320:             $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
                   81321:         }
                   81322:         if (isset($dep['conflicts'])) {
                   81323:             $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
                   81324:         }
                   81325:     }
                   81326: 
                   81327:     function _validateExtensionDep($dep, $group = false, $installcondition = false)
                   81328:     {
                   81329:         if (isset($dep['conflicts'])) {
                   81330:             $structure = array(
                   81331:                 'name',
                   81332:                 '*min',
                   81333:                 '*max',
                   81334:                 '*exclude',
                   81335:                 'conflicts',
                   81336:             );
                   81337:         } else {
                   81338:             $structure = array(
                   81339:                 'name',
                   81340:                 '*min',
                   81341:                 '*max',
                   81342:                 '*recommended',
                   81343:                 '*exclude',
                   81344:             );
                   81345:         }
                   81346:         if ($installcondition) {
                   81347:             $type = '<installcondition><extension>';
                   81348:         } else {
                   81349:             $type = '<dependencies>' . $group . '<extension>';
                   81350:         }
                   81351:         if (isset($dep['name'])) {
                   81352:             $type .= '<name>' . $dep['name'] . '</name>';
                   81353:         }
                   81354:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   81355:         if (isset($dep['min'])) {
                   81356:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81357:                   $dep['min'])) {
                   81358:                 $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
                   81359:             }
                   81360:         }
                   81361:         if (isset($dep['max'])) {
                   81362:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81363:                   $dep['max'])) {
                   81364:                 $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
                   81365:             }
                   81366:         }
                   81367:         if (isset($dep['recommended'])) {
                   81368:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81369:                   $dep['recommended'])) {
                   81370:                 $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
                   81371:             }
                   81372:         }
                   81373:         if (isset($dep['exclude'])) {
                   81374:             if (!is_array($dep['exclude'])) {
                   81375:                 $dep['exclude'] = array($dep['exclude']);
                   81376:             }
                   81377:             foreach ($dep['exclude'] as $exclude) {
                   81378:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81379:                       $exclude)) {
                   81380:                     $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   81381:                 }
                   81382:             }
                   81383:         }
                   81384:     }
                   81385: 
                   81386:     function _validateOsDep($dep, $installcondition = false)
                   81387:     {
                   81388:         $structure = array(
                   81389:             'name',
                   81390:             '*conflicts',
                   81391:         );
                   81392:         $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
                   81393:         if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
                   81394:             if ($dep['name'] == '*') {
                   81395:                 if (array_key_exists('conflicts', $dep)) {
                   81396:                     $this->_cannotConflictWithAllOs($type);
                   81397:                 }
                   81398:             }
                   81399:         }
                   81400:     }
                   81401: 
                   81402:     function _validateArchDep($dep, $installcondition = false)
                   81403:     {
                   81404:         $structure = array(
                   81405:             'pattern',
                   81406:             '*conflicts',
                   81407:         );
                   81408:         $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
                   81409:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   81410:     }
                   81411: 
                   81412:     function _validateInstallConditions($cond, $release)
                   81413:     {
                   81414:         $structure = array(
                   81415:             '*php',
                   81416:             '*extension',
                   81417:             '*os',
                   81418:             '*arch',
                   81419:         );
                   81420:         if (!$this->_stupidSchemaValidate($structure,
                   81421:               $cond, $release)) {
                   81422:             return false;
                   81423:         }
                   81424:         foreach (array('php', 'extension', 'os', 'arch') as $type) {
                   81425:             if (isset($cond[$type])) {
                   81426:                 $iter = $cond[$type];
                   81427:                 if (!is_array($iter) || !isset($iter[0])) {
                   81428:                     $iter = array($iter);
                   81429:                 }
                   81430:                 foreach ($iter as $package) {
                   81431:                     if ($type == 'extension') {
                   81432:                         $this->{"_validate{$type}Dep"}($package, false, true);
                   81433:                     } else {
                   81434:                         $this->{"_validate{$type}Dep"}($package, true);
                   81435:                     }
                   81436:                 }
                   81437:             }
                   81438:         }
                   81439:     }
                   81440: 
                   81441:     function _validateDependencies()
                   81442:     {
                   81443:         $structure = array(
                   81444:             'required',
                   81445:             '*optional',
                   81446:             '*group->name->hint'
                   81447:         );
                   81448:         if (!$this->_stupidSchemaValidate($structure,
                   81449:               $this->_packageInfo['dependencies'], '<dependencies>')) {
                   81450:             return false;
                   81451:         }
                   81452:         foreach (array('required', 'optional') as $simpledep) {
                   81453:             if (isset($this->_packageInfo['dependencies'][$simpledep])) {
                   81454:                 if ($simpledep == 'optional') {
                   81455:                     $structure = array(
                   81456:                         '*package',
                   81457:                         '*subpackage',
                   81458:                         '*extension',
                   81459:                     );
                   81460:                 } else {
                   81461:                     $structure = array(
                   81462:                         'php',
                   81463:                         'pearinstaller',
                   81464:                         '*package',
                   81465:                         '*subpackage',
                   81466:                         '*extension',
                   81467:                         '*os',
                   81468:                         '*arch',
                   81469:                     );
                   81470:                 }
                   81471:                 if ($this->_stupidSchemaValidate($structure,
                   81472:                       $this->_packageInfo['dependencies'][$simpledep],
                   81473:                       "<dependencies><$simpledep>")) {
                   81474:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   81475:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   81476:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   81477:                             if (!isset($iter[0])) {
                   81478:                                 $iter = array($iter);
                   81479:                             }
                   81480:                             foreach ($iter as $package) {
                   81481:                                 if ($type != 'extension') {
                   81482:                                     if (isset($package['uri'])) {
                   81483:                                         if (isset($package['channel'])) {
                   81484:                                             $this->_UrlOrChannel($type,
                   81485:                                                 $package['name']);
                   81486:                                         }
                   81487:                                     } else {
                   81488:                                         if (!isset($package['channel'])) {
                   81489:                                             $this->_NoChannel($type, $package['name']);
                   81490:                                         }
                   81491:                                     }
                   81492:                                 }
                   81493:                                 $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
                   81494:                             }
                   81495:                         }
                   81496:                     }
                   81497:                     if ($simpledep == 'optional') {
                   81498:                         continue;
                   81499:                     }
                   81500:                     foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
                   81501:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   81502:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   81503:                             if (!isset($iter[0])) {
                   81504:                                 $iter = array($iter);
                   81505:                             }
                   81506:                             foreach ($iter as $package) {
                   81507:                                 $this->{"_validate{$type}Dep"}($package);
                   81508:                             }
                   81509:                         }
                   81510:                     }
                   81511:                 }
                   81512:             }
                   81513:         }
                   81514:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   81515:             $groups = $this->_packageInfo['dependencies']['group'];
                   81516:             if (!isset($groups[0])) {
                   81517:                 $groups = array($groups);
                   81518:             }
                   81519:             $structure = array(
                   81520:                 '*package',
                   81521:                 '*subpackage',
                   81522:                 '*extension',
                   81523:             );
                   81524:             foreach ($groups as $group) {
                   81525:                 if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
                   81526:                     if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
                   81527:                         $this->_invalidDepGroupName($group['attribs']['name']);
                   81528:                     }
                   81529:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   81530:                         if (isset($group[$type])) {
                   81531:                             $iter = $group[$type];
                   81532:                             if (!isset($iter[0])) {
                   81533:                                 $iter = array($iter);
                   81534:                             }
                   81535:                             foreach ($iter as $package) {
                   81536:                                 if ($type != 'extension') {
                   81537:                                     if (isset($package['uri'])) {
                   81538:                                         if (isset($package['channel'])) {
                   81539:                                             $this->_UrlOrChannelGroup($type,
                   81540:                                                 $package['name'],
                   81541:                                                 $group['name']);
                   81542:                                         }
                   81543:                                     } else {
                   81544:                                         if (!isset($package['channel'])) {
                   81545:                                             $this->_NoChannelGroup($type,
                   81546:                                                 $package['name'],
                   81547:                                                 $group['name']);
                   81548:                                         }
                   81549:                                     }
                   81550:                                 }
                   81551:                                 $this->{"_validate{$type}Dep"}($package, '<group name="' .
                   81552:                                     $group['attribs']['name'] . '">');
                   81553:                             }
                   81554:                         }
                   81555:                     }
                   81556:                 }
                   81557:             }
                   81558:         }
                   81559:     }
                   81560: 
                   81561:     function _validateCompatible()
                   81562:     {
                   81563:         $compat = $this->_packageInfo['compatible'];
                   81564:         if (!isset($compat[0])) {
                   81565:             $compat = array($compat);
                   81566:         }
                   81567:         $required = array('name', 'channel', 'min', 'max', '*exclude');
                   81568:         foreach ($compat as $package) {
                   81569:             $type = '<compatible>';
                   81570:             if (is_array($package) && array_key_exists('name', $package)) {
                   81571:                 $type .= '<name>' . $package['name'] . '</name>';
                   81572:             }
                   81573:             $this->_stupidSchemaValidate($required, $package, $type);
                   81574:             if (is_array($package) && array_key_exists('min', $package)) {
                   81575:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81576:                       $package['min'])) {
                   81577:                     $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
                   81578:                 }
                   81579:             }
                   81580:             if (is_array($package) && array_key_exists('max', $package)) {
                   81581:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81582:                       $package['max'])) {
                   81583:                     $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
                   81584:                 }
                   81585:             }
                   81586:             if (is_array($package) && array_key_exists('exclude', $package)) {
                   81587:                 if (!is_array($package['exclude'])) {
                   81588:                     $package['exclude'] = array($package['exclude']);
                   81589:                 }
                   81590:                 foreach ($package['exclude'] as $exclude) {
                   81591:                     if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   81592:                           $exclude)) {
                   81593:                         $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   81594:                     }
                   81595:                 }
                   81596:             }
                   81597:         }
                   81598:     }
                   81599: 
                   81600:     function _validateBundle($list)
                   81601:     {
                   81602:         if (!is_array($list) || !isset($list['bundledpackage'])) {
                   81603:             return $this->_NoBundledPackages();
                   81604:         }
                   81605:         if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
                   81606:             return $this->_AtLeast2BundledPackages();
                   81607:         }
                   81608:         foreach ($list['bundledpackage'] as $package) {
                   81609:             if (!is_string($package)) {
                   81610:                 $this->_bundledPackagesMustBeFilename();
                   81611:             }
                   81612:         }
                   81613:     }
                   81614: 
                   81615:     function _validateFilelist($list = false, $allowignore = false, $dirs = '')
                   81616:     {
                   81617:         $iscontents = false;
                   81618:         if (!$list) {
                   81619:             $iscontents = true;
                   81620:             $list = $this->_packageInfo['contents'];
                   81621:             if (isset($this->_packageInfo['bundle'])) {
                   81622:                 return $this->_validateBundle($list);
                   81623:             }
                   81624:         }
                   81625:         if ($allowignore) {
                   81626:             $struc = array(
                   81627:                 '*install->name->as',
                   81628:                 '*ignore->name'
                   81629:             );
                   81630:         } else {
                   81631:             $struc = array(
                   81632:                 '*dir->name->?baseinstalldir',
                   81633:                 '*file->name->role->?baseinstalldir->?md5sum'
                   81634:             );
                   81635:             if (isset($list['dir']) && isset($list['file'])) {
                   81636:                 // stave off validation errors without requiring a set order.
                   81637:                 $_old = $list;
                   81638:                 if (isset($list['attribs'])) {
                   81639:                     $list = array('attribs' => $_old['attribs']);
                   81640:                 }
                   81641:                 $list['dir'] = $_old['dir'];
                   81642:                 $list['file'] = $_old['file'];
                   81643:             }
                   81644:         }
                   81645:         if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
                   81646:             $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
                   81647:             $dirname = $iscontents ? '<contents>' : $unknown;
                   81648:         } else {
                   81649:             $dirname = '<dir name="' . $list['attribs']['name'] . '">';
                   81650:             if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   81651:                           str_replace('\\', '/', $list['attribs']['name']))) {
                   81652:                 // file contains .. parent directory or . cur directory
                   81653:                 $this->_invalidDirName($list['attribs']['name']);
                   81654:             }
                   81655:         }
                   81656:         $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
                   81657:         if ($allowignore && $res) {
                   81658:             $ignored_or_installed = array();
                   81659:             $this->_pf->getFilelist();
                   81660:             $fcontents = $this->_pf->getContents();
                   81661:             $filelist = array();
                   81662:             if (!isset($fcontents['dir']['file'][0])) {
                   81663:                 $fcontents['dir']['file'] = array($fcontents['dir']['file']);
                   81664:             }
                   81665:             foreach ($fcontents['dir']['file'] as $file) {
                   81666:                 $filelist[$file['attribs']['name']] = true;
                   81667:             }
                   81668:             if (isset($list['install'])) {
                   81669:                 if (!isset($list['install'][0])) {
                   81670:                     $list['install'] = array($list['install']);
                   81671:                 }
                   81672:                 foreach ($list['install'] as $file) {
                   81673:                     if (!isset($filelist[$file['attribs']['name']])) {
                   81674:                         $this->_notInContents($file['attribs']['name'], 'install');
                   81675:                         continue;
                   81676:                     }
                   81677:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   81678:                         $this->_multipleInstallAs($file['attribs']['name']);
                   81679:                     }
                   81680:                     if (!isset($ignored_or_installed[$file['attribs']['name']])) {
                   81681:                         $ignored_or_installed[$file['attribs']['name']] = array();
                   81682:                     }
                   81683:                     $ignored_or_installed[$file['attribs']['name']][] = 1;
                   81684:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   81685:                                   str_replace('\\', '/', $file['attribs']['as']))) {
                   81686:                         // file contains .. parent directory or . cur directory references
                   81687:                         $this->_invalidFileInstallAs($file['attribs']['name'],
                   81688:                             $file['attribs']['as']);
                   81689:                     }
                   81690:                 }
                   81691:             }
                   81692:             if (isset($list['ignore'])) {
                   81693:                 if (!isset($list['ignore'][0])) {
                   81694:                     $list['ignore'] = array($list['ignore']);
                   81695:                 }
                   81696:                 foreach ($list['ignore'] as $file) {
                   81697:                     if (!isset($filelist[$file['attribs']['name']])) {
                   81698:                         $this->_notInContents($file['attribs']['name'], 'ignore');
                   81699:                         continue;
                   81700:                     }
                   81701:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   81702:                         $this->_ignoreAndInstallAs($file['attribs']['name']);
                   81703:                     }
                   81704:                 }
                   81705:             }
                   81706:         }
                   81707:         if (!$allowignore && isset($list['file'])) {
                   81708:             if (is_string($list['file'])) {
                   81709:                 $this->_oldStyleFileNotAllowed();
                   81710:                 return false;
                   81711:             }
                   81712:             if (!isset($list['file'][0])) {
                   81713:                 // single file
                   81714:                 $list['file'] = array($list['file']);
                   81715:             }
                   81716:             foreach ($list['file'] as $i => $file)
                   81717:             {
                   81718:                 if (isset($file['attribs']) && isset($file['attribs']['name'])) {
                   81719:                     if ($file['attribs']['name']{0} == '.' &&
                   81720:                           $file['attribs']['name']{1} == '/') {
                   81721:                         // name is something like "./doc/whatever.txt"
                   81722:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   81723:                     }
                   81724:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   81725:                                   str_replace('\\', '/', $file['attribs']['name']))) {
                   81726:                         // file contains .. parent directory or . cur directory
                   81727:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   81728:                     }
                   81729:                 }
                   81730:                 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
                   81731:                     if (!$this->_validateRole($file['attribs']['role'])) {
                   81732:                         if (isset($this->_packageInfo['usesrole'])) {
                   81733:                             $roles = $this->_packageInfo['usesrole'];
                   81734:                             if (!isset($roles[0])) {
                   81735:                                 $roles = array($roles);
                   81736:                             }
                   81737:                             foreach ($roles as $role) {
                   81738:                                 if ($role['role'] = $file['attribs']['role']) {
                   81739:                                     $msg = 'This package contains role "%role%" and requires ' .
                   81740:                                         'package "%package%" to be used';
                   81741:                                     if (isset($role['uri'])) {
                   81742:                                         $params = array('role' => $role['role'],
                   81743:                                             'package' => $role['uri']);
                   81744:                                     } else {
                   81745:                                         $params = array('role' => $role['role'],
                   81746:                                             'package' => $this->_pf->_registry->
                   81747:                                             parsedPackageNameToString(array('package' =>
                   81748:                                                 $role['package'], 'channel' => $role['channel']),
                   81749:                                                 true));
                   81750:                                     }
                   81751:                                     $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
                   81752:                                 }
                   81753:                             }
                   81754:                         }
                   81755:                         $this->_invalidFileRole($file['attribs']['name'],
                   81756:                             $dirname, $file['attribs']['role']);
                   81757:                     }
                   81758:                 }
                   81759:                 if (!isset($file['attribs'])) {
                   81760:                     continue;
                   81761:                 }
                   81762:                 $save = $file['attribs'];
                   81763:                 if ($dirs) {
                   81764:                     $save['name'] = $dirs . '/' . $save['name'];
                   81765:                 }
                   81766:                 unset($file['attribs']);
                   81767:                 if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
                   81768:                     foreach ($file as $task => $value) {
                   81769:                         if ($tagClass = $this->_pf->getTask($task)) {
                   81770:                             if (!is_array($value) || !isset($value[0])) {
                   81771:                                 $value = array($value);
                   81772:                             }
                   81773:                             foreach ($value as $v) {
                   81774:                                 $ret = call_user_func(array($tagClass, 'validateXml'),
                   81775:                                     $this->_pf, $v, $this->_pf->_config, $save);
                   81776:                                 if (is_array($ret)) {
                   81777:                                     $this->_invalidTask($task, $ret, isset($save['name']) ?
                   81778:                                         $save['name'] : '');
                   81779:                                 }
                   81780:                             }
                   81781:                         } else {
                   81782:                             if (isset($this->_packageInfo['usestask'])) {
                   81783:                                 $roles = $this->_packageInfo['usestask'];
                   81784:                                 if (!isset($roles[0])) {
                   81785:                                     $roles = array($roles);
                   81786:                                 }
                   81787:                                 foreach ($roles as $role) {
                   81788:                                     if ($role['task'] = $task) {
                   81789:                                         $msg = 'This package contains task "%task%" and requires ' .
                   81790:                                             'package "%package%" to be used';
                   81791:                                         if (isset($role['uri'])) {
                   81792:                                             $params = array('task' => $role['task'],
                   81793:                                                 'package' => $role['uri']);
                   81794:                                         } else {
                   81795:                                             $params = array('task' => $role['task'],
                   81796:                                                 'package' => $this->_pf->_registry->
                   81797:                                                 parsedPackageNameToString(array('package' =>
                   81798:                                                     $role['package'], 'channel' => $role['channel']),
                   81799:                                                     true));
                   81800:                                         }
                   81801:                                         $this->_stack->push('_mustInstallTask', 'error',
                   81802:                                             $params, $msg);
                   81803:                                     }
                   81804:                                 }
                   81805:                             }
                   81806:                             $this->_unknownTask($task, $save['name']);
                   81807:                         }
                   81808:                     }
                   81809:                 }
                   81810:             }
                   81811:         }
                   81812:         if (isset($list['ignore'])) {
                   81813:             if (!$allowignore) {
                   81814:                 $this->_ignoreNotAllowed('ignore');
                   81815:             }
                   81816:         }
                   81817:         if (isset($list['install'])) {
                   81818:             if (!$allowignore) {
                   81819:                 $this->_ignoreNotAllowed('install');
                   81820:             }
                   81821:         }
                   81822:         if (isset($list['file'])) {
                   81823:             if ($allowignore) {
                   81824:                 $this->_fileNotAllowed('file');
                   81825:             }
                   81826:         }
                   81827:         if (isset($list['dir'])) {
                   81828:             if ($allowignore) {
                   81829:                 $this->_fileNotAllowed('dir');
                   81830:             } else {
                   81831:                 if (!isset($list['dir'][0])) {
                   81832:                     $list['dir'] = array($list['dir']);
                   81833:                 }
                   81834:                 foreach ($list['dir'] as $dir) {
                   81835:                     if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
                   81836:                         if ($dir['attribs']['name'] == '/' ||
                   81837:                               !isset($this->_packageInfo['contents']['dir']['dir'])) {
                   81838:                             // always use nothing if the filelist has already been flattened
                   81839:                             $newdirs = '';
                   81840:                         } elseif ($dirs == '') {
                   81841:                             $newdirs = $dir['attribs']['name'];
                   81842:                         } else {
                   81843:                             $newdirs = $dirs . '/' . $dir['attribs']['name'];
                   81844:                         }
                   81845:                     } else {
                   81846:                         $newdirs = $dirs;
                   81847:                     }
                   81848:                     $this->_validateFilelist($dir, $allowignore, $newdirs);
                   81849:                 }
                   81850:             }
                   81851:         }
                   81852:     }
                   81853: 
                   81854:     function _validateRelease()
                   81855:     {
                   81856:         if (isset($this->_packageInfo['phprelease'])) {
                   81857:             $release = 'phprelease';
                   81858:             if (isset($this->_packageInfo['providesextension'])) {
                   81859:                 $this->_cannotProvideExtension($release);
                   81860:             }
                   81861:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   81862:                 $this->_cannotHaveSrcpackage($release);
                   81863:             }
                   81864:             $releases = $this->_packageInfo['phprelease'];
                   81865:             if (!is_array($releases)) {
                   81866:                 return true;
                   81867:             }
                   81868:             if (!isset($releases[0])) {
                   81869:                 $releases = array($releases);
                   81870:             }
                   81871:             foreach ($releases as $rel) {
                   81872:                 $this->_stupidSchemaValidate(array(
                   81873:                     '*installconditions',
                   81874:                     '*filelist',
                   81875:                 ), $rel, '<phprelease>');
                   81876:             }
                   81877:         }
                   81878:         foreach (array('', 'zend') as $prefix) {
                   81879:             $releasetype = $prefix . 'extsrcrelease';
                   81880:             if (isset($this->_packageInfo[$releasetype])) {
                   81881:                 $release = $releasetype;
                   81882:                 if (!isset($this->_packageInfo['providesextension'])) {
                   81883:                     $this->_mustProvideExtension($release);
                   81884:                 }
                   81885:                 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   81886:                     $this->_cannotHaveSrcpackage($release);
                   81887:                 }
                   81888:                 $releases = $this->_packageInfo[$releasetype];
                   81889:                 if (!is_array($releases)) {
                   81890:                     return true;
                   81891:                 }
                   81892:                 if (!isset($releases[0])) {
                   81893:                     $releases = array($releases);
                   81894:                 }
                   81895:                 foreach ($releases as $rel) {
                   81896:                     $this->_stupidSchemaValidate(array(
                   81897:                         '*installconditions',
                   81898:                         '*configureoption->name->prompt->?default',
                   81899:                         '*binarypackage',
                   81900:                         '*filelist',
                   81901:                     ), $rel, '<' . $releasetype . '>');
                   81902:                     if (isset($rel['binarypackage'])) {
                   81903:                         if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
                   81904:                             $rel['binarypackage'] = array($rel['binarypackage']);
                   81905:                         }
                   81906:                         foreach ($rel['binarypackage'] as $bin) {
                   81907:                             if (!is_string($bin)) {
                   81908:                                 $this->_binaryPackageMustBePackagename();
                   81909:                             }
                   81910:                         }
                   81911:                     }
                   81912:                 }
                   81913:             }
                   81914:             $releasetype = 'extbinrelease';
                   81915:             if (isset($this->_packageInfo[$releasetype])) {
                   81916:                 $release = $releasetype;
                   81917:                 if (!isset($this->_packageInfo['providesextension'])) {
                   81918:                     $this->_mustProvideExtension($release);
                   81919:                 }
                   81920:                 if (isset($this->_packageInfo['channel']) &&
                   81921:                       !isset($this->_packageInfo['srcpackage'])) {
                   81922:                     $this->_mustSrcPackage($release);
                   81923:                 }
                   81924:                 if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
                   81925:                     $this->_mustSrcuri($release);
                   81926:                 }
                   81927:                 $releases = $this->_packageInfo[$releasetype];
                   81928:                 if (!is_array($releases)) {
                   81929:                     return true;
                   81930:                 }
                   81931:                 if (!isset($releases[0])) {
                   81932:                     $releases = array($releases);
                   81933:                 }
                   81934:                 foreach ($releases as $rel) {
                   81935:                     $this->_stupidSchemaValidate(array(
                   81936:                         '*installconditions',
                   81937:                         '*filelist',
                   81938:                     ), $rel, '<' . $releasetype . '>');
                   81939:                 }
                   81940:             }
                   81941:         }
                   81942:         if (isset($this->_packageInfo['bundle'])) {
                   81943:             $release = 'bundle';
                   81944:             if (isset($this->_packageInfo['providesextension'])) {
                   81945:                 $this->_cannotProvideExtension($release);
                   81946:             }
                   81947:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   81948:                 $this->_cannotHaveSrcpackage($release);
                   81949:             }
                   81950:             $releases = $this->_packageInfo['bundle'];
                   81951:             if (!is_array($releases) || !isset($releases[0])) {
                   81952:                 $releases = array($releases);
                   81953:             }
                   81954:             foreach ($releases as $rel) {
                   81955:                 $this->_stupidSchemaValidate(array(
                   81956:                     '*installconditions',
                   81957:                     '*filelist',
                   81958:                 ), $rel, '<bundle>');
                   81959:             }
                   81960:         }
                   81961:         foreach ($releases as $rel) {
                   81962:             if (is_array($rel) && array_key_exists('installconditions', $rel)) {
                   81963:                 $this->_validateInstallConditions($rel['installconditions'],
                   81964:                     "<$release><installconditions>");
                   81965:             }
                   81966:             if (is_array($rel) && array_key_exists('filelist', $rel)) {
                   81967:                 if ($rel['filelist']) {
                   81968: 
                   81969:                     $this->_validateFilelist($rel['filelist'], true);
                   81970:                 }
                   81971:             }
                   81972:         }
                   81973:     }
                   81974: 
                   81975:     /**
                   81976:      * This is here to allow role extension through plugins
                   81977:      * @param string
                   81978:      */
                   81979:     function _validateRole($role)
                   81980:     {
                   81981:         return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
                   81982:     }
                   81983: 
                   81984:     function _pearVersionTooLow($version)
                   81985:     {
                   81986:         $this->_stack->push(__FUNCTION__, 'error',
                   81987:             array('version' => $version),
                   81988:             'This package.xml requires PEAR version %version% to parse properly, we are ' .
                   81989:             'version 1.10.0beta1');
                   81990:     }
                   81991: 
                   81992:     function _invalidTagOrder($oktags, $actual, $root)
                   81993:     {
                   81994:         $this->_stack->push(__FUNCTION__, 'error',
                   81995:             array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
                   81996:             'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
                   81997:     }
                   81998: 
                   81999:     function _ignoreNotAllowed($type)
                   82000:     {
                   82001:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   82002:             '<%type%> is not allowed inside global <contents>, only inside ' .
                   82003:             '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
                   82004:     }
                   82005: 
                   82006:     function _fileNotAllowed($type)
                   82007:     {
                   82008:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   82009:             '<%type%> is not allowed inside release <filelist>, only inside ' .
                   82010:             '<contents>, use <ignore> and <install> only');
                   82011:     }
                   82012: 
                   82013:     function _oldStyleFileNotAllowed()
                   82014:     {
                   82015:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82016:             'Old-style <file>name</file> is not allowed.  Use' .
                   82017:             '<file name="name" role="role"/>');
                   82018:     }
                   82019: 
                   82020:     function _tagMissingAttribute($tag, $attr, $context)
                   82021:     {
                   82022:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   82023:             'attribute' => $attr, 'context' => $context),
                   82024:             'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
                   82025:     }
                   82026: 
                   82027:     function _tagHasNoAttribs($tag, $context)
                   82028:     {
                   82029:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   82030:             'context' => $context),
                   82031:             'tag <%tag%> has no attributes in context "%context%"');
                   82032:     }
                   82033: 
                   82034:     function _invalidInternalStructure()
                   82035:     {
                   82036:         $this->_stack->push(__FUNCTION__, 'exception', array(),
                   82037:             'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
                   82038:     }
                   82039: 
                   82040:     function _invalidFileRole($file, $dir, $role)
                   82041:     {
                   82042:         $this->_stack->push(__FUNCTION__, 'error', array(
                   82043:             'file' => $file, 'dir' => $dir, 'role' => $role,
                   82044:             'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
                   82045:             'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
                   82046:     }
                   82047: 
                   82048:     function _invalidFileName($file, $dir)
                   82049:     {
                   82050:         $this->_stack->push(__FUNCTION__, 'error', array(
                   82051:             'file' => $file),
                   82052:             'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
                   82053:     }
                   82054: 
                   82055:     function _invalidFileInstallAs($file, $as)
                   82056:     {
                   82057:         $this->_stack->push(__FUNCTION__, 'error', array(
                   82058:             'file' => $file, 'as' => $as),
                   82059:             'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
                   82060:     }
                   82061: 
                   82062:     function _invalidDirName($dir)
                   82063:     {
                   82064:         $this->_stack->push(__FUNCTION__, 'error', array(
                   82065:             'dir' => $file),
                   82066:             'Directory "%dir%" cannot begin with "./" or contain ".."');
                   82067:     }
                   82068: 
                   82069:     function _filelistCannotContainFile($filelist)
                   82070:     {
                   82071:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   82072:             '<%tag%> can only contain <dir>, contains <file>.  Use ' .
                   82073:             '<dir name="/"> as the first dir element');
                   82074:     }
                   82075: 
                   82076:     function _filelistMustContainDir($filelist)
                   82077:     {
                   82078:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   82079:             '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
                   82080:             'first dir element');
                   82081:     }
                   82082: 
                   82083:     function _tagCannotBeEmpty($tag)
                   82084:     {
                   82085:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   82086:             '<%tag%> cannot be empty (<%tag%/>)');
                   82087:     }
                   82088: 
                   82089:     function _UrlOrChannel($type, $name)
                   82090:     {
                   82091:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   82092:             'name' => $name),
                   82093:             'Required dependency <%type%> "%name%" can have either url OR ' .
                   82094:             'channel attributes, and not both');
                   82095:     }
                   82096: 
                   82097:     function _NoChannel($type, $name)
                   82098:     {
                   82099:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   82100:             'name' => $name),
                   82101:             'Required dependency <%type%> "%name%" must have either url OR ' .
                   82102:             'channel attributes');
                   82103:     }
                   82104: 
                   82105:     function _UrlOrChannelGroup($type, $name, $group)
                   82106:     {
                   82107:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   82108:             'name' => $name, 'group' => $group),
                   82109:             'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
                   82110:             'channel attributes, and not both');
                   82111:     }
                   82112: 
                   82113:     function _NoChannelGroup($type, $name, $group)
                   82114:     {
                   82115:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   82116:             'name' => $name, 'group' => $group),
                   82117:             'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
                   82118:             'channel attributes');
                   82119:     }
                   82120: 
                   82121:     function _unknownChannel($channel)
                   82122:     {
                   82123:         $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
                   82124:             'Unknown channel "%channel%"');
                   82125:     }
                   82126: 
                   82127:     function _noPackageVersion()
                   82128:     {
                   82129:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82130:             'package.xml <package> tag has no version attribute, or version is not 2.0');
                   82131:     }
                   82132: 
                   82133:     function _NoBundledPackages()
                   82134:     {
                   82135:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82136:             'No <bundledpackage> tag was found in <contents>, required for bundle packages');
                   82137:     }
                   82138: 
                   82139:     function _AtLeast2BundledPackages()
                   82140:     {
                   82141:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82142:             'At least 2 packages must be bundled in a bundle package');
                   82143:     }
                   82144: 
                   82145:     function _ChannelOrUri($name)
                   82146:     {
                   82147:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   82148:             'Bundled package "%name%" can have either a uri or a channel, not both');
                   82149:     }
                   82150: 
                   82151:     function _noChildTag($child, $tag)
                   82152:     {
                   82153:         $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
                   82154:             'Tag <%tag%> is missing child tag <%child%>');
                   82155:     }
                   82156: 
                   82157:     function _invalidVersion($type, $value)
                   82158:     {
                   82159:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
                   82160:             'Version type <%type%> is not a valid version (%value%)');
                   82161:     }
                   82162: 
                   82163:     function _invalidState($type, $value)
                   82164:     {
                   82165:         $states = array('stable', 'beta', 'alpha', 'devel');
                   82166:         if ($type != 'api') {
                   82167:             $states[] = 'snapshot';
                   82168:         }
                   82169:         if (strtolower($value) == 'rc') {
                   82170:             $this->_stack->push(__FUNCTION__, 'error',
                   82171:                 array('version' => $this->_packageInfo['version']['release']),
                   82172:                 'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
                   82173:         }
                   82174:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
                   82175:             'types' => $states),
                   82176:             'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
                   82177:             '%types%');
                   82178:     }
                   82179: 
                   82180:     function _invalidTask($task, $ret, $file)
                   82181:     {
                   82182:         switch ($ret[0]) {
                   82183:             case PEAR_TASK_ERROR_MISSING_ATTRIB :
                   82184:                 $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
                   82185:                 $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
                   82186:             break;
                   82187:             case PEAR_TASK_ERROR_NOATTRIBS :
                   82188:                 $info = array('task' => $task, 'file' => $file);
                   82189:                 $msg = 'task <%task%> has no attributes in file %file%';
                   82190:             break;
                   82191:             case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
                   82192:                 $info = array('attrib' => $ret[1], 'values' => $ret[3],
                   82193:                     'was' => $ret[2], 'task' => $task, 'file' => $file);
                   82194:                 $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
                   82195:                     'in file %file%, expecting one of "%values%"';
                   82196:             break;
                   82197:             case PEAR_TASK_ERROR_INVALID :
                   82198:                 $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
                   82199:                 $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
                   82200:             break;
                   82201:         }
                   82202:         $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
                   82203:     }
                   82204: 
                   82205:     function _unknownTask($task, $file)
                   82206:     {
                   82207:         $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
                   82208:             'Unknown task "%task%" passed in file <file name="%file%">');
                   82209:     }
                   82210: 
                   82211:     function _subpackageCannotProvideExtension($name)
                   82212:     {
                   82213:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   82214:             'Subpackage dependency "%name%" cannot use <providesextension>, ' .
                   82215:             'only package dependencies can use this tag');
                   82216:     }
                   82217: 
                   82218:     function _subpackagesCannotConflict($name)
                   82219:     {
                   82220:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   82221:             'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
                   82222:             'only package dependencies can use this tag');
                   82223:     }
                   82224: 
                   82225:     function _cannotProvideExtension($release)
                   82226:     {
                   82227:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   82228:             '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
                   82229:     }
                   82230: 
                   82231:     function _mustProvideExtension($release)
                   82232:     {
                   82233:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   82234:             '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
                   82235:     }
                   82236: 
                   82237:     function _cannotHaveSrcpackage($release)
                   82238:     {
                   82239:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   82240:             '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
                   82241:     }
                   82242: 
                   82243:     function _mustSrcPackage($release)
                   82244:     {
                   82245:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   82246:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
                   82247:     }
                   82248: 
                   82249:     function _mustSrcuri($release)
                   82250:     {
                   82251:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   82252:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
                   82253:     }
                   82254: 
                   82255:     function _uriDepsCannotHaveVersioning($type)
                   82256:     {
                   82257:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   82258:             '%type%: dependencies with a <uri> tag cannot have any versioning information');
                   82259:     }
                   82260: 
                   82261:     function _conflictingDepsCannotHaveVersioning($type)
                   82262:     {
                   82263:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   82264:             '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
                   82265:             'exclude specific versions of a dependency');
                   82266:     }
                   82267: 
                   82268:     function _DepchannelCannotBeUri($type)
                   82269:     {
                   82270:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   82271:             '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
                   82272:             'dependencies only');
                   82273:     }
                   82274: 
                   82275:     function _bundledPackagesMustBeFilename()
                   82276:     {
                   82277:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82278:             '<bundledpackage> tags must contain only the filename of a package release ' .
                   82279:             'in the bundle');
                   82280:     }
                   82281: 
                   82282:     function _binaryPackageMustBePackagename()
                   82283:     {
                   82284:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82285:             '<binarypackage> tags must contain the name of a package that is ' .
                   82286:             'a compiled version of this extsrc/zendextsrc package');
                   82287:     }
                   82288: 
                   82289:     function _fileNotFound($file)
                   82290:     {
                   82291:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   82292:             'File "%file%" in package.xml does not exist');
                   82293:     }
                   82294: 
                   82295:     function _notInContents($file, $tag)
                   82296:     {
                   82297:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
                   82298:             '<%tag% name="%file%"> is invalid, file is not in <contents>');
                   82299:     }
                   82300: 
                   82301:     function _cannotValidateNoPathSet()
                   82302:     {
                   82303:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82304:             'Cannot validate files, no path to package file is set (use setPackageFile())');
                   82305:     }
                   82306: 
                   82307:     function _usesroletaskMustHaveChannelOrUri($role, $tag)
                   82308:     {
                   82309:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   82310:             '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
                   82311:     }
                   82312: 
                   82313:     function _usesroletaskMustHavePackage($role, $tag)
                   82314:     {
                   82315:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   82316:             '<%tag%> for role "%role%" must contain <package>');
                   82317:     }
                   82318: 
                   82319:     function _usesroletaskMustHaveRoleTask($tag, $type)
                   82320:     {
                   82321:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
                   82322:             '<%tag%> must contain <%type%> defining the %type% to be used');
                   82323:     }
                   82324: 
                   82325:     function _cannotConflictWithAllOs($type)
                   82326:     {
                   82327:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   82328:             '%tag% cannot conflict with all OSes');
                   82329:     }
                   82330: 
                   82331:     function _invalidDepGroupName($name)
                   82332:     {
                   82333:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   82334:             'Invalid dependency group name "%name%"');
                   82335:     }
                   82336: 
                   82337:     function _multipleToplevelDirNotAllowed()
                   82338:     {
                   82339:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   82340:             'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
                   82341:                 'in a <dir name="/">');
                   82342:     }
                   82343: 
                   82344:     function _multipleInstallAs($file)
                   82345:     {
                   82346:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   82347:             'Only one <install> tag is allowed for file "%file%"');
                   82348:     }
                   82349: 
                   82350:     function _ignoreAndInstallAs($file)
                   82351:     {
                   82352:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   82353:             'Cannot have both <ignore> and <install> tags for file "%file%"');
                   82354:     }
                   82355: 
                   82356:     function _analyzeBundledPackages()
                   82357:     {
                   82358:         if (!$this->_isValid) {
                   82359:             return false;
                   82360:         }
                   82361:         if (!$this->_pf->getPackageType() == 'bundle') {
                   82362:             return false;
                   82363:         }
                   82364:         if (!isset($this->_pf->_packageFile)) {
                   82365:             return false;
                   82366:         }
                   82367:         $dir_prefix = dirname($this->_pf->_packageFile);
                   82368:         $common = new PEAR_Common;
                   82369:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   82370:             array($common, 'log');
                   82371:         $info = $this->_pf->getContents();
                   82372:         $info = $info['bundledpackage'];
                   82373:         if (!is_array($info)) {
                   82374:             $info = array($info);
                   82375:         }
                   82376:         $pkg = &new PEAR_PackageFile($this->_pf->_config);
                   82377:         foreach ($info as $package) {
                   82378:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
                   82379:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
                   82380:                 $this->_isValid = 0;
                   82381:                 continue;
                   82382:             }
                   82383:             call_user_func_array($log, array(1, "Analyzing bundled package $package"));
                   82384:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   82385:             $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
                   82386:                 PEAR_VALIDATE_NORMAL);
                   82387:             PEAR::popErrorHandling();
                   82388:             if (PEAR::isError($ret)) {
                   82389:                 call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
                   82390:                     'package'));
                   82391:                 $inf = $ret->getUserInfo();
                   82392:                 if (is_array($inf)) {
                   82393:                     foreach ($inf as $err) {
                   82394:                         call_user_func_array($log, array(1, $err['message']));
                   82395:                     }
                   82396:                 }
                   82397:                 return false;
                   82398:             }
                   82399:         }
                   82400:         return true;
                   82401:     }
                   82402: 
                   82403:     function _analyzePhpFiles()
                   82404:     {
                   82405:         if (!$this->_isValid) {
                   82406:             return false;
                   82407:         }
                   82408:         if (!isset($this->_pf->_packageFile)) {
                   82409:             $this->_cannotValidateNoPathSet();
                   82410:             return false;
                   82411:         }
                   82412:         $dir_prefix = dirname($this->_pf->_packageFile);
                   82413:         $common = new PEAR_Common;
                   82414:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   82415:             array(&$common, 'log');
                   82416:         $info = $this->_pf->getContents();
                   82417:         if (!$info || !isset($info['dir']['file'])) {
                   82418:             $this->_tagCannotBeEmpty('contents><dir');
                   82419:             return false;
                   82420:         }
                   82421:         $info = $info['dir']['file'];
                   82422:         if (isset($info['attribs'])) {
                   82423:             $info = array($info);
                   82424:         }
                   82425:         $provides = array();
                   82426:         foreach ($info as $fa) {
                   82427:             $fa = $fa['attribs'];
                   82428:             $file = $fa['name'];
                   82429:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   82430:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   82431:                 $this->_isValid = 0;
                   82432:                 continue;
                   82433:             }
                   82434:             if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
                   82435:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   82436:                 $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   82437:                 if ($srcinfo) {
                   82438:                     $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
                   82439:                 }
                   82440:             }
                   82441:         }
                   82442:         $this->_packageName = $pn = $this->_pf->getPackage();
                   82443:         $pnl = strlen($pn);
                   82444:         foreach ($provides as $key => $what) {
                   82445:             if (isset($what['explicit']) || !$what) {
                   82446:                 // skip conformance checks if the provides entry is
                   82447:                 // specified in the package.xml file
                   82448:                 continue;
                   82449:             }
                   82450:             extract($what);
                   82451:             if ($type == 'class') {
                   82452:                 if (!strncasecmp($name, $pn, $pnl)) {
                   82453:                     continue;
                   82454:                 }
                   82455:                 $this->_stack->push(__FUNCTION__, 'warning',
                   82456:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   82457:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   82458:             } elseif ($type == 'function') {
                   82459:                 if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   82460:                     continue;
                   82461:                 }
                   82462:                 $this->_stack->push(__FUNCTION__, 'warning',
                   82463:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   82464:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   82465:             }
                   82466:         }
                   82467:         return $this->_isValid;
                   82468:     }
                   82469: 
                   82470:     /**
                   82471:      * Analyze the source code of the given PHP file
                   82472:      *
                   82473:      * @param  string Filename of the PHP file
                   82474:      * @param  boolean whether to analyze $file as the file contents
                   82475:      * @return mixed
                   82476:      */
                   82477:     function analyzeSourceCode($file, $string = false)
                   82478:     {
                   82479:         if (!function_exists("token_get_all")) {
                   82480:             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   82481:                 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
                   82482:             return false;
                   82483:         }
                   82484: 
                   82485:         if (!defined('T_DOC_COMMENT')) {
                   82486:             define('T_DOC_COMMENT', T_COMMENT);
                   82487:         }
                   82488: 
                   82489:         if (!defined('T_INTERFACE')) {
                   82490:             define('T_INTERFACE', -1);
                   82491:         }
                   82492: 
                   82493:         if (!defined('T_IMPLEMENTS')) {
                   82494:             define('T_IMPLEMENTS', -1);
                   82495:         }
                   82496: 
                   82497:         if ($string) {
                   82498:             $contents = $file;
                   82499:         } else {
                   82500:             if (!$fp = @fopen($file, "r")) {
                   82501:                 return false;
                   82502:             }
                   82503:             fclose($fp);
                   82504:             $contents = file_get_contents($file);
                   82505:         }
                   82506: 
                   82507:         // Silence this function so we can catch PHP Warnings and show our own custom message
                   82508:         $tokens = @token_get_all($contents);
                   82509:         if (isset($php_errormsg)) {
                   82510:             if (isset($this->_stack)) {
                   82511:                 $pn = $this->_pf->getPackage();
                   82512:                 $this->_stack->push(__FUNCTION__, 'warning',
                   82513:                         array('file' => $file, 'package' => $pn),
                   82514:                         'in %file%: Could not process file for unkown reasons,' .
                   82515:                         ' possibly a PHP parse error in %file% from %package%');
                   82516:             }
                   82517:         }
                   82518: /*
                   82519:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   82520:             @list($token, $data) = $tokens[$i];
                   82521:             if (is_string($token)) {
                   82522:                 var_dump($token);
                   82523:             } else {
                   82524:                 print token_name($token) . ' ';
                   82525:                 var_dump(rtrim($data));
                   82526:             }
                   82527:         }
                   82528: */
                   82529:         $look_for = 0;
                   82530:         $paren_level = 0;
                   82531:         $bracket_level = 0;
                   82532:         $brace_level = 0;
                   82533:         $lastphpdoc = '';
                   82534:         $current_class = '';
                   82535:         $current_interface = '';
                   82536:         $current_class_level = -1;
                   82537:         $current_function = '';
                   82538:         $current_function_level = -1;
                   82539:         $declared_classes = array();
                   82540:         $declared_interfaces = array();
                   82541:         $declared_functions = array();
                   82542:         $declared_methods = array();
                   82543:         $used_classes = array();
                   82544:         $used_functions = array();
                   82545:         $extends = array();
                   82546:         $implements = array();
                   82547:         $nodeps = array();
                   82548:         $inquote = false;
                   82549:         $interface = false;
                   82550:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   82551:             if (is_array($tokens[$i])) {
                   82552:                 list($token, $data) = $tokens[$i];
                   82553:             } else {
                   82554:                 $token = $tokens[$i];
                   82555:                 $data = '';
                   82556:             }
                   82557: 
                   82558:             if ($inquote) {
                   82559:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   82560:                     continue;
                   82561:                 } else {
                   82562:                     $inquote = false;
                   82563:                     continue;
                   82564:                 }
                   82565:             }
                   82566: 
                   82567:             switch ($token) {
                   82568:                 case T_WHITESPACE :
                   82569:                     continue;
                   82570:                 case ';':
                   82571:                     if ($interface) {
                   82572:                         $current_function = '';
                   82573:                         $current_function_level = -1;
                   82574:                     }
                   82575:                     break;
                   82576:                 case '"':
                   82577:                 case T_START_HEREDOC:
                   82578:                     $inquote = true;
                   82579:                     break;
                   82580:                 case T_CURLY_OPEN:
                   82581:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   82582:                 case '{': $brace_level++; continue 2;
                   82583:                 case '}':
                   82584:                     $brace_level--;
                   82585:                     if ($current_class_level == $brace_level) {
                   82586:                         $current_class = '';
                   82587:                         $current_class_level = -1;
                   82588:                     }
                   82589:                     if ($current_function_level == $brace_level) {
                   82590:                         $current_function = '';
                   82591:                         $current_function_level = -1;
                   82592:                     }
                   82593:                     continue 2;
                   82594:                 case '[': $bracket_level++; continue 2;
                   82595:                 case ']': $bracket_level--; continue 2;
                   82596:                 case '(': $paren_level++;   continue 2;
                   82597:                 case ')': $paren_level--;   continue 2;
                   82598:                 case T_INTERFACE:
                   82599:                     $interface = true;
                   82600:                 case T_CLASS:
                   82601:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   82602:                         if (isset($this->_stack)) {
                   82603:                             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   82604:                             'Parser error: invalid PHP found in file "%file%"');
                   82605:                         } else {
                   82606:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   82607:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   82608:                         }
                   82609: 
                   82610:                         return false;
                   82611:                     }
                   82612:                 case T_FUNCTION:
                   82613:                 case T_NEW:
                   82614:                 case T_EXTENDS:
                   82615:                 case T_IMPLEMENTS:
                   82616:                     $look_for = $token;
                   82617:                     continue 2;
                   82618:                 case T_STRING:
                   82619:                     if (version_compare(zend_version(), '2.0', '<')) {
                   82620:                         if (in_array(strtolower($data),
                   82621:                             array('public', 'private', 'protected', 'abstract',
                   82622:                                   'interface', 'implements', 'throw')
                   82623:                                  )
                   82624:                         ) {
                   82625:                             if (isset($this->_stack)) {
                   82626:                                 $this->_stack->push(__FUNCTION__, 'warning', array(
                   82627:                                     'file' => $file),
                   82628:                                     'Error, PHP5 token encountered in %file%,' .
                   82629:                                     ' analysis should be in PHP5');
                   82630:                             } else {
                   82631:                                 PEAR::raiseError('Error: PHP5 token encountered in ' . $file .
                   82632:                                     'packaging should be done in PHP 5');
                   82633:                                 return false;
                   82634:                             }
                   82635:                         }
                   82636:                     }
                   82637: 
                   82638:                     if ($look_for == T_CLASS) {
                   82639:                         $current_class = $data;
                   82640:                         $current_class_level = $brace_level;
                   82641:                         $declared_classes[] = $current_class;
                   82642:                     } elseif ($look_for == T_INTERFACE) {
                   82643:                         $current_interface = $data;
                   82644:                         $current_class_level = $brace_level;
                   82645:                         $declared_interfaces[] = $current_interface;
                   82646:                     } elseif ($look_for == T_IMPLEMENTS) {
                   82647:                         $implements[$current_class] = $data;
                   82648:                     } elseif ($look_for == T_EXTENDS) {
                   82649:                         $extends[$current_class] = $data;
                   82650:                     } elseif ($look_for == T_FUNCTION) {
                   82651:                         if ($current_class) {
                   82652:                             $current_function = "$current_class::$data";
                   82653:                             $declared_methods[$current_class][] = $data;
                   82654:                         } elseif ($current_interface) {
                   82655:                             $current_function = "$current_interface::$data";
                   82656:                             $declared_methods[$current_interface][] = $data;
                   82657:                         } else {
                   82658:                             $current_function = $data;
                   82659:                             $declared_functions[] = $current_function;
                   82660:                         }
                   82661: 
                   82662:                         $current_function_level = $brace_level;
                   82663:                         $m = array();
                   82664:                     } elseif ($look_for == T_NEW) {
                   82665:                         $used_classes[$data] = true;
                   82666:                     }
                   82667: 
                   82668:                     $look_for = 0;
                   82669:                     continue 2;
                   82670:                 case T_VARIABLE:
                   82671:                     $look_for = 0;
                   82672:                     continue 2;
                   82673:                 case T_DOC_COMMENT:
                   82674:                 case T_COMMENT:
                   82675:                     if (preg_match('!^/\*\*\s!', $data)) {
                   82676:                         $lastphpdoc = $data;
                   82677:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   82678:                             $nodeps = array_merge($nodeps, $m[1]);
                   82679:                         }
                   82680:                     }
                   82681:                     continue 2;
                   82682:                 case T_DOUBLE_COLON:
                   82683:                     $token = $tokens[$i - 1][0];
                   82684:                     if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC)) {
                   82685:                         if (isset($this->_stack)) {
                   82686:                             $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
                   82687:                                 'Parser error: invalid PHP found in file "%file%"');
                   82688:                         } else {
                   82689:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   82690:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   82691:                         }
                   82692: 
                   82693:                         return false;
                   82694:                     }
                   82695: 
                   82696:                     $class = $tokens[$i - 1][1];
                   82697:                     if (strtolower($class) != 'parent') {
                   82698:                         $used_classes[$class] = true;
                   82699:                     }
                   82700: 
                   82701:                     continue 2;
                   82702:             }
                   82703:         }
                   82704: 
                   82705:         return array(
                   82706:             "source_file" => $file,
                   82707:             "declared_classes" => $declared_classes,
                   82708:             "declared_interfaces" => $declared_interfaces,
                   82709:             "declared_methods" => $declared_methods,
                   82710:             "declared_functions" => $declared_functions,
                   82711:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   82712:             "inheritance" => $extends,
                   82713:             "implements" => $implements,
                   82714:         );
                   82715:     }
                   82716: 
                   82717:     /**
                   82718:      * Build a "provides" array from data returned by
                   82719:      * analyzeSourceCode().  The format of the built array is like
                   82720:      * this:
                   82721:      *
                   82722:      *  array(
                   82723:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   82724:      *    ...
                   82725:      *  )
                   82726:      *
                   82727:      *
                   82728:      * @param array $srcinfo array with information about a source file
                   82729:      * as returned by the analyzeSourceCode() method.
                   82730:      *
                   82731:      * @return void
                   82732:      *
                   82733:      * @access private
                   82734:      *
                   82735:      */
                   82736:     function _buildProvidesArray($srcinfo)
                   82737:     {
                   82738:         if (!$this->_isValid) {
                   82739:             return array();
                   82740:         }
                   82741: 
                   82742:         $providesret = array();
                   82743:         $file        = basename($srcinfo['source_file']);
                   82744:         $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
                   82745:         $pnl         = strlen($pn);
                   82746:         foreach ($srcinfo['declared_classes'] as $class) {
                   82747:             $key = "class;$class";
                   82748:             if (isset($providesret[$key])) {
                   82749:                 continue;
                   82750:             }
                   82751: 
                   82752:             $providesret[$key] =
                   82753:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   82754:             if (isset($srcinfo['inheritance'][$class])) {
                   82755:                 $providesret[$key]['extends'] =
                   82756:                     $srcinfo['inheritance'][$class];
                   82757:             }
                   82758:         }
                   82759: 
                   82760:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   82761:             foreach ($methods as $method) {
                   82762:                 $function = "$class::$method";
                   82763:                 $key = "function;$function";
                   82764:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   82765:                     isset($providesret[$key])) {
                   82766:                     continue;
                   82767:                 }
                   82768: 
                   82769:                 $providesret[$key] =
                   82770:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   82771:             }
                   82772:         }
                   82773: 
                   82774:         foreach ($srcinfo['declared_functions'] as $function) {
                   82775:             $key = "function;$function";
                   82776:             if ($function{0} == '_' || isset($providesret[$key])) {
                   82777:                 continue;
                   82778:             }
                   82779: 
                   82780:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   82781:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   82782:             }
                   82783: 
                   82784:             $providesret[$key] =
                   82785:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   82786:         }
                   82787: 
                   82788:         return $providesret;
                   82789:     }
                   82790: }<?php
                   82791: /**
                   82792:  * PEAR_Registry
                   82793:  *
                   82794:  * PHP versions 4 and 5
                   82795:  *
                   82796:  * @category   pear
                   82797:  * @package    PEAR
                   82798:  * @author     Stig Bakken <ssb@php.net>
                   82799:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   82800:  * @author     Greg Beaver <cellog@php.net>
                   82801:  * @copyright  1997-2009 The Authors
                   82802:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   82803:  * @version    CVS: $Id: Registry.php 287555 2009-08-21 21:27:27Z dufuz $
                   82804:  * @link       http://pear.php.net/package/PEAR
                   82805:  * @since      File available since Release 0.1
                   82806:  */
                   82807: 
                   82808: /**
                   82809:  * for PEAR_Error
                   82810:  */
                   82811: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   82812: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/DependencyDB.php';
                   82813: 
                   82814: define('PEAR_REGISTRY_ERROR_LOCK',         -2);
                   82815: define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
                   82816: define('PEAR_REGISTRY_ERROR_FILE',         -4);
                   82817: define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
                   82818: define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
                   82819: 
                   82820: /**
                   82821:  * Administration class used to maintain the installed package database.
                   82822:  * @category   pear
                   82823:  * @package    PEAR
                   82824:  * @author     Stig Bakken <ssb@php.net>
                   82825:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   82826:  * @author     Greg Beaver <cellog@php.net>
                   82827:  * @copyright  1997-2009 The Authors
                   82828:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   82829:  * @version    Release: 1.10.0beta1
                   82830:  * @link       http://pear.php.net/package/PEAR
                   82831:  * @since      Class available since Release 1.4.0a1
                   82832:  */
                   82833: class PEAR_Registry extends PEAR
                   82834: {
                   82835:     /**
                   82836:      * File containing all channel information.
                   82837:      * @var string
                   82838:      */
                   82839:     var $channels = '';
                   82840: 
                   82841:     /** Directory where registry files are stored.
                   82842:      * @var string
                   82843:      */
                   82844:     var $statedir = '';
                   82845: 
                   82846:     /** File where the file map is stored
                   82847:      * @var string
                   82848:      */
                   82849:     var $filemap = '';
                   82850: 
                   82851:     /** Directory where registry files for channels are stored.
                   82852:      * @var string
                   82853:      */
                   82854:     var $channelsdir = '';
                   82855: 
                   82856:     /** Name of file used for locking the registry
                   82857:      * @var string
                   82858:      */
                   82859:     var $lockfile = '';
                   82860: 
                   82861:     /** File descriptor used during locking
                   82862:      * @var resource
                   82863:      */
                   82864:     var $lock_fp = null;
                   82865: 
                   82866:     /** Mode used during locking
                   82867:      * @var int
                   82868:      */
                   82869:     var $lock_mode = 0; // XXX UNUSED
                   82870: 
                   82871:     /** Cache of package information.  Structure:
                   82872:      * array(
                   82873:      *   'package' => array('id' => ... ),
                   82874:      *   ... )
                   82875:      * @var array
                   82876:      */
                   82877:     var $pkginfo_cache = array();
                   82878: 
                   82879:     /** Cache of file map.  Structure:
                   82880:      * array( '/path/to/file' => 'package', ... )
                   82881:      * @var array
                   82882:      */
                   82883:     var $filemap_cache = array();
                   82884: 
                   82885:     /**
                   82886:      * @var false|PEAR_ChannelFile
                   82887:      */
                   82888:     var $_pearChannel;
                   82889: 
                   82890:     /**
                   82891:      * @var false|PEAR_ChannelFile
                   82892:      */
                   82893:     var $_peclChannel;
                   82894: 
                   82895:     /**
                   82896:      * @var false|PEAR_ChannelFile
                   82897:      */
                   82898:     var $_docChannel;
                   82899: 
                   82900:     /**
                   82901:      * @var PEAR_DependencyDB
                   82902:      */
                   82903:     var $_dependencyDB;
                   82904: 
                   82905:     /**
                   82906:      * @var PEAR_Config
                   82907:      */
                   82908:     var $_config;
                   82909: 
                   82910:     /**
                   82911:      * PEAR_Registry constructor.
                   82912:      *
                   82913:      * @param string (optional) PEAR install directory (for .php files)
                   82914:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
                   82915:      *        default values are not desired.  Only used the very first time a PEAR
                   82916:      *        repository is initialized
                   82917:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
                   82918:      *        default values are not desired.  Only used the very first time a PEAR
                   82919:      *        repository is initialized
                   82920:      *
                   82921:      * @access public
                   82922:      */
                   82923:     function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
                   82924:                            $pecl_channel = false)
                   82925:     {
                   82926:         parent::PEAR();
                   82927:         $this->setInstallDir($pear_install_dir);
                   82928:         $this->_pearChannel = $pear_channel;
                   82929:         $this->_peclChannel = $pecl_channel;
                   82930:         $this->_config      = false;
                   82931:     }
                   82932: 
                   82933:     function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR)
                   82934:     {
                   82935:         $ds = DIRECTORY_SEPARATOR;
                   82936:         $this->install_dir = $pear_install_dir;
                   82937:         $this->channelsdir = $pear_install_dir.$ds.'.channels';
                   82938:         $this->statedir    = $pear_install_dir.$ds.'.registry';
                   82939:         $this->filemap     = $pear_install_dir.$ds.'.filemap';
                   82940:         $this->lockfile    = $pear_install_dir.$ds.'.lock';
                   82941:     }
                   82942: 
                   82943:     function hasWriteAccess()
                   82944:     {
                   82945:         if (!file_exists($this->install_dir)) {
                   82946:             $dir = $this->install_dir;
                   82947:             while ($dir && $dir != '.') {
                   82948:                 $olddir = $dir;
                   82949:                 $dir    = dirname($dir);
                   82950:                 if ($dir != '.' && file_exists($dir)) {
                   82951:                     if (is_writeable($dir)) {
                   82952:                         return true;
                   82953:                     }
                   82954: 
                   82955:                     return false;
                   82956:                 }
                   82957: 
                   82958:                 if ($dir == $olddir) { // this can happen in safe mode
                   82959:                     return @is_writable($dir);
                   82960:                 }
                   82961:             }
                   82962: 
                   82963:             return false;
                   82964:         }
                   82965: 
                   82966:         return is_writeable($this->install_dir);
                   82967:     }
                   82968: 
                   82969:     function setConfig(&$config, $resetInstallDir = true)
                   82970:     {
                   82971:         $this->_config = &$config;
                   82972:         if ($resetInstallDir) {
                   82973:             $this->setInstallDir($config->get('php_dir'));
                   82974:         }
                   82975:     }
                   82976: 
                   82977:     function _initializeChannelDirs()
                   82978:     {
                   82979:         static $running = false;
                   82980:         if (!$running) {
                   82981:             $running = true;
                   82982:             $ds = DIRECTORY_SEPARATOR;
                   82983:             if (!is_dir($this->channelsdir) ||
                   82984:                   !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   82985:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   82986:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   82987:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   82988:                 if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   82989:                     $pear_channel = $this->_pearChannel;
                   82990:                     if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
                   82991:                         if (!class_exists('PEAR_ChannelFile')) {
                   82992:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   82993:                         }
                   82994: 
                   82995:                         $pear_channel = new PEAR_ChannelFile;
                   82996:                         $pear_channel->setAlias('pear');
                   82997:                         $pear_channel->setServer('pear.php.net');
                   82998:                         $pear_channel->setSummary('PHP Extension and Application Repository');
                   82999:                         $pear_channel->setDefaultPEARProtocols();
                   83000:                         $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   83001:                         $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   83002:                         $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   83003:                         //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
                   83004:                     } else {
                   83005:                         $pear_channel->setServer('pear.php.net');
                   83006:                         $pear_channel->setAlias('pear');
                   83007:                     }
                   83008: 
                   83009:                     $pear_channel->validate();
                   83010:                     $this->_addChannel($pear_channel);
                   83011:                 }
                   83012: 
                   83013:                 if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
                   83014:                     $pecl_channel = $this->_peclChannel;
                   83015:                     if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
                   83016:                         if (!class_exists('PEAR_ChannelFile')) {
                   83017:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   83018:                         }
                   83019: 
                   83020:                         $pecl_channel = new PEAR_ChannelFile;
                   83021:                         $pecl_channel->setAlias('pecl');
                   83022:                         $pecl_channel->setServer('pecl.php.net');
                   83023:                         $pecl_channel->setSummary('PHP Extension Community Library');
                   83024:                         $pecl_channel->setDefaultPEARProtocols();
                   83025:                         $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   83026:                         $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   83027:                         $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   83028:                     } else {
                   83029:                         $pecl_channel->setServer('pecl.php.net');
                   83030:                         $pecl_channel->setAlias('pecl');
                   83031:                     }
                   83032: 
                   83033:                     $pecl_channel->validate();
                   83034:                     $this->_addChannel($pecl_channel);
                   83035:                 }
                   83036: 
                   83037:                 if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
                   83038:                     $doc_channel = $this->_docChannel;
                   83039:                     if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
                   83040:                         if (!class_exists('PEAR_ChannelFile')) {
                   83041:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   83042:                         }
                   83043: 
                   83044:                         $doc_channel = new PEAR_ChannelFile;
                   83045:                         $doc_channel->setAlias('phpdocs');
                   83046:                         $doc_channel->setServer('doc.php.net');
                   83047:                         $doc_channel->setSummary('PHP Documentation Team');
                   83048:                         $doc_channel->setDefaultPEARProtocols();
                   83049:                         $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   83050:                         $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   83051:                         $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   83052:                     } else {
                   83053:                         $doc_channel->setServer('doc.php.net');
                   83054:                         $doc_channel->setAlias('doc');
                   83055:                     }
                   83056: 
                   83057:                     $doc_channel->validate();
                   83058:                     $this->_addChannel($doc_channel);
                   83059:                 }
                   83060: 
                   83061:                 if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   83062:                     if (!class_exists('PEAR_ChannelFile')) {
                   83063:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   83064:                     }
                   83065: 
                   83066:                     $private = new PEAR_ChannelFile;
                   83067:                     $private->setName('__uri');
                   83068:                     $private->setDefaultPEARProtocols();
                   83069:                     $private->setBaseURL('REST1.0', '****');
                   83070:                     $private->setSummary('Pseudo-channel for static packages');
                   83071:                     $this->_addChannel($private);
                   83072:                 }
                   83073:                 $this->_rebuildFileMap();
                   83074:             }
                   83075: 
                   83076:             $running = false;
                   83077:         }
                   83078:     }
                   83079: 
                   83080:     function _initializeDirs()
                   83081:     {
                   83082:         $ds = DIRECTORY_SEPARATOR;
                   83083:         // XXX Compatibility code should be removed in the future
                   83084:         // rename all registry files if any to lowercase
                   83085:         if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
                   83086:               $handle = opendir($this->statedir)) {
                   83087:             $dest = $this->statedir . $ds;
                   83088:             while (false !== ($file = readdir($handle))) {
                   83089:                 if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
                   83090:                     rename($dest . $file, $dest . strtolower($file));
                   83091:                 }
                   83092:             }
                   83093:             closedir($handle);
                   83094:         }
                   83095: 
                   83096:         $this->_initializeChannelDirs();
                   83097:         if (!file_exists($this->filemap)) {
                   83098:             $this->_rebuildFileMap();
                   83099:         }
                   83100:         $this->_initializeDepDB();
                   83101:     }
                   83102: 
                   83103:     function _initializeDepDB()
                   83104:     {
                   83105:         if (!isset($this->_dependencyDB)) {
                   83106:             static $initializing = false;
                   83107:             if (!$initializing) {
                   83108:                 $initializing = true;
                   83109:                 if (!$this->_config) { // never used?
                   83110:                     $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
                   83111:                     $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
                   83112:                         $file);
                   83113:                     $this->_config->setRegistry($this);
                   83114:                     $this->_config->set('php_dir', $this->install_dir);
                   83115:                 }
                   83116: 
                   83117:                 $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   83118:                 if (PEAR::isError($this->_dependencyDB)) {
                   83119:                     // attempt to recover by removing the dep db
                   83120:                     if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
                   83121:                         DIRECTORY_SEPARATOR . '.depdb')) {
                   83122:                         @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
                   83123:                             DIRECTORY_SEPARATOR . '.depdb');
                   83124:                     }
                   83125: 
                   83126:                     $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   83127:                     if (PEAR::isError($this->_dependencyDB)) {
                   83128:                         echo $this->_dependencyDB->getMessage();
                   83129:                         echo 'Unrecoverable error';
                   83130:                         exit(1);
                   83131:                     }
                   83132:                 }
                   83133: 
                   83134:                 $initializing = false;
                   83135:             }
                   83136:         }
                   83137:     }
                   83138: 
                   83139:     /**
                   83140:      * PEAR_Registry destructor.  Makes sure no locks are forgotten.
                   83141:      *
                   83142:      * @access private
                   83143:      */
                   83144:     function _PEAR_Registry()
                   83145:     {
                   83146:         parent::_PEAR();
                   83147:         if (is_resource($this->lock_fp)) {
                   83148:             $this->_unlock();
                   83149:         }
                   83150:     }
                   83151: 
                   83152:     /**
                   83153:      * Make sure the directory where we keep registry files exists.
                   83154:      *
                   83155:      * @return bool TRUE if directory exists, FALSE if it could not be
                   83156:      * created
                   83157:      *
                   83158:      * @access private
                   83159:      */
                   83160:     function _assertStateDir($channel = false)
                   83161:     {
                   83162:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   83163:             return $this->_assertChannelStateDir($channel);
                   83164:         }
                   83165: 
                   83166:         static $init = false;
                   83167:         if (!file_exists($this->statedir)) {
                   83168:             if (!$this->hasWriteAccess()) {
                   83169:                 return false;
                   83170:             }
                   83171: 
                   83172:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   83173:             if (!System::mkdir(array('-p', $this->statedir))) {
                   83174:                 return $this->raiseError("could not create directory '{$this->statedir}'");
                   83175:             }
                   83176:             $init = true;
                   83177:         } elseif (!is_dir($this->statedir)) {
                   83178:             return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
                   83179:                 'it already exists and is not a directory');
                   83180:         }
                   83181: 
                   83182:         $ds = DIRECTORY_SEPARATOR;
                   83183:         if (!file_exists($this->channelsdir)) {
                   83184:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   83185:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   83186:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   83187:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   83188:                 $init = true;
                   83189:             }
                   83190:         } elseif (!is_dir($this->channelsdir)) {
                   83191:             return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
                   83192:                 'it already exists and is not a directory');
                   83193:         }
                   83194: 
                   83195:         if ($init) {
                   83196:             static $running = false;
                   83197:             if (!$running) {
                   83198:                 $running = true;
                   83199:                 $this->_initializeDirs();
                   83200:                 $running = false;
                   83201:                 $init = false;
                   83202:             }
                   83203:         } else {
                   83204:             $this->_initializeDepDB();
                   83205:         }
                   83206: 
                   83207:         return true;
                   83208:     }
                   83209: 
                   83210:     /**
                   83211:      * Make sure the directory where we keep registry files exists for a non-standard channel.
                   83212:      *
                   83213:      * @param string channel name
                   83214:      * @return bool TRUE if directory exists, FALSE if it could not be
                   83215:      * created
                   83216:      *
                   83217:      * @access private
                   83218:      */
                   83219:     function _assertChannelStateDir($channel)
                   83220:     {
                   83221:         $ds = DIRECTORY_SEPARATOR;
                   83222:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   83223:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   83224:                 $this->_initializeChannelDirs();
                   83225:             }
                   83226:             return $this->_assertStateDir($channel);
                   83227:         }
                   83228: 
                   83229:         $channelDir = $this->_channelDirectoryName($channel);
                   83230:         if (!is_dir($this->channelsdir) ||
                   83231:               !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   83232:             $this->_initializeChannelDirs();
                   83233:         }
                   83234: 
                   83235:         if (!file_exists($channelDir)) {
                   83236:             if (!$this->hasWriteAccess()) {
                   83237:                 return false;
                   83238:             }
                   83239: 
                   83240:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   83241:             if (!System::mkdir(array('-p', $channelDir))) {
                   83242:                 return $this->raiseError("could not create directory '" . $channelDir .
                   83243:                     "'");
                   83244:             }
                   83245:         } elseif (!is_dir($channelDir)) {
                   83246:             return $this->raiseError("could not create directory '" . $channelDir .
                   83247:                 "', already exists and is not a directory");
                   83248:         }
                   83249: 
                   83250:         return true;
                   83251:     }
                   83252: 
                   83253:     /**
                   83254:      * Make sure the directory where we keep registry files for channels exists
                   83255:      *
                   83256:      * @return bool TRUE if directory exists, FALSE if it could not be
                   83257:      * created
                   83258:      *
                   83259:      * @access private
                   83260:      */
                   83261:     function _assertChannelDir()
                   83262:     {
                   83263:         if (!file_exists($this->channelsdir)) {
                   83264:             if (!$this->hasWriteAccess()) {
                   83265:                 return false;
                   83266:             }
                   83267: 
                   83268:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   83269:             if (!System::mkdir(array('-p', $this->channelsdir))) {
                   83270:                 return $this->raiseError("could not create directory '{$this->channelsdir}'");
                   83271:             }
                   83272:         } elseif (!is_dir($this->channelsdir)) {
                   83273:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   83274:                 "', it already exists and is not a directory");
                   83275:         }
                   83276: 
                   83277:         if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   83278:             if (!$this->hasWriteAccess()) {
                   83279:                 return false;
                   83280:             }
                   83281: 
                   83282:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   83283:             if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
                   83284:                 return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
                   83285:             }
                   83286:         } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   83287:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   83288:                 "/.alias', it already exists and is not a directory");
                   83289:         }
                   83290: 
                   83291:         return true;
                   83292:     }
                   83293: 
                   83294:     /**
                   83295:      * Get the name of the file where data for a given package is stored.
                   83296:      *
                   83297:      * @param string channel name, or false if this is a PEAR package
                   83298:      * @param string package name
                   83299:      *
                   83300:      * @return string registry file name
                   83301:      *
                   83302:      * @access public
                   83303:      */
                   83304:     function _packageFileName($package, $channel = false)
                   83305:     {
                   83306:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   83307:             return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
                   83308:                 strtolower($package) . '.reg';
                   83309:         }
                   83310: 
                   83311:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
                   83312:     }
                   83313: 
                   83314:     /**
                   83315:      * Get the name of the file where data for a given channel is stored.
                   83316:      * @param string channel name
                   83317:      * @return string registry file name
                   83318:      */
                   83319:     function _channelFileName($channel, $noaliases = false)
                   83320:     {
                   83321:         if (!$noaliases) {
                   83322:             if (file_exists($this->_getChannelAliasFileName($channel))) {
                   83323:                 $channel = implode('', file($this->_getChannelAliasFileName($channel)));
                   83324:             }
                   83325:         }
                   83326:         return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
                   83327:             strtolower($channel)) . '.reg';
                   83328:     }
                   83329: 
                   83330:     /**
                   83331:      * @param string
                   83332:      * @return string
                   83333:      */
                   83334:     function _getChannelAliasFileName($alias)
                   83335:     {
                   83336:         return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
                   83337:               DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
                   83338:     }
                   83339: 
                   83340:     /**
                   83341:      * Get the name of a channel from its alias
                   83342:      */
                   83343:     function _getChannelFromAlias($channel)
                   83344:     {
                   83345:         if (!$this->_channelExists($channel)) {
                   83346:             if ($channel == 'pear.php.net') {
                   83347:                 return 'pear.php.net';
                   83348:             }
                   83349: 
                   83350:             if ($channel == 'pecl.php.net') {
                   83351:                 return 'pecl.php.net';
                   83352:             }
                   83353: 
                   83354:             if ($channel == 'doc.php.net') {
                   83355:                 return 'doc.php.net';
                   83356:             }
                   83357: 
                   83358:             if ($channel == '__uri') {
                   83359:                 return '__uri';
                   83360:             }
                   83361: 
                   83362:             return false;
                   83363:         }
                   83364: 
                   83365:         $channel = strtolower($channel);
                   83366:         if (file_exists($this->_getChannelAliasFileName($channel))) {
                   83367:             // translate an alias to an actual channel
                   83368:             return implode('', file($this->_getChannelAliasFileName($channel)));
                   83369:         }
                   83370: 
                   83371:         return $channel;
                   83372:     }
                   83373: 
                   83374:     /**
                   83375:      * Get the alias of a channel from its alias or its name
                   83376:      */
                   83377:     function _getAlias($channel)
                   83378:     {
                   83379:         if (!$this->_channelExists($channel)) {
                   83380:             if ($channel == 'pear.php.net') {
                   83381:                 return 'pear';
                   83382:             }
                   83383: 
                   83384:             if ($channel == 'pecl.php.net') {
                   83385:                 return 'pecl';
                   83386:             }
                   83387: 
                   83388:             if ($channel == 'doc.php.net') {
                   83389:                 return 'phpdocs';
                   83390:             }
                   83391: 
                   83392:             return false;
                   83393:         }
                   83394: 
                   83395:         $channel = $this->_getChannel($channel);
                   83396:         if (PEAR::isError($channel)) {
                   83397:             return $channel;
                   83398:         }
                   83399: 
                   83400:         return $channel->getAlias();
                   83401:     }
                   83402: 
                   83403:     /**
                   83404:      * Get the name of the file where data for a given package is stored.
                   83405:      *
                   83406:      * @param string channel name, or false if this is a PEAR package
                   83407:      * @param string package name
                   83408:      *
                   83409:      * @return string registry file name
                   83410:      *
                   83411:      * @access public
                   83412:      */
                   83413:     function _channelDirectoryName($channel)
                   83414:     {
                   83415:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   83416:             return $this->statedir;
                   83417:         }
                   83418: 
                   83419:         $ch = $this->_getChannelFromAlias($channel);
                   83420:         if (!$ch) {
                   83421:             $ch = $channel;
                   83422:         }
                   83423: 
                   83424:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
                   83425:             str_replace('/', '_', $ch));
                   83426:     }
                   83427: 
                   83428:     function _openPackageFile($package, $mode, $channel = false)
                   83429:     {
                   83430:         if (!$this->_assertStateDir($channel)) {
                   83431:             return null;
                   83432:         }
                   83433: 
                   83434:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   83435:             return null;
                   83436:         }
                   83437: 
                   83438:         $file = $this->_packageFileName($package, $channel);
                   83439:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   83440:             return null;
                   83441:         }
                   83442: 
                   83443:         $fp = @fopen($file, $mode);
                   83444:         if (!$fp) {
                   83445:             return null;
                   83446:         }
                   83447: 
                   83448:         return $fp;
                   83449:     }
                   83450: 
                   83451:     function _closePackageFile($fp)
                   83452:     {
                   83453:         fclose($fp);
                   83454:     }
                   83455: 
                   83456:     function _openChannelFile($channel, $mode)
                   83457:     {
                   83458:         if (!$this->_assertChannelDir()) {
                   83459:             return null;
                   83460:         }
                   83461: 
                   83462:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   83463:             return null;
                   83464:         }
                   83465: 
                   83466:         $file = $this->_channelFileName($channel);
                   83467:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   83468:             return null;
                   83469:         }
                   83470: 
                   83471:         $fp = @fopen($file, $mode);
                   83472:         if (!$fp) {
                   83473:             return null;
                   83474:         }
                   83475: 
                   83476:         return $fp;
                   83477:     }
                   83478: 
                   83479:     function _closeChannelFile($fp)
                   83480:     {
                   83481:         fclose($fp);
                   83482:     }
                   83483: 
                   83484:     function _rebuildFileMap()
                   83485:     {
                   83486:         if (!class_exists('PEAR_Installer_Role')) {
                   83487:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
                   83488:         }
                   83489: 
                   83490:         $channels = $this->_listAllPackages();
                   83491:         $files = array();
                   83492:         foreach ($channels as $channel => $packages) {
                   83493:             foreach ($packages as $package) {
                   83494:                 $version = $this->_packageInfo($package, 'version', $channel);
                   83495:                 $filelist = $this->_packageInfo($package, 'filelist', $channel);
                   83496:                 if (!is_array($filelist)) {
                   83497:                     continue;
                   83498:                 }
                   83499: 
                   83500:                 foreach ($filelist as $name => $attrs) {
                   83501:                     if (isset($attrs['attribs'])) {
                   83502:                         $attrs = $attrs['attribs'];
                   83503:                     }
                   83504: 
                   83505:                     // it is possible for conflicting packages in different channels to
                   83506:                     // conflict with data files/doc files
                   83507:                     if ($name == 'dirtree') {
                   83508:                         continue;
                   83509:                     }
                   83510: 
                   83511:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   83512:                           PEAR_Installer_Role::getInstallableRoles())) {
                   83513:                         // these are not installed
                   83514:                         continue;
                   83515:                     }
                   83516: 
                   83517:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   83518:                           PEAR_Installer_Role::getBaseinstallRoles())) {
                   83519:                         $attrs['baseinstalldir'] = $package;
                   83520:                     }
                   83521: 
                   83522:                     if (isset($attrs['baseinstalldir'])) {
                   83523:                         $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
                   83524:                     } else {
                   83525:                         $file = $name;
                   83526:                     }
                   83527: 
                   83528:                     $file = preg_replace(',^/+,', '', $file);
                   83529:                     if ($channel != 'pear.php.net') {
                   83530:                         if (!isset($files[$attrs['role']])) {
                   83531:                             $files[$attrs['role']] = array();
                   83532:                         }
                   83533:                         $files[$attrs['role']][$file] = array(strtolower($channel),
                   83534:                             strtolower($package));
                   83535:                     } else {
                   83536:                         if (!isset($files[$attrs['role']])) {
                   83537:                             $files[$attrs['role']] = array();
                   83538:                         }
                   83539:                         $files[$attrs['role']][$file] = strtolower($package);
                   83540:                     }
                   83541:                 }
                   83542:             }
                   83543:         }
                   83544: 
                   83545: 
                   83546:         $this->_assertStateDir();
                   83547:         if (!$this->hasWriteAccess()) {
                   83548:             return false;
                   83549:         }
                   83550: 
                   83551:         $fp = @fopen($this->filemap, 'wb');
                   83552:         if (!$fp) {
                   83553:             return false;
                   83554:         }
                   83555: 
                   83556:         $this->filemap_cache = $files;
                   83557:         fwrite($fp, serialize($files));
                   83558:         fclose($fp);
                   83559:         return true;
                   83560:     }
                   83561: 
                   83562:     function _readFileMap()
                   83563:     {
                   83564:         if (!file_exists($this->filemap)) {
                   83565:             return array();
                   83566:         }
                   83567: 
                   83568:         $fp = @fopen($this->filemap, 'r');
                   83569:         if (!$fp) {
                   83570:             return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
                   83571:         }
                   83572: 
                   83573:         clearstatcache();
                   83574:         $rt = get_magic_quotes_runtime();
                   83575:         set_magic_quotes_runtime(0);
                   83576:         $fsize = filesize($this->filemap);
                   83577:         fclose($fp);
                   83578:         $data = file_get_contents($this->filemap);
                   83579:         set_magic_quotes_runtime($rt);
                   83580:         $tmp = unserialize($data);
                   83581:         if (!$tmp && $fsize > 7) {
                   83582:             return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
                   83583:         }
                   83584: 
                   83585:         $this->filemap_cache = $tmp;
                   83586:         return true;
                   83587:     }
                   83588: 
                   83589:     /**
                   83590:      * Lock the registry.
                   83591:      *
                   83592:      * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
                   83593:      *                See flock manual for more information.
                   83594:      *
                   83595:      * @return bool TRUE on success, FALSE if locking failed, or a
                   83596:      *              PEAR error if some other error occurs (such as the
                   83597:      *              lock file not being writable).
                   83598:      *
                   83599:      * @access private
                   83600:      */
                   83601:     function _lock($mode = LOCK_EX)
                   83602:     {
                   83603:         if (stristr(php_uname(), 'Windows 9')) {
                   83604:             return true;
                   83605:         }
                   83606: 
                   83607:         if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
                   83608:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   83609:             return true;
                   83610:         }
                   83611: 
                   83612:         if (!$this->_assertStateDir()) {
                   83613:             if ($mode == LOCK_EX) {
                   83614:                 return $this->raiseError('Registry directory is not writeable by the current user');
                   83615:             }
                   83616: 
                   83617:             return true;
                   83618:         }
                   83619: 
                   83620:         $open_mode = 'w';
                   83621:         // XXX People reported problems with LOCK_SH and 'w'
                   83622:         if ($mode === LOCK_SH || $mode === LOCK_UN) {
                   83623:             if (!file_exists($this->lockfile)) {
                   83624:                 touch($this->lockfile);
                   83625:             }
                   83626:             $open_mode = 'r';
                   83627:         }
                   83628: 
                   83629:         if (!is_resource($this->lock_fp)) {
                   83630:             $this->lock_fp = @fopen($this->lockfile, $open_mode);
                   83631:         }
                   83632: 
                   83633:         if (!is_resource($this->lock_fp)) {
                   83634:             $this->lock_fp = null;
                   83635:             return $this->raiseError("could not create lock file" .
                   83636:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   83637:         }
                   83638: 
                   83639:         if (!(int)flock($this->lock_fp, $mode)) {
                   83640:             switch ($mode) {
                   83641:                 case LOCK_SH: $str = 'shared';    break;
                   83642:                 case LOCK_EX: $str = 'exclusive'; break;
                   83643:                 case LOCK_UN: $str = 'unlock';    break;
                   83644:                 default:      $str = 'unknown';   break;
                   83645:             }
                   83646: 
                   83647:             //is resource at this point, close it on error.
                   83648:             fclose($this->lock_fp);
                   83649:             $this->lock_fp = null;
                   83650:             return $this->raiseError("could not acquire $str lock ($this->lockfile)",
                   83651:                                      PEAR_REGISTRY_ERROR_LOCK);
                   83652:         }
                   83653: 
                   83654:         return true;
                   83655:     }
                   83656: 
                   83657:     function _unlock()
                   83658:     {
                   83659:         $ret = $this->_lock(LOCK_UN);
                   83660:         if (is_resource($this->lock_fp)) {
                   83661:             fclose($this->lock_fp);
                   83662:         }
                   83663: 
                   83664:         $this->lock_fp = null;
                   83665:         return $ret;
                   83666:     }
                   83667: 
                   83668:     function _packageExists($package, $channel = false)
                   83669:     {
                   83670:         return file_exists($this->_packageFileName($package, $channel));
                   83671:     }
                   83672: 
                   83673:     /**
                   83674:      * Determine whether a channel exists in the registry
                   83675:      *
                   83676:      * @param string Channel name
                   83677:      * @param bool if true, then aliases will be ignored
                   83678:      * @return boolean
                   83679:      */
                   83680:     function _channelExists($channel, $noaliases = false)
                   83681:     {
                   83682:         $a = file_exists($this->_channelFileName($channel, $noaliases));
                   83683:         if (!$a && $channel == 'pear.php.net') {
                   83684:             return true;
                   83685:         }
                   83686: 
                   83687:         if (!$a && $channel == 'pecl.php.net') {
                   83688:             return true;
                   83689:         }
                   83690: 
                   83691:         if (!$a && $channel == 'doc.php.net') {
                   83692:             return true;
                   83693:         }
                   83694: 
                   83695:         return $a;
                   83696:     }
                   83697: 
                   83698:     /**
                   83699:      * Determine whether a mirror exists within the deafult channel in the registry
                   83700:      *
                   83701:      * @param string Channel name
                   83702:      * @param string Mirror name
                   83703:      *
                   83704:      * @return boolean
                   83705:      */
                   83706:     function _mirrorExists($channel, $mirror)
                   83707:     {
                   83708:         $data = $this->_channelInfo($channel);
                   83709:         if (!isset($data['servers']['mirror'])) {
                   83710:             return false;
                   83711:         }
                   83712: 
                   83713:         foreach ($data['servers']['mirror'] as $m) {
                   83714:             if ($m['attribs']['host'] == $mirror) {
                   83715:                 return true;
                   83716:             }
                   83717:         }
                   83718: 
                   83719:         return false;
                   83720:     }
                   83721: 
                   83722:     /**
                   83723:      * @param PEAR_ChannelFile Channel object
                   83724:      * @param donotuse
                   83725:      * @param string Last-Modified HTTP tag from remote request
                   83726:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   83727:      */
                   83728:     function _addChannel($channel, $update = false, $lastmodified = false)
                   83729:     {
                   83730:         if (!is_a($channel, 'PEAR_ChannelFile')) {
                   83731:             return false;
                   83732:         }
                   83733: 
                   83734:         if (!$channel->validate()) {
                   83735:             return false;
                   83736:         }
                   83737: 
                   83738:         if (file_exists($this->_channelFileName($channel->getName()))) {
                   83739:             if (!$update) {
                   83740:                 return false;
                   83741:             }
                   83742: 
                   83743:             $checker = $this->_getChannel($channel->getName());
                   83744:             if (PEAR::isError($checker)) {
                   83745:                 return $checker;
                   83746:             }
                   83747: 
                   83748:             if ($channel->getAlias() != $checker->getAlias()) {
                   83749:                 if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
                   83750:                     @unlink($this->_getChannelAliasFileName($checker->getAlias()));
                   83751:                 }
                   83752:             }
                   83753:         } else {
                   83754:             if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
                   83755:                 return false;
                   83756:             }
                   83757:         }
                   83758: 
                   83759:         $ret = $this->_assertChannelDir();
                   83760:         if (PEAR::isError($ret)) {
                   83761:             return $ret;
                   83762:         }
                   83763: 
                   83764:         $ret = $this->_assertChannelStateDir($channel->getName());
                   83765:         if (PEAR::isError($ret)) {
                   83766:             return $ret;
                   83767:         }
                   83768: 
                   83769:         if ($channel->getAlias() != $channel->getName()) {
                   83770:             if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
                   83771:                   $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
                   83772:                 $channel->setAlias($channel->getName());
                   83773:             }
                   83774: 
                   83775:             if (!$this->hasWriteAccess()) {
                   83776:                 return false;
                   83777:             }
                   83778: 
                   83779:             $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
                   83780:             if (!$fp) {
                   83781:                 return false;
                   83782:             }
                   83783: 
                   83784:             fwrite($fp, $channel->getName());
                   83785:             fclose($fp);
                   83786:         }
                   83787: 
                   83788:         if (!$this->hasWriteAccess()) {
                   83789:             return false;
                   83790:         }
                   83791: 
                   83792:         $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
                   83793:         if (!$fp) {
                   83794:             return false;
                   83795:         }
                   83796: 
                   83797:         $info = $channel->toArray();
                   83798:         if ($lastmodified) {
                   83799:             $info['_lastmodified'] = $lastmodified;
                   83800:         } else {
                   83801:             $info['_lastmodified'] = date('r');
                   83802:         }
                   83803: 
                   83804:         fwrite($fp, serialize($info));
                   83805:         fclose($fp);
                   83806:         return true;
                   83807:     }
                   83808: 
                   83809:     /**
                   83810:      * Deletion fails if there are any packages installed from the channel
                   83811:      * @param string|PEAR_ChannelFile channel name
                   83812:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   83813:      */
                   83814:     function _deleteChannel($channel)
                   83815:     {
                   83816:         if (!is_string($channel)) {
                   83817:             if (!is_a($channel, 'PEAR_ChannelFile')) {
                   83818:                 return false;
                   83819:             }
                   83820: 
                   83821:             if (!$channel->validate()) {
                   83822:                 return false;
                   83823:             }
                   83824:             $channel = $channel->getName();
                   83825:         }
                   83826: 
                   83827:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   83828:             return false;
                   83829:         }
                   83830: 
                   83831:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   83832:             return false;
                   83833:         }
                   83834: 
                   83835:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   83836:             return false;
                   83837:         }
                   83838: 
                   83839:         if (!$this->_channelExists($channel)) {
                   83840:             return false;
                   83841:         }
                   83842: 
                   83843:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   83844:             return false;
                   83845:         }
                   83846: 
                   83847:         $channel = $this->_getChannelFromAlias($channel);
                   83848:         if ($channel == 'pear.php.net') {
                   83849:             return false;
                   83850:         }
                   83851: 
                   83852:         $test = $this->_listChannelPackages($channel);
                   83853:         if (count($test)) {
                   83854:             return false;
                   83855:         }
                   83856: 
                   83857:         $test = @rmdir($this->_channelDirectoryName($channel));
                   83858:         if (!$test) {
                   83859:             return false;
                   83860:         }
                   83861: 
                   83862:         $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
                   83863:         if (file_exists($file)) {
                   83864:             $test = @unlink($file);
                   83865:             if (!$test) {
                   83866:                 return false;
                   83867:             }
                   83868:         }
                   83869: 
                   83870:         $file = $this->_channelFileName($channel);
                   83871:         $ret = true;
                   83872:         if (file_exists($file)) {
                   83873:             $ret = @unlink($file);
                   83874:         }
                   83875: 
                   83876:         return $ret;
                   83877:     }
                   83878: 
                   83879:     /**
                   83880:      * Determine whether a channel exists in the registry
                   83881:      * @param string Channel Alias
                   83882:      * @return boolean
                   83883:      */
                   83884:     function _isChannelAlias($alias)
                   83885:     {
                   83886:         return file_exists($this->_getChannelAliasFileName($alias));
                   83887:     }
                   83888: 
                   83889:     /**
                   83890:      * @param string|null
                   83891:      * @param string|null
                   83892:      * @param string|null
                   83893:      * @return array|null
                   83894:      * @access private
                   83895:      */
                   83896:     function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   83897:     {
                   83898:         if ($package === null) {
                   83899:             if ($channel === null) {
                   83900:                 $channels = $this->_listChannels();
                   83901:                 $ret = array();
                   83902:                 foreach ($channels as $channel) {
                   83903:                     $channel = strtolower($channel);
                   83904:                     $ret[$channel] = array();
                   83905:                     $packages = $this->_listPackages($channel);
                   83906:                     foreach ($packages as $package) {
                   83907:                         $ret[$channel][] = $this->_packageInfo($package, null, $channel);
                   83908:                     }
                   83909:                 }
                   83910: 
                   83911:                 return $ret;
                   83912:             }
                   83913: 
                   83914:             $ps = $this->_listPackages($channel);
                   83915:             if (!count($ps)) {
                   83916:                 return array();
                   83917:             }
                   83918:             return array_map(array(&$this, '_packageInfo'),
                   83919:                              $ps, array_fill(0, count($ps), null),
                   83920:                              array_fill(0, count($ps), $channel));
                   83921:         }
                   83922: 
                   83923:         $fp = $this->_openPackageFile($package, 'r', $channel);
                   83924:         if ($fp === null) {
                   83925:             return null;
                   83926:         }
                   83927: 
                   83928:         $rt = get_magic_quotes_runtime();
                   83929:         set_magic_quotes_runtime(0);
                   83930:         clearstatcache();
                   83931:         $this->_closePackageFile($fp);
                   83932:         $data = file_get_contents($this->_packageFileName($package, $channel));
                   83933:         set_magic_quotes_runtime($rt);
                   83934:         $data = unserialize($data);
                   83935:         if ($key === null) {
                   83936:             return $data;
                   83937:         }
                   83938: 
                   83939:         // compatibility for package.xml version 2.0
                   83940:         if (isset($data['old'][$key])) {
                   83941:             return $data['old'][$key];
                   83942:         }
                   83943: 
                   83944:         if (isset($data[$key])) {
                   83945:             return $data[$key];
                   83946:         }
                   83947: 
                   83948:         return null;
                   83949:     }
                   83950: 
                   83951:     /**
                   83952:      * @param string Channel name
                   83953:      * @param bool whether to strictly retrieve info of channels, not just aliases
                   83954:      * @return array|null
                   83955:      */
                   83956:     function _channelInfo($channel, $noaliases = false)
                   83957:     {
                   83958:         if (!$this->_channelExists($channel, $noaliases)) {
                   83959:             return null;
                   83960:         }
                   83961: 
                   83962:         $fp = $this->_openChannelFile($channel, 'r');
                   83963:         if ($fp === null) {
                   83964:             return null;
                   83965:         }
                   83966: 
                   83967:         $rt = get_magic_quotes_runtime();
                   83968:         set_magic_quotes_runtime(0);
                   83969:         clearstatcache();
                   83970:         $this->_closeChannelFile($fp);
                   83971:         $data = file_get_contents($this->_channelFileName($channel));
                   83972:         set_magic_quotes_runtime($rt);
                   83973:         $data = unserialize($data);
                   83974:         return $data;
                   83975:     }
                   83976: 
                   83977:     function _listChannels()
                   83978:     {
                   83979:         $channellist = array();
                   83980:         if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
                   83981:             return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
                   83982:         }
                   83983: 
                   83984:         $dp = opendir($this->channelsdir);
                   83985:         while ($ent = readdir($dp)) {
                   83986:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   83987:                 continue;
                   83988:             }
                   83989: 
                   83990:             if ($ent == '__uri.reg') {
                   83991:                 $channellist[] = '__uri';
                   83992:                 continue;
                   83993:             }
                   83994: 
                   83995:             $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
                   83996:         }
                   83997: 
                   83998:         closedir($dp);
                   83999:         if (!in_array('pear.php.net', $channellist)) {
                   84000:             $channellist[] = 'pear.php.net';
                   84001:         }
                   84002: 
                   84003:         if (!in_array('pecl.php.net', $channellist)) {
                   84004:             $channellist[] = 'pecl.php.net';
                   84005:         }
                   84006: 
                   84007:         if (!in_array('doc.php.net', $channellist)) {
                   84008:             $channellist[] = 'doc.php.net';
                   84009:         }
                   84010: 
                   84011: 
                   84012:         if (!in_array('__uri', $channellist)) {
                   84013:             $channellist[] = '__uri';
                   84014:         }
                   84015: 
                   84016:         natsort($channellist);
                   84017:         return $channellist;
                   84018:     }
                   84019: 
                   84020:     function _listPackages($channel = false)
                   84021:     {
                   84022:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   84023:             return $this->_listChannelPackages($channel);
                   84024:         }
                   84025: 
                   84026:         if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
                   84027:             return array();
                   84028:         }
                   84029: 
                   84030:         $pkglist = array();
                   84031:         $dp = opendir($this->statedir);
                   84032:         if (!$dp) {
                   84033:             return $pkglist;
                   84034:         }
                   84035: 
                   84036:         while ($ent = readdir($dp)) {
                   84037:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   84038:                 continue;
                   84039:             }
                   84040: 
                   84041:             $pkglist[] = substr($ent, 0, -4);
                   84042:         }
                   84043:         closedir($dp);
                   84044:         return $pkglist;
                   84045:     }
                   84046: 
                   84047:     function _listChannelPackages($channel)
                   84048:     {
                   84049:         $pkglist = array();
                   84050:         if (!file_exists($this->_channelDirectoryName($channel)) ||
                   84051:               !is_dir($this->_channelDirectoryName($channel))) {
                   84052:             return array();
                   84053:         }
                   84054: 
                   84055:         $dp = opendir($this->_channelDirectoryName($channel));
                   84056:         if (!$dp) {
                   84057:             return $pkglist;
                   84058:         }
                   84059: 
                   84060:         while ($ent = readdir($dp)) {
                   84061:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   84062:                 continue;
                   84063:             }
                   84064:             $pkglist[] = substr($ent, 0, -4);
                   84065:         }
                   84066: 
                   84067:         closedir($dp);
                   84068:         return $pkglist;
                   84069:     }
                   84070: 
                   84071:     function _listAllPackages()
                   84072:     {
                   84073:         $ret = array();
                   84074:         foreach ($this->_listChannels() as $channel) {
                   84075:             $ret[$channel] = $this->_listPackages($channel);
                   84076:         }
                   84077: 
                   84078:         return $ret;
                   84079:     }
                   84080: 
                   84081:     /**
                   84082:      * Add an installed package to the registry
                   84083:      * @param string package name
                   84084:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   84085:      * @return bool success of saving
                   84086:      * @access private
                   84087:      */
                   84088:     function _addPackage($package, $info)
                   84089:     {
                   84090:         if ($this->_packageExists($package)) {
                   84091:             return false;
                   84092:         }
                   84093: 
                   84094:         $fp = $this->_openPackageFile($package, 'wb');
                   84095:         if ($fp === null) {
                   84096:             return false;
                   84097:         }
                   84098: 
                   84099:         $info['_lastmodified'] = time();
                   84100:         fwrite($fp, serialize($info));
                   84101:         $this->_closePackageFile($fp);
                   84102:         if (isset($info['filelist'])) {
                   84103:             $this->_rebuildFileMap();
                   84104:         }
                   84105: 
                   84106:         return true;
                   84107:     }
                   84108: 
                   84109:     /**
                   84110:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   84111:      * @return bool
                   84112:      * @access private
                   84113:      */
                   84114:     function _addPackage2($info)
                   84115:     {
                   84116:         if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
                   84117:             return false;
                   84118:         }
                   84119: 
                   84120:         if (!$info->validate()) {
                   84121:             if (class_exists('PEAR_Common')) {
                   84122:                 $ui = PEAR_Frontend::singleton();
                   84123:                 if ($ui) {
                   84124:                     foreach ($info->getValidationWarnings() as $err) {
                   84125:                         $ui->log($err['message'], true);
                   84126:                     }
                   84127:                 }
                   84128:             }
                   84129:             return false;
                   84130:         }
                   84131: 
                   84132:         $channel = $info->getChannel();
                   84133:         $package = $info->getPackage();
                   84134:         $save = $info;
                   84135:         if ($this->_packageExists($package, $channel)) {
                   84136:             return false;
                   84137:         }
                   84138: 
                   84139:         if (!$this->_channelExists($channel, true)) {
                   84140:             return false;
                   84141:         }
                   84142: 
                   84143:         $info = $info->toArray(true);
                   84144:         if (!$info) {
                   84145:             return false;
                   84146:         }
                   84147: 
                   84148:         $fp = $this->_openPackageFile($package, 'wb', $channel);
                   84149:         if ($fp === null) {
                   84150:             return false;
                   84151:         }
                   84152: 
                   84153:         $info['_lastmodified'] = time();
                   84154:         fwrite($fp, serialize($info));
                   84155:         $this->_closePackageFile($fp);
                   84156:         $this->_rebuildFileMap();
                   84157:         return true;
                   84158:     }
                   84159: 
                   84160:     /**
                   84161:      * @param string Package name
                   84162:      * @param array parsed package.xml 1.0
                   84163:      * @param bool this parameter is only here for BC.  Don't use it.
                   84164:      * @access private
                   84165:      */
                   84166:     function _updatePackage($package, $info, $merge = true)
                   84167:     {
                   84168:         $oldinfo = $this->_packageInfo($package);
                   84169:         if (empty($oldinfo)) {
                   84170:             return false;
                   84171:         }
                   84172: 
                   84173:         $fp = $this->_openPackageFile($package, 'w');
                   84174:         if ($fp === null) {
                   84175:             return false;
                   84176:         }
                   84177: 
                   84178:         if (is_object($info)) {
                   84179:             $info = $info->toArray();
                   84180:         }
                   84181:         $info['_lastmodified'] = time();
                   84182: 
                   84183:         $newinfo = $info;
                   84184:         if ($merge) {
                   84185:             $info = array_merge($oldinfo, $info);
                   84186:         } else {
                   84187:             $diff = $info;
                   84188:         }
                   84189: 
                   84190:         fwrite($fp, serialize($info));
                   84191:         $this->_closePackageFile($fp);
                   84192:         if (isset($newinfo['filelist'])) {
                   84193:             $this->_rebuildFileMap();
                   84194:         }
                   84195: 
                   84196:         return true;
                   84197:     }
                   84198: 
                   84199:     /**
                   84200:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   84201:      * @return bool
                   84202:      * @access private
                   84203:      */
                   84204:     function _updatePackage2($info)
                   84205:     {
                   84206:         if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
                   84207:             return false;
                   84208:         }
                   84209: 
                   84210:         $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
                   84211:         if ($fp === null) {
                   84212:             return false;
                   84213:         }
                   84214: 
                   84215:         $save = $info;
                   84216:         $info = $save->getArray(true);
                   84217:         $info['_lastmodified'] = time();
                   84218:         fwrite($fp, serialize($info));
                   84219:         $this->_closePackageFile($fp);
                   84220:         $this->_rebuildFileMap();
                   84221:         return true;
                   84222:     }
                   84223: 
                   84224:     /**
                   84225:      * @param string Package name
                   84226:      * @param string Channel name
                   84227:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   84228:      * @access private
                   84229:      */
                   84230:     function &_getPackage($package, $channel = 'pear.php.net')
                   84231:     {
                   84232:         $info = $this->_packageInfo($package, null, $channel);
                   84233:         if ($info === null) {
                   84234:             return $info;
                   84235:         }
                   84236: 
                   84237:         $a = $this->_config;
                   84238:         if (!$a) {
                   84239:             $this->_config = &new PEAR_Config;
                   84240:             $this->_config->set('php_dir', $this->statedir);
                   84241:         }
                   84242: 
                   84243:         if (!class_exists('PEAR_PackageFile')) {
                   84244:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
                   84245:         }
                   84246: 
                   84247:         $pkg = &new PEAR_PackageFile($this->_config);
                   84248:         $pf = &$pkg->fromArray($info);
                   84249:         return $pf;
                   84250:     }
                   84251: 
                   84252:     /**
                   84253:      * @param string channel name
                   84254:      * @param bool whether to strictly retrieve channel names
                   84255:      * @return PEAR_ChannelFile|PEAR_Error
                   84256:      * @access private
                   84257:      */
                   84258:     function &_getChannel($channel, $noaliases = false)
                   84259:     {
                   84260:         $ch = false;
                   84261:         if ($this->_channelExists($channel, $noaliases)) {
                   84262:             $chinfo = $this->_channelInfo($channel, $noaliases);
                   84263:             if ($chinfo) {
                   84264:                 if (!class_exists('PEAR_ChannelFile')) {
                   84265:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   84266:                 }
                   84267: 
                   84268:                 $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
                   84269:             }
                   84270:         }
                   84271: 
                   84272:         if ($ch) {
                   84273:             if ($ch->validate()) {
                   84274:                 return $ch;
                   84275:             }
                   84276: 
                   84277:             foreach ($ch->getErrors(true) as $err) {
                   84278:                 $message = $err['message'] . "\n";
                   84279:             }
                   84280: 
                   84281:             $ch = PEAR::raiseError($message);
                   84282:             return $ch;
                   84283:         }
                   84284: 
                   84285:         if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   84286:             // the registry is not properly set up, so use defaults
                   84287:             if (!class_exists('PEAR_ChannelFile')) {
                   84288:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   84289:             }
                   84290: 
                   84291:             $pear_channel = new PEAR_ChannelFile;
                   84292:             $pear_channel->setServer('pear.php.net');
                   84293:             $pear_channel->setAlias('pear');
                   84294:             $pear_channel->setSummary('PHP Extension and Application Repository');
                   84295:             $pear_channel->setDefaultPEARProtocols();
                   84296:             $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   84297:             $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   84298:             $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   84299:             return $pear_channel;
                   84300:         }
                   84301: 
                   84302:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   84303:             // the registry is not properly set up, so use defaults
                   84304:             if (!class_exists('PEAR_ChannelFile')) {
                   84305:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   84306:             }
                   84307:             $pear_channel = new PEAR_ChannelFile;
                   84308:             $pear_channel->setServer('pecl.php.net');
                   84309:             $pear_channel->setAlias('pecl');
                   84310:             $pear_channel->setSummary('PHP Extension Community Library');
                   84311:             $pear_channel->setDefaultPEARProtocols();
                   84312:             $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   84313:             $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   84314:             $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   84315:             return $pear_channel;
                   84316:         }
                   84317: 
                   84318:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   84319:             // the registry is not properly set up, so use defaults
                   84320:             if (!class_exists('PEAR_ChannelFile')) {
                   84321:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   84322:             }
                   84323: 
                   84324:             $doc_channel = new PEAR_ChannelFile;
                   84325:             $doc_channel->setServer('doc.php.net');
                   84326:             $doc_channel->setAlias('phpdocs');
                   84327:             $doc_channel->setSummary('PHP Documentation Team');
                   84328:             $doc_channel->setDefaultPEARProtocols();
                   84329:             $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   84330:             $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   84331:             $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   84332:             return $doc_channel;
                   84333:         }
                   84334: 
                   84335: 
                   84336:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   84337:             // the registry is not properly set up, so use defaults
                   84338:             if (!class_exists('PEAR_ChannelFile')) {
                   84339:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
                   84340:             }
                   84341: 
                   84342:             $private = new PEAR_ChannelFile;
                   84343:             $private->setName('__uri');
                   84344:             $private->setDefaultPEARProtocols();
                   84345:             $private->setBaseURL('REST1.0', '****');
                   84346:             $private->setSummary('Pseudo-channel for static packages');
                   84347:             return $private;
                   84348:         }
                   84349: 
                   84350:         return $ch;
                   84351:     }
                   84352: 
                   84353:     /**
                   84354:      * @param string Package name
                   84355:      * @param string Channel name
                   84356:      * @return bool
                   84357:      */
                   84358:     function packageExists($package, $channel = 'pear.php.net')
                   84359:     {
                   84360:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84361:             return $e;
                   84362:         }
                   84363:         $ret = $this->_packageExists($package, $channel);
                   84364:         $this->_unlock();
                   84365:         return $ret;
                   84366:     }
                   84367: 
                   84368:     // }}}
                   84369: 
                   84370:     // {{{ channelExists()
                   84371: 
                   84372:     /**
                   84373:      * @param string channel name
                   84374:      * @param bool if true, then aliases will be ignored
                   84375:      * @return bool
                   84376:      */
                   84377:     function channelExists($channel, $noaliases = false)
                   84378:     {
                   84379:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84380:             return $e;
                   84381:         }
                   84382:         $ret = $this->_channelExists($channel, $noaliases);
                   84383:         $this->_unlock();
                   84384:         return $ret;
                   84385:     }
                   84386: 
                   84387:     // }}}
                   84388: 
                   84389:     /**
                   84390:      * @param string channel name mirror is in
                   84391:      * @param string mirror name
                   84392:      *
                   84393:      * @return bool
                   84394:      */
                   84395:     function mirrorExists($channel, $mirror)
                   84396:     {
                   84397:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84398:             return $e;
                   84399:         }
                   84400: 
                   84401:         $ret = $this->_mirrorExists($channel, $mirror);
                   84402:         $this->_unlock();
                   84403:         return $ret;
                   84404:     }
                   84405: 
                   84406:     // {{{ isAlias()
                   84407: 
                   84408:     /**
                   84409:      * Determines whether the parameter is an alias of a channel
                   84410:      * @param string
                   84411:      * @return bool
                   84412:      */
                   84413:     function isAlias($alias)
                   84414:     {
                   84415:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84416:             return $e;
                   84417:         }
                   84418:         $ret = $this->_isChannelAlias($alias);
                   84419:         $this->_unlock();
                   84420:         return $ret;
                   84421:     }
                   84422: 
                   84423:     // }}}
                   84424:     // {{{ packageInfo()
                   84425: 
                   84426:     /**
                   84427:      * @param string|null
                   84428:      * @param string|null
                   84429:      * @param string
                   84430:      * @return array|null
                   84431:      */
                   84432:     function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   84433:     {
                   84434:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84435:             return $e;
                   84436:         }
                   84437:         $ret = $this->_packageInfo($package, $key, $channel);
                   84438:         $this->_unlock();
                   84439:         return $ret;
                   84440:     }
                   84441: 
                   84442:     // }}}
                   84443:     // {{{ channelInfo()
                   84444: 
                   84445:     /**
                   84446:      * Retrieve a raw array of channel data.
                   84447:      *
                   84448:      * Do not use this, instead use {@link getChannel()} for normal
                   84449:      * operations.  Array structure is undefined in this method
                   84450:      * @param string channel name
                   84451:      * @param bool whether to strictly retrieve information only on non-aliases
                   84452:      * @return array|null|PEAR_Error
                   84453:      */
                   84454:     function channelInfo($channel = null, $noaliases = false)
                   84455:     {
                   84456:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84457:             return $e;
                   84458:         }
                   84459:         $ret = $this->_channelInfo($channel, $noaliases);
                   84460:         $this->_unlock();
                   84461:         return $ret;
                   84462:     }
                   84463: 
                   84464:     // }}}
                   84465: 
                   84466:     /**
                   84467:      * @param string
                   84468:      */
                   84469:     function channelName($channel)
                   84470:     {
                   84471:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84472:             return $e;
                   84473:         }
                   84474:         $ret = $this->_getChannelFromAlias($channel);
                   84475:         $this->_unlock();
                   84476:         return $ret;
                   84477:     }
                   84478: 
                   84479:     /**
                   84480:      * @param string
                   84481:      */
                   84482:     function channelAlias($channel)
                   84483:     {
                   84484:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84485:             return $e;
                   84486:         }
                   84487:         $ret = $this->_getAlias($channel);
                   84488:         $this->_unlock();
                   84489:         return $ret;
                   84490:     }
                   84491:     // {{{ listPackages()
                   84492: 
                   84493:     function listPackages($channel = false)
                   84494:     {
                   84495:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84496:             return $e;
                   84497:         }
                   84498:         $ret = $this->_listPackages($channel);
                   84499:         $this->_unlock();
                   84500:         return $ret;
                   84501:     }
                   84502: 
                   84503:     // }}}
                   84504:     // {{{ listAllPackages()
                   84505: 
                   84506:     function listAllPackages()
                   84507:     {
                   84508:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84509:             return $e;
                   84510:         }
                   84511:         $ret = $this->_listAllPackages();
                   84512:         $this->_unlock();
                   84513:         return $ret;
                   84514:     }
                   84515: 
                   84516:     // }}}
                   84517:     // {{{ listChannel()
                   84518: 
                   84519:     function listChannels()
                   84520:     {
                   84521:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84522:             return $e;
                   84523:         }
                   84524:         $ret = $this->_listChannels();
                   84525:         $this->_unlock();
                   84526:         return $ret;
                   84527:     }
                   84528: 
                   84529:     // }}}
                   84530:     // {{{ addPackage()
                   84531: 
                   84532:     /**
                   84533:      * Add an installed package to the registry
                   84534:      * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
                   84535:      *               that will be passed to {@link addPackage2()}
                   84536:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   84537:      * @return bool success of saving
                   84538:      */
                   84539:     function addPackage($package, $info)
                   84540:     {
                   84541:         if (is_object($info)) {
                   84542:             return $this->addPackage2($info);
                   84543:         }
                   84544:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84545:             return $e;
                   84546:         }
                   84547:         $ret = $this->_addPackage($package, $info);
                   84548:         $this->_unlock();
                   84549:         if ($ret) {
                   84550:             if (!class_exists('PEAR_PackageFile_v1')) {
                   84551:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   84552:             }
                   84553:             $pf = new PEAR_PackageFile_v1;
                   84554:             $pf->setConfig($this->_config);
                   84555:             $pf->fromArray($info);
                   84556:             $this->_dependencyDB->uninstallPackage($pf);
                   84557:             $this->_dependencyDB->installPackage($pf);
                   84558:         }
                   84559:         return $ret;
                   84560:     }
                   84561: 
                   84562:     // }}}
                   84563:     // {{{ addPackage2()
                   84564: 
                   84565:     function addPackage2($info)
                   84566:     {
                   84567:         if (!is_object($info)) {
                   84568:             return $this->addPackage($info['package'], $info);
                   84569:         }
                   84570:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84571:             return $e;
                   84572:         }
                   84573:         $ret = $this->_addPackage2($info);
                   84574:         $this->_unlock();
                   84575:         if ($ret) {
                   84576:             $this->_dependencyDB->uninstallPackage($info);
                   84577:             $this->_dependencyDB->installPackage($info);
                   84578:         }
                   84579:         return $ret;
                   84580:     }
                   84581: 
                   84582:     // }}}
                   84583:     // {{{ updateChannel()
                   84584: 
                   84585:     /**
                   84586:      * For future expandibility purposes, separate this
                   84587:      * @param PEAR_ChannelFile
                   84588:      */
                   84589:     function updateChannel($channel, $lastmodified = null)
                   84590:     {
                   84591:         if ($channel->getName() == '__uri') {
                   84592:             return false;
                   84593:         }
                   84594:         return $this->addChannel($channel, $lastmodified, true);
                   84595:     }
                   84596: 
                   84597:     // }}}
                   84598:     // {{{ deleteChannel()
                   84599: 
                   84600:     /**
                   84601:      * Deletion fails if there are any packages installed from the channel
                   84602:      * @param string|PEAR_ChannelFile channel name
                   84603:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   84604:      */
                   84605:     function deleteChannel($channel)
                   84606:     {
                   84607:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84608:             return $e;
                   84609:         }
                   84610: 
                   84611:         $ret = $this->_deleteChannel($channel);
                   84612:         $this->_unlock();
                   84613:         if ($ret && is_a($this->_config, 'PEAR_Config')) {
                   84614:             $this->_config->setChannels($this->listChannels());
                   84615:         }
                   84616: 
                   84617:         return $ret;
                   84618:     }
                   84619: 
                   84620:     // }}}
                   84621:     // {{{ addChannel()
                   84622: 
                   84623:     /**
                   84624:      * @param PEAR_ChannelFile Channel object
                   84625:      * @param string Last-Modified header from HTTP for caching
                   84626:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   84627:      */
                   84628:     function addChannel($channel, $lastmodified = false, $update = false)
                   84629:     {
                   84630:         if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
                   84631:             return false;
                   84632:         }
                   84633: 
                   84634:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84635:             return $e;
                   84636:         }
                   84637: 
                   84638:         $ret = $this->_addChannel($channel, $update, $lastmodified);
                   84639:         $this->_unlock();
                   84640:         if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
                   84641:             $this->_config->setChannels($this->listChannels());
                   84642:         }
                   84643: 
                   84644:         return $ret;
                   84645:     }
                   84646: 
                   84647:     // }}}
                   84648:     // {{{ deletePackage()
                   84649: 
                   84650:     function deletePackage($package, $channel = 'pear.php.net')
                   84651:     {
                   84652:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84653:             return $e;
                   84654:         }
                   84655: 
                   84656:         $file = $this->_packageFileName($package, $channel);
                   84657:         $ret  = file_exists($file) ? @unlink($file) : false;
                   84658:         $this->_rebuildFileMap();
                   84659:         $this->_unlock();
                   84660:         $p = array('channel' => $channel, 'package' => $package);
                   84661:         $this->_dependencyDB->uninstallPackage($p);
                   84662:         return $ret;
                   84663:     }
                   84664: 
                   84665:     // }}}
                   84666:     // {{{ updatePackage()
                   84667: 
                   84668:     function updatePackage($package, $info, $merge = true)
                   84669:     {
                   84670:         if (is_object($info)) {
                   84671:             return $this->updatePackage2($info, $merge);
                   84672:         }
                   84673:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84674:             return $e;
                   84675:         }
                   84676:         $ret = $this->_updatePackage($package, $info, $merge);
                   84677:         $this->_unlock();
                   84678:         if ($ret) {
                   84679:             if (!class_exists('PEAR_PackageFile_v1')) {
                   84680:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
                   84681:             }
                   84682:             $pf = new PEAR_PackageFile_v1;
                   84683:             $pf->setConfig($this->_config);
                   84684:             $pf->fromArray($this->packageInfo($package));
                   84685:             $this->_dependencyDB->uninstallPackage($pf);
                   84686:             $this->_dependencyDB->installPackage($pf);
                   84687:         }
                   84688:         return $ret;
                   84689:     }
                   84690: 
                   84691:     // }}}
                   84692:     // {{{ updatePackage2()
                   84693: 
                   84694:     function updatePackage2($info)
                   84695:     {
                   84696: 
                   84697:         if (!is_object($info)) {
                   84698:             return $this->updatePackage($info['package'], $info, $merge);
                   84699:         }
                   84700: 
                   84701:         if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
                   84702:             return false;
                   84703:         }
                   84704: 
                   84705:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   84706:             return $e;
                   84707:         }
                   84708: 
                   84709:         $ret = $this->_updatePackage2($info);
                   84710:         $this->_unlock();
                   84711:         if ($ret) {
                   84712:             $this->_dependencyDB->uninstallPackage($info);
                   84713:             $this->_dependencyDB->installPackage($info);
                   84714:         }
                   84715: 
                   84716:         return $ret;
                   84717:     }
                   84718: 
                   84719:     // }}}
                   84720:     // {{{ getChannel()
                   84721:     /**
                   84722:      * @param string channel name
                   84723:      * @param bool whether to strictly return raw channels (no aliases)
                   84724:      * @return PEAR_ChannelFile|PEAR_Error
                   84725:      */
                   84726:     function &getChannel($channel, $noaliases = false)
                   84727:     {
                   84728:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84729:             return $e;
                   84730:         }
                   84731:         $ret = &$this->_getChannel($channel, $noaliases);
                   84732:         $this->_unlock();
                   84733:         if (!$ret) {
                   84734:             return PEAR::raiseError('Unknown channel: ' . $channel);
                   84735:         }
                   84736:         return $ret;
                   84737:     }
                   84738: 
                   84739:     // }}}
                   84740:     // {{{ getPackage()
                   84741:     /**
                   84742:      * @param string package name
                   84743:      * @param string channel name
                   84744:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   84745:      */
                   84746:     function &getPackage($package, $channel = 'pear.php.net')
                   84747:     {
                   84748:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84749:             return $e;
                   84750:         }
                   84751:         $pf = &$this->_getPackage($package, $channel);
                   84752:         $this->_unlock();
                   84753:         return $pf;
                   84754:     }
                   84755: 
                   84756:     // }}}
                   84757: 
                   84758:     /**
                   84759:      * Get PEAR_PackageFile_v[1/2] objects representing the contents of
                   84760:      * a dependency group that are installed.
                   84761:      *
                   84762:      * This is used at uninstall-time
                   84763:      * @param array
                   84764:      * @return array|false
                   84765:      */
                   84766:     function getInstalledGroup($group)
                   84767:     {
                   84768:         $ret = array();
                   84769:         if (isset($group['package'])) {
                   84770:             if (!isset($group['package'][0])) {
                   84771:                 $group['package'] = array($group['package']);
                   84772:             }
                   84773:             foreach ($group['package'] as $package) {
                   84774:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   84775:                 $p = &$this->getPackage($package['name'], $depchannel);
                   84776:                 if ($p) {
                   84777:                     $save = &$p;
                   84778:                     $ret[] = &$save;
                   84779:                 }
                   84780:             }
                   84781:         }
                   84782:         if (isset($group['subpackage'])) {
                   84783:             if (!isset($group['subpackage'][0])) {
                   84784:                 $group['subpackage'] = array($group['subpackage']);
                   84785:             }
                   84786:             foreach ($group['subpackage'] as $package) {
                   84787:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   84788:                 $p = &$this->getPackage($package['name'], $depchannel);
                   84789:                 if ($p) {
                   84790:                     $save = &$p;
                   84791:                     $ret[] = &$save;
                   84792:                 }
                   84793:             }
                   84794:         }
                   84795:         if (!count($ret)) {
                   84796:             return false;
                   84797:         }
                   84798:         return $ret;
                   84799:     }
                   84800: 
                   84801:     // {{{ getChannelValidator()
                   84802:     /**
                   84803:      * @param string channel name
                   84804:      * @return PEAR_Validate|false
                   84805:      */
                   84806:     function &getChannelValidator($channel)
                   84807:     {
                   84808:         $chan = $this->getChannel($channel);
                   84809:         if (PEAR::isError($chan)) {
                   84810:             return $chan;
                   84811:         }
                   84812:         $val = $chan->getValidationObject();
                   84813:         return $val;
                   84814:     }
                   84815:     // }}}
                   84816:     // {{{ getChannels()
                   84817:     /**
                   84818:      * @param string channel name
                   84819:      * @return array an array of PEAR_ChannelFile objects representing every installed channel
                   84820:      */
                   84821:     function &getChannels()
                   84822:     {
                   84823:         $ret = array();
                   84824:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84825:             return $e;
                   84826:         }
                   84827:         foreach ($this->_listChannels() as $channel) {
                   84828:             $e = &$this->_getChannel($channel);
                   84829:             if (!$e || PEAR::isError($e)) {
                   84830:                 continue;
                   84831:             }
                   84832:             $ret[] = $e;
                   84833:         }
                   84834:         $this->_unlock();
                   84835:         return $ret;
                   84836:     }
                   84837: 
                   84838:     // }}}
                   84839:     // {{{ checkFileMap()
                   84840: 
                   84841:     /**
                   84842:      * Test whether a file or set of files belongs to a package.
                   84843:      *
                   84844:      * If an array is passed in
                   84845:      * @param string|array file path, absolute or relative to the pear
                   84846:      *                     install dir
                   84847:      * @param string|array name of PEAR package or array('package' => name, 'channel' =>
                   84848:      *                     channel) of a package that will be ignored
                   84849:      * @param string API version - 1.1 will exclude any files belonging to a package
                   84850:      * @param array private recursion variable
                   84851:      * @return array|false which package and channel the file belongs to, or an empty
                   84852:      *                     string if the file does not belong to an installed package,
                   84853:      *                     or belongs to the second parameter's package
                   84854:      */
                   84855:     function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
                   84856:     {
                   84857:         if (is_array($path)) {
                   84858:             static $notempty;
                   84859:             if (empty($notempty)) {
                   84860:                 if (!class_exists('PEAR_Installer_Role')) {
                   84861:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
                   84862:                 }
                   84863:                 $notempty = create_function('$a','return !empty($a);');
                   84864:             }
                   84865:             $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
                   84866:                 : strtolower($package);
                   84867:             $pkgs = array();
                   84868:             foreach ($path as $name => $attrs) {
                   84869:                 if (is_array($attrs)) {
                   84870:                     if (isset($attrs['install-as'])) {
                   84871:                         $name = $attrs['install-as'];
                   84872:                     }
                   84873:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
                   84874:                         // these are not installed
                   84875:                         continue;
                   84876:                     }
                   84877:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
                   84878:                         $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
                   84879:                     }
                   84880:                     if (isset($attrs['baseinstalldir'])) {
                   84881:                         $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
                   84882:                     }
                   84883:                 }
                   84884:                 $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
                   84885:                 if (PEAR::isError($pkgs[$name])) {
                   84886:                     return $pkgs[$name];
                   84887:                 }
                   84888:             }
                   84889:             return array_filter($pkgs, $notempty);
                   84890:         }
                   84891:         if (empty($this->filemap_cache)) {
                   84892:             if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   84893:                 return $e;
                   84894:             }
                   84895:             $err = $this->_readFileMap();
                   84896:             $this->_unlock();
                   84897:             if (PEAR::isError($err)) {
                   84898:                 return $err;
                   84899:             }
                   84900:         }
                   84901:         if (!$attrs) {
                   84902:             $attrs = array('role' => 'php'); // any old call would be for PHP role only
                   84903:         }
                   84904:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   84905:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   84906:                 return false;
                   84907:             }
                   84908:             return $this->filemap_cache[$attrs['role']][$path];
                   84909:         }
                   84910:         $l = strlen($this->install_dir);
                   84911:         if (substr($path, 0, $l) == $this->install_dir) {
                   84912:             $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
                   84913:         }
                   84914:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   84915:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   84916:                 return false;
                   84917:             }
                   84918:             return $this->filemap_cache[$attrs['role']][$path];
                   84919:         }
                   84920:         return false;
                   84921:     }
                   84922: 
                   84923:     // }}}
                   84924:     // {{{ flush()
                   84925:     /**
                   84926:      * Force a reload of the filemap
                   84927:      * @since 1.5.0RC3
                   84928:      */
                   84929:     function flushFileMap()
                   84930:     {
                   84931:         $this->filemap_cache = null;
                   84932:         clearstatcache(); // ensure that the next read gets the full, current filemap
                   84933:     }
                   84934: 
                   84935:     // }}}
                   84936:     // {{{ apiVersion()
                   84937:     /**
                   84938:      * Get the expected API version.  Channels API is version 1.1, as it is backwards
                   84939:      * compatible with 1.0
                   84940:      * @return string
                   84941:      */
                   84942:     function apiVersion()
                   84943:     {
                   84944:         return '1.1';
                   84945:     }
                   84946:     // }}}
                   84947: 
                   84948: 
                   84949:     /**
                   84950:      * Parse a package name, or validate a parsed package name array
                   84951:      * @param string|array pass in an array of format
                   84952:      *                     array(
                   84953:      *                      'package' => 'pname',
                   84954:      *                     ['channel' => 'channame',]
                   84955:      *                     ['version' => 'version',]
                   84956:      *                     ['state' => 'state',]
                   84957:      *                     ['group' => 'groupname'])
                   84958:      *                     or a string of format
                   84959:      *                     [channel://][channame/]pname[-version|-state][/group=groupname]
                   84960:      * @return array|PEAR_Error
                   84961:      */
                   84962:     function parsePackageName($param, $defaultchannel = 'pear.php.net')
                   84963:     {
                   84964:         $saveparam = $param;
                   84965:         if (is_array($param)) {
                   84966:             // convert to string for error messages
                   84967:             $saveparam = $this->parsedPackageNameToString($param);
                   84968:             // process the array
                   84969:             if (!isset($param['package'])) {
                   84970:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   84971:                     'must contain a valid package name in index "param"',
                   84972:                     'package', null, null, $param);
                   84973:             }
                   84974:             if (!isset($param['uri'])) {
                   84975:                 if (!isset($param['channel'])) {
                   84976:                     $param['channel'] = $defaultchannel;
                   84977:                 }
                   84978:             } else {
                   84979:                 $param['channel'] = '__uri';
                   84980:             }
                   84981:         } else {
                   84982:             $components = @parse_url((string) $param);
                   84983:             if (isset($components['scheme'])) {
                   84984:                 if ($components['scheme'] == 'http') {
                   84985:                     // uri package
                   84986:                     $param = array('uri' => $param, 'channel' => '__uri');
                   84987:                 } elseif($components['scheme'] != 'channel') {
                   84988:                     return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
                   84989:                         'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
                   84990:                 }
                   84991:             }
                   84992:             if (!isset($components['path'])) {
                   84993:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   84994:                     'must contain a valid package name in "' . $param . '"',
                   84995:                     'package', null, null, $param);
                   84996:             }
                   84997:             if (isset($components['host'])) {
                   84998:                 // remove the leading "/"
                   84999:                 $components['path'] = substr($components['path'], 1);
                   85000:             }
                   85001:             if (!isset($components['scheme'])) {
                   85002:                 if (strpos($components['path'], '/') !== false) {
                   85003:                     if ($components['path']{0} == '/') {
                   85004:                         return PEAR::raiseError('parsePackageName(): this is not ' .
                   85005:                             'a package name, it begins with "/" in "' . $param . '"',
                   85006:                             'invalid', null, null, $param);
                   85007:                     }
                   85008:                     $parts = explode('/', $components['path']);
                   85009:                     $components['host'] = array_shift($parts);
                   85010:                     if (count($parts) > 1) {
                   85011:                         $components['path'] = array_pop($parts);
                   85012:                         $components['host'] .= '/' . implode('/', $parts);
                   85013:                     } else {
                   85014:                         $components['path'] = implode('/', $parts);
                   85015:                     }
                   85016:                 } else {
                   85017:                     $components['host'] = $defaultchannel;
                   85018:                 }
                   85019:             } else {
                   85020:                 if (strpos($components['path'], '/')) {
                   85021:                     $parts = explode('/', $components['path']);
                   85022:                     $components['path'] = array_pop($parts);
                   85023:                     $components['host'] .= '/' . implode('/', $parts);
                   85024:                 }
                   85025:             }
                   85026: 
                   85027:             if (is_array($param)) {
                   85028:                 $param['package'] = $components['path'];
                   85029:             } else {
                   85030:                 $param = array(
                   85031:                     'package' => $components['path']
                   85032:                     );
                   85033:                 if (isset($components['host'])) {
                   85034:                     $param['channel'] = $components['host'];
                   85035:                 }
                   85036:             }
                   85037:             if (isset($components['fragment'])) {
                   85038:                 $param['group'] = $components['fragment'];
                   85039:             }
                   85040:             if (isset($components['user'])) {
                   85041:                 $param['user'] = $components['user'];
                   85042:             }
                   85043:             if (isset($components['pass'])) {
                   85044:                 $param['pass'] = $components['pass'];
                   85045:             }
                   85046:             if (isset($components['query'])) {
                   85047:                 parse_str($components['query'], $param['opts']);
                   85048:             }
                   85049:             // check for extension
                   85050:             $pathinfo = pathinfo($param['package']);
                   85051:             if (isset($pathinfo['extension']) &&
                   85052:                   in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
                   85053:                 $param['extension'] = $pathinfo['extension'];
                   85054:                 $param['package'] = substr($pathinfo['basename'], 0,
                   85055:                     strlen($pathinfo['basename']) - 4);
                   85056:             }
                   85057:             // check for version
                   85058:             if (strpos($param['package'], '-')) {
                   85059:                 $test = explode('-', $param['package']);
                   85060:                 if (count($test) != 2) {
                   85061:                     return PEAR::raiseError('parsePackageName(): only one version/state ' .
                   85062:                         'delimiter "-" is allowed in "' . $saveparam . '"',
                   85063:                         'version', null, null, $param);
                   85064:                 }
                   85065:                 list($param['package'], $param['version']) = $test;
                   85066:             }
                   85067:         }
                   85068:         // validation
                   85069:         $info = $this->channelExists($param['channel']);
                   85070:         if (PEAR::isError($info)) {
                   85071:             return $info;
                   85072:         }
                   85073:         if (!$info) {
                   85074:             return PEAR::raiseError('unknown channel "' . $param['channel'] .
                   85075:                 '" in "' . $saveparam . '"', 'channel', null, null, $param);
                   85076:         }
                   85077:         $chan = $this->getChannel($param['channel']);
                   85078:         if (PEAR::isError($chan)) {
                   85079:             return $chan;
                   85080:         }
                   85081:         if (!$chan) {
                   85082:             return PEAR::raiseError("Exception: corrupt registry, could not " .
                   85083:                 "retrieve channel " . $param['channel'] . " information",
                   85084:                 'registry', null, null, $param);
                   85085:         }
                   85086:         $param['channel'] = $chan->getName();
                   85087:         $validate = $chan->getValidationObject();
                   85088:         $vpackage = $chan->getValidationPackage();
                   85089:         // validate package name
                   85090:         if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
                   85091:             return PEAR::raiseError('parsePackageName(): invalid package name "' .
                   85092:                 $param['package'] . '" in "' . $saveparam . '"',
                   85093:                 'package', null, null, $param);
                   85094:         }
                   85095:         if (isset($param['group'])) {
                   85096:             if (!PEAR_Validate::validGroupName($param['group'])) {
                   85097:                 return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
                   85098:                     '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
                   85099:                     $param);
                   85100:             }
                   85101:         }
                   85102:         if (isset($param['state'])) {
                   85103:             if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
                   85104:                 return PEAR::raiseError('parsePackageName(): state "' . $param['state']
                   85105:                     . '" is not a valid state in "' . $saveparam . '"',
                   85106:                     'state', null, null, $param);
                   85107:             }
                   85108:         }
                   85109:         if (isset($param['version'])) {
                   85110:             if (isset($param['state'])) {
                   85111:                 return PEAR::raiseError('parsePackageName(): cannot contain both ' .
                   85112:                     'a version and a stability (state) in "' . $saveparam . '"',
                   85113:                     'version/state', null, null, $param);
                   85114:             }
                   85115:             // check whether version is actually a state
                   85116:             if (in_array(strtolower($param['version']), $validate->getValidStates())) {
                   85117:                 $param['state'] = strtolower($param['version']);
                   85118:                 unset($param['version']);
                   85119:             } else {
                   85120:                 if (!$validate->validVersion($param['version'])) {
                   85121:                     return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
                   85122:                         '" is neither a valid version nor a valid state in "' .
                   85123:                         $saveparam . '"', 'version/state', null, null, $param);
                   85124:                 }
                   85125:             }
                   85126:         }
                   85127:         return $param;
                   85128:     }
                   85129: 
                   85130:     /**
                   85131:      * @param array
                   85132:      * @return string
                   85133:      */
                   85134:     function parsedPackageNameToString($parsed, $brief = false)
                   85135:     {
                   85136:         if (is_string($parsed)) {
                   85137:             return $parsed;
                   85138:         }
                   85139:         if (is_object($parsed)) {
                   85140:             $p = $parsed;
                   85141:             $parsed = array(
                   85142:                 'package' => $p->getPackage(),
                   85143:                 'channel' => $p->getChannel(),
                   85144:                 'version' => $p->getVersion(),
                   85145:             );
                   85146:         }
                   85147:         if (isset($parsed['uri'])) {
                   85148:             return $parsed['uri'];
                   85149:         }
                   85150:         if ($brief) {
                   85151:             if ($channel = $this->channelAlias($parsed['channel'])) {
                   85152:                 return $channel . '/' . $parsed['package'];
                   85153:             }
                   85154:         }
                   85155:         $upass = '';
                   85156:         if (isset($parsed['user'])) {
                   85157:             $upass = $parsed['user'];
                   85158:             if (isset($parsed['pass'])) {
                   85159:                 $upass .= ':' . $parsed['pass'];
                   85160:             }
                   85161:             $upass = "$upass@";
                   85162:         }
                   85163:         $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
                   85164:         if (isset($parsed['version']) || isset($parsed['state'])) {
                   85165:             $ver = isset($parsed['version']) ? $parsed['version'] : '';
                   85166:             $ver .= isset($parsed['state']) ? $parsed['state'] : '';
                   85167:             $ret .= '-' . $ver;
                   85168:         }
                   85169:         if (isset($parsed['extension'])) {
                   85170:             $ret .= '.' . $parsed['extension'];
                   85171:         }
                   85172:         if (isset($parsed['opts'])) {
                   85173:             $ret .= '?';
                   85174:             foreach ($parsed['opts'] as $name => $value) {
                   85175:                 $parsed['opts'][$name] = "$name=$value";
                   85176:             }
                   85177:             $ret .= implode('&', $parsed['opts']);
                   85178:         }
                   85179:         if (isset($parsed['group'])) {
                   85180:             $ret .= '#' . $parsed['group'];
                   85181:         }
                   85182:         return $ret;
                   85183:     }
                   85184: }<?php
                   85185: /**
                   85186:  * PEAR_REST
                   85187:  *
                   85188:  * PHP versions 4 and 5
                   85189:  *
                   85190:  * @category   pear
                   85191:  * @package    PEAR
                   85192:  * @author     Greg Beaver <cellog@php.net>
                   85193:  * @copyright  1997-2009 The Authors
                   85194:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   85195:  * @version    CVS: $Id: REST.php 309593 2011-03-23 12:34:39Z dufuz $
                   85196:  * @link       http://pear.php.net/package/PEAR
                   85197:  * @since      File available since Release 1.4.0a1
                   85198:  */
                   85199: 
                   85200: /**
                   85201:  * For downloading xml files
                   85202:  */
                   85203: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   85204: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
                   85205: 
                   85206: /**
                   85207:  * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
                   85208:  * as well
                   85209:  * @category   pear
                   85210:  * @package    PEAR
                   85211:  * @author     Greg Beaver <cellog@php.net>
                   85212:  * @copyright  1997-2009 The Authors
                   85213:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   85214:  * @version    Release: 1.10.0beta1
                   85215:  * @link       http://pear.php.net/package/PEAR
                   85216:  * @since      Class available since Release 1.4.0a1
                   85217:  */
                   85218: class PEAR_REST
                   85219: {
                   85220:     var $config;
                   85221:     var $_options;
                   85222: 
                   85223:     function PEAR_REST(&$config, $options = array())
                   85224:     {
                   85225:         $this->config   = &$config;
                   85226:         $this->_options = $options;
                   85227:     }
                   85228: 
                   85229:     /**
                   85230:      * Retrieve REST data, but always retrieve the local cache if it is available.
                   85231:      *
                   85232:      * This is useful for elements that should never change, such as information on a particular
                   85233:      * release
                   85234:      * @param string full URL to this resource
                   85235:      * @param array|false contents of the accept-encoding header
                   85236:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   85237:      *                    parsed using PEAR_XMLParser
                   85238:      * @return string|array
                   85239:      */
                   85240:     function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
                   85241:     {
                   85242:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   85243:             md5($url) . 'rest.cachefile';
                   85244: 
                   85245:         if (file_exists($cachefile)) {
                   85246:             return unserialize(implode('', file($cachefile)));
                   85247:         }
                   85248: 
                   85249:         return $this->retrieveData($url, $accept, $forcestring, $channel);
                   85250:     }
                   85251: 
                   85252:     /**
                   85253:      * Retrieve a remote REST resource
                   85254:      * @param string full URL to this resource
                   85255:      * @param array|false contents of the accept-encoding header
                   85256:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   85257:      *                    parsed using PEAR_XMLParser
                   85258:      * @return string|array
                   85259:      */
                   85260:     function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
                   85261:     {
                   85262:         $cacheId = $this->getCacheId($url);
                   85263:         if ($ret = $this->useLocalCache($url, $cacheId)) {
                   85264:             return $ret;
                   85265:         }
                   85266: 
                   85267:         $file = $trieddownload = false;
                   85268:         if (!isset($this->_options['offline'])) {
                   85269:             $trieddownload = true;
                   85270:             $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
                   85271:         }
                   85272: 
                   85273:         if (PEAR::isError($file)) {
                   85274:             if ($file->getCode() !== -9276) {
                   85275:                 return $file;
                   85276:             }
                   85277: 
                   85278:             $trieddownload = false;
                   85279:             $file = false; // use local copy if available on socket connect error
                   85280:         }
                   85281: 
                   85282:         if (!$file) {
                   85283:             $ret = $this->getCache($url);
                   85284:             if (!PEAR::isError($ret) && $trieddownload) {
                   85285:                 // reset the age of the cache if the server says it was unmodified
                   85286:                 $result = $this->saveCache($url, $ret, null, true, $cacheId);
                   85287:                 if (PEAR::isError($result)) {
                   85288:                     return PEAR::raiseError($result->getMessage());
                   85289:                 }
                   85290:             }
                   85291: 
                   85292:             return $ret;
                   85293:         }
                   85294: 
                   85295:         if (is_array($file)) {
                   85296:             $headers      = $file[2];
                   85297:             $lastmodified = $file[1];
                   85298:             $content      = $file[0];
                   85299:         } else {
                   85300:             $headers      = array();
                   85301:             $lastmodified = false;
                   85302:             $content      = $file;
                   85303:         }
                   85304: 
                   85305:         if ($forcestring) {
                   85306:             $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   85307:             if (PEAR::isError($result)) {
                   85308:                 return PEAR::raiseError($result->getMessage());
                   85309:             }
                   85310: 
                   85311:             return $content;
                   85312:         }
                   85313: 
                   85314:         if (isset($headers['content-type'])) {
                   85315:             switch ($headers['content-type']) {
                   85316:                 case 'text/xml' :
                   85317:                 case 'application/xml' :
                   85318:                 case 'text/plain' :
                   85319:                     if ($headers['content-type'] === 'text/plain') {
                   85320:                         $check = substr($content, 0, 5);
                   85321:                         if ($check !== '<?xml') {
                   85322:                             break;
                   85323:                         }
                   85324:                     }
                   85325: 
                   85326:                     $parser = new PEAR_XMLParser;
                   85327:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   85328:                     $err = $parser->parse($content);
                   85329:                     PEAR::popErrorHandling();
                   85330:                     if (PEAR::isError($err)) {
                   85331:                         return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
                   85332:                             $err->getMessage());
                   85333:                     }
                   85334:                     $content = $parser->getData();
                   85335:                 case 'text/html' :
                   85336:                 default :
                   85337:                     // use it as a string
                   85338:             }
                   85339:         } else {
                   85340:             // assume XML
                   85341:             $parser = new PEAR_XMLParser;
                   85342:             $parser->parse($content);
                   85343:             $content = $parser->getData();
                   85344:         }
                   85345: 
                   85346:         $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   85347:         if (PEAR::isError($result)) {
                   85348:             return PEAR::raiseError($result->getMessage());
                   85349:         }
                   85350: 
                   85351:         return $content;
                   85352:     }
                   85353: 
                   85354:     function useLocalCache($url, $cacheid = null)
                   85355:     {
                   85356:         if ($cacheid === null) {
                   85357:             $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   85358:                 md5($url) . 'rest.cacheid';
                   85359:             if (!file_exists($cacheidfile)) {
                   85360:                 return false;
                   85361:             }
                   85362: 
                   85363:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   85364:         }
                   85365: 
                   85366:         $cachettl = $this->config->get('cache_ttl');
                   85367:         // If cache is newer than $cachettl seconds, we use the cache!
                   85368:         if (time() - $cacheid['age'] < $cachettl) {
                   85369:             return $this->getCache($url);
                   85370:         }
                   85371: 
                   85372:         return false;
                   85373:     }
                   85374: 
                   85375:     function getCacheId($url)
                   85376:     {
                   85377:         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   85378:             md5($url) . 'rest.cacheid';
                   85379: 
                   85380:         if (!file_exists($cacheidfile)) {
                   85381:             return false;
                   85382:         }
                   85383: 
                   85384:         $ret = unserialize(implode('', file($cacheidfile)));
                   85385:         return $ret;
                   85386:     }
                   85387: 
                   85388:     function getCache($url)
                   85389:     {
                   85390:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   85391:             md5($url) . 'rest.cachefile';
                   85392: 
                   85393:         if (!file_exists($cachefile)) {
                   85394:             return PEAR::raiseError('No cached content available for "' . $url . '"');
                   85395:         }
                   85396: 
                   85397:         return unserialize(implode('', file($cachefile)));
                   85398:     }
                   85399: 
                   85400:     /**
                   85401:      * @param string full URL to REST resource
                   85402:      * @param string original contents of the REST resource
                   85403:      * @param array  HTTP Last-Modified and ETag headers
                   85404:      * @param bool   if true, then the cache id file should be regenerated to
                   85405:      *               trigger a new time-to-live value
                   85406:      */
                   85407:     function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
                   85408:     {
                   85409:         $cache_dir   = $this->config->get('cache_dir');
                   85410:         $d           = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
                   85411:         $cacheidfile = $d . 'rest.cacheid';
                   85412:         $cachefile   = $d . 'rest.cachefile';
                   85413: 
                   85414:         if (!is_dir($cache_dir)) {
                   85415:             if (System::mkdir(array('-p', $cache_dir)) === false) {
                   85416:               return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
                   85417:             }
                   85418:         }
                   85419: 
                   85420:         if ($cacheid === null && $nochange) {
                   85421:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   85422:         }
                   85423: 
                   85424:         $idData = serialize(array(
                   85425:             'age'        => time(),
                   85426:             'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
                   85427:         ));
                   85428: 
                   85429:         $result = $this->saveCacheFile($cacheidfile, $idData);
                   85430:         if (PEAR::isError($result)) {
                   85431:             return $result;
                   85432:         } elseif ($nochange) {
                   85433:             return true;
                   85434:         }
                   85435: 
                   85436:         $result = $this->saveCacheFile($cachefile, serialize($contents));
                   85437:         if (PEAR::isError($result)) {
                   85438:             if (file_exists($cacheidfile)) {
                   85439:               @unlink($cacheidfile);
                   85440:             }
                   85441: 
                   85442:             return $result;
                   85443:         }
                   85444: 
                   85445:         return true;
                   85446:     }
                   85447: 
                   85448:     function saveCacheFile($file, $contents)
                   85449:     {
                   85450:         $len = strlen($contents);
                   85451: 
                   85452:         $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
                   85453:         if ($cachefile_fp !== false) { // create file
                   85454:             if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   85455:                 fclose($cachefile_fp);
                   85456:                 return PEAR::raiseError("Could not write $file.");
                   85457:             }
                   85458:         } else { // update file
                   85459:             $cachefile_lstat = lstat($file);
                   85460:             $cachefile_fp = @fopen($file, 'wb');
                   85461:             if (!$cachefile_fp) {
                   85462:                 return PEAR::raiseError("Could not open $file for writing.");
                   85463:             }
                   85464: 
                   85465:             $cachefile_fstat = fstat($cachefile_fp);
                   85466:             if (
                   85467:               $cachefile_lstat['mode'] == $cachefile_fstat['mode'] &&
                   85468:               $cachefile_lstat['ino']  == $cachefile_fstat['ino'] &&
                   85469:               $cachefile_lstat['dev']  == $cachefile_fstat['dev'] &&
                   85470:               $cachefile_fstat['nlink'] === 1
                   85471:             ) {
                   85472:                 if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   85473:                     fclose($cachefile_fp);
                   85474:                     return PEAR::raiseError("Could not write $file.");
                   85475:                 }
                   85476:             } else {
                   85477:                 fclose($cachefile_fp);
                   85478:                 $link = function_exists('readlink') ? readlink($file) : $file;
                   85479:                 return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
                   85480:             }
                   85481:         }
                   85482: 
                   85483:         fclose($cachefile_fp);
                   85484:         return true;
                   85485:     }
                   85486: 
                   85487:     /**
                   85488:      * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
                   85489:      * This is best used for small files
                   85490:      *
                   85491:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   85492:      * setting), the proxy will be used.
                   85493:      *
                   85494:      * @param string  $url       the URL to download
                   85495:      * @param string  $save_dir  directory to save file in
                   85496:      * @param false|string|array $lastmodified header values to check against for caching
                   85497:      *                           use false to return the header values from this download
                   85498:      * @param false|array $accept Accept headers to send
                   85499:      * @return string|array  Returns the contents of the downloaded file or a PEAR
                   85500:      *                       error on failure.  If the error is caused by
                   85501:      *                       socket-related errors, the error object will
                   85502:      *                       have the fsockopen error code available through
                   85503:      *                       getCode().  If caching is requested, then return the header
                   85504:      *                       values.
                   85505:      *
                   85506:      * @access public
                   85507:      */
                   85508:     function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
                   85509:     {
                   85510:         static $redirect = 0;
                   85511:         // always reset , so we are clean case of error
                   85512:         $wasredirect = $redirect;
                   85513:         $redirect = 0;
                   85514: 
                   85515:         $info = parse_url($url);
                   85516:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   85517:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   85518:         }
                   85519: 
                   85520:         if (!isset($info['host'])) {
                   85521:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   85522:         }
                   85523: 
                   85524:         $host   = isset($info['host']) ? $info['host'] : null;
                   85525:         $port   = isset($info['port']) ? $info['port'] : null;
                   85526:         $path   = isset($info['path']) ? $info['path'] : null;
                   85527:         $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   85528: 
                   85529:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   85530:         if ($this->config->get('http_proxy')&&
                   85531:               $proxy = parse_url($this->config->get('http_proxy'))
                   85532:         ) {
                   85533:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   85534:             if ($schema === 'https') {
                   85535:                 $proxy_host = 'ssl://' . $proxy_host;
                   85536:             }
                   85537: 
                   85538:             $proxy_port   = isset($proxy['port']) ? $proxy['port'] : 8080;
                   85539:             $proxy_user   = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   85540:             $proxy_pass   = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   85541:             $proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
                   85542:         }
                   85543: 
                   85544:         if (empty($port)) {
                   85545:             $port = (isset($info['scheme']) && $info['scheme'] == 'https')  ? 443 : 80;
                   85546:         }
                   85547: 
                   85548:         if (isset($proxy['host'])) {
                   85549:             $request = "GET $url HTTP/1.1\r\n";
                   85550:         } else {
                   85551:             $request = "GET $path HTTP/1.1\r\n";
                   85552:         }
                   85553: 
                   85554:         $request .= "Host: $host\r\n";
                   85555:         $ifmodifiedsince = '';
                   85556:         if (is_array($lastmodified)) {
                   85557:             if (isset($lastmodified['Last-Modified'])) {
                   85558:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   85559:             }
                   85560: 
                   85561:             if (isset($lastmodified['ETag'])) {
                   85562:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   85563:             }
                   85564:         } else {
                   85565:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   85566:         }
                   85567: 
                   85568:         $request .= $ifmodifiedsince .
                   85569:             "User-Agent: PEAR/1.10.0beta1/PHP/" . PHP_VERSION . "\r\n";
                   85570: 
                   85571:         $username = $this->config->get('username', null, $channel);
                   85572:         $password = $this->config->get('password', null, $channel);
                   85573: 
                   85574:         if ($username && $password) {
                   85575:             $tmp = base64_encode("$username:$password");
                   85576:             $request .= "Authorization: Basic $tmp\r\n";
                   85577:         }
                   85578: 
                   85579:         if ($proxy_host != '' && $proxy_user != '') {
                   85580:             $request .= 'Proxy-Authorization: Basic ' .
                   85581:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   85582:         }
                   85583: 
                   85584:         if ($accept) {
                   85585:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   85586:         }
                   85587: 
                   85588:         $request .= "Accept-Encoding:\r\n";
                   85589:         $request .= "Connection: close\r\n";
                   85590:         $request .= "\r\n";
                   85591: 
                   85592:         if ($proxy_host != '') {
                   85593:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
                   85594:             if (!$fp) {
                   85595:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276);
                   85596:             }
                   85597:         } else {
                   85598:             if ($schema === 'https') {
                   85599:                 $host = 'ssl://' . $host;
                   85600:             }
                   85601: 
                   85602:             $fp = @fsockopen($host, $port, $errno, $errstr);
                   85603:             if (!$fp) {
                   85604:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   85605:             }
                   85606:         }
                   85607: 
                   85608:         fwrite($fp, $request);
                   85609: 
                   85610:         $headers = array();
                   85611:         $reply   = 0;
                   85612:         while ($line = trim(fgets($fp, 1024))) {
                   85613:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   85614:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   85615:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   85616:                 $reply = (int)$matches[1];
                   85617:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   85618:                     return false;
                   85619:                 }
                   85620: 
                   85621:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   85622:                     return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
                   85623:                 }
                   85624:             }
                   85625:         }
                   85626: 
                   85627:         if ($reply != 200) {
                   85628:             if (!isset($headers['location'])) {
                   85629:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
                   85630:             }
                   85631: 
                   85632:             if ($wasredirect > 4) {
                   85633:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
                   85634:             }
                   85635: 
                   85636:             $redirect = $wasredirect + 1;
                   85637:             return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
                   85638:         }
                   85639: 
                   85640:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   85641: 
                   85642:         $data = '';
                   85643:         while ($chunk = @fread($fp, 8192)) {
                   85644:             $data .= $chunk;
                   85645:         }
                   85646:         fclose($fp);
                   85647: 
                   85648:         if ($lastmodified === false || $lastmodified) {
                   85649:             if (isset($headers['etag'])) {
                   85650:                 $lastmodified = array('ETag' => $headers['etag']);
                   85651:             }
                   85652: 
                   85653:             if (isset($headers['last-modified'])) {
                   85654:                 if (is_array($lastmodified)) {
                   85655:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   85656:                 } else {
                   85657:                     $lastmodified = $headers['last-modified'];
                   85658:                 }
                   85659:             }
                   85660: 
                   85661:             return array($data, $lastmodified, $headers);
                   85662:         }
                   85663: 
                   85664:         return $data;
                   85665:     }
                   85666: }
                   85667: <?php
                   85668: /**
                   85669:  * PEAR_REST_10
                   85670:  *
                   85671:  * PHP versions 4 and 5
                   85672:  *
                   85673:  * @category   pear
                   85674:  * @package    PEAR
                   85675:  * @author     Greg Beaver <cellog@php.net>
                   85676:  * @copyright  1997-2009 The Authors
                   85677:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   85678:  * @version    CVS: $Id: 10.php 311690 2011-06-01 04:57:58Z dufuz $
                   85679:  * @link       http://pear.php.net/package/PEAR
                   85680:  * @since      File available since Release 1.4.0a12
                   85681:  */
                   85682: 
                   85683: /**
                   85684:  * For downloading REST xml/txt files
                   85685:  */
                   85686: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
                   85687: 
                   85688: /**
                   85689:  * Implement REST 1.0
                   85690:  *
                   85691:  * @category   pear
                   85692:  * @package    PEAR
                   85693:  * @author     Greg Beaver <cellog@php.net>
                   85694:  * @copyright  1997-2009 The Authors
                   85695:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   85696:  * @version    Release: 1.10.0beta1
                   85697:  * @link       http://pear.php.net/package/PEAR
                   85698:  * @since      Class available since Release 1.4.0a12
                   85699:  */
                   85700: class PEAR_REST_10
                   85701: {
                   85702:     /**
                   85703:      * @var PEAR_REST
                   85704:      */
                   85705:     var $_rest;
                   85706:     function PEAR_REST_10($config, $options = array())
                   85707:     {
                   85708:         $this->_rest = &new PEAR_REST($config, $options);
                   85709:     }
                   85710: 
                   85711:     /**
                   85712:      * Retrieve information about a remote package to be downloaded from a REST server
                   85713:      *
                   85714:      * @param string $base The uri to prepend to all REST calls
                   85715:      * @param array $packageinfo an array of format:
                   85716:      * <pre>
                   85717:      *  array(
                   85718:      *   'package' => 'packagename',
                   85719:      *   'channel' => 'channelname',
                   85720:      *  ['state' => 'alpha' (or valid state),]
                   85721:      *  -or-
                   85722:      *  ['version' => '1.whatever']
                   85723:      * </pre>
                   85724:      * @param string $prefstate Current preferred_state config variable value
                   85725:      * @param bool $installed the installed version of this package to compare against
                   85726:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   85727:      */
                   85728:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   85729:     {
                   85730:         $states = $this->betterStates($prefstate, true);
                   85731:         if (!$states) {
                   85732:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   85733:         }
                   85734: 
                   85735:         $channel  = $packageinfo['channel'];
                   85736:         $package  = $packageinfo['package'];
                   85737:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   85738:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
                   85739:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   85740: 
                   85741:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   85742:         if (PEAR::isError($info)) {
                   85743:             return PEAR::raiseError('No releases available for package "' .
                   85744:                 $channel . '/' . $package . '"');
                   85745:         }
                   85746: 
                   85747:         if (!isset($info['r'])) {
                   85748:             return false;
                   85749:         }
                   85750: 
                   85751:         $release = $found = false;
                   85752:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   85753:             $info['r'] = array($info['r']);
                   85754:         }
                   85755: 
                   85756:         foreach ($info['r'] as $release) {
                   85757:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   85758:                   version_compare($release['v'], $installed, '<'))) {
                   85759:                 continue;
                   85760:             }
                   85761: 
                   85762:             if (isset($state)) {
                   85763:                 // try our preferred state first
                   85764:                 if ($release['s'] == $state) {
                   85765:                     $found = true;
                   85766:                     break;
                   85767:                 }
                   85768:                 // see if there is something newer and more stable
                   85769:                 // bug #7221
                   85770:                 if (in_array($release['s'], $this->betterStates($state), true)) {
                   85771:                     $found = true;
                   85772:                     break;
                   85773:                 }
                   85774:             } elseif (isset($version)) {
                   85775:                 if ($release['v'] == $version) {
                   85776:                     $found = true;
                   85777:                     break;
                   85778:                 }
                   85779:             } else {
                   85780:                 if (in_array($release['s'], $states)) {
                   85781:                     $found = true;
                   85782:                     break;
                   85783:                 }
                   85784:             }
                   85785:         }
                   85786: 
                   85787:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   85788:     }
                   85789: 
                   85790:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   85791:                                $prefstate = 'stable', $installed = false, $channel = false)
                   85792:     {
                   85793:         $states = $this->betterStates($prefstate, true);
                   85794:         if (!$states) {
                   85795:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   85796:         }
                   85797: 
                   85798:         $channel  = $dependency['channel'];
                   85799:         $package  = $dependency['name'];
                   85800:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   85801:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
                   85802:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   85803: 
                   85804:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   85805:         if (PEAR::isError($info)) {
                   85806:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   85807:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   85808:         }
                   85809: 
                   85810:         if (!is_array($info) || !isset($info['r'])) {
                   85811:             return false;
                   85812:         }
                   85813: 
                   85814:         $exclude = array();
                   85815:         $min = $max = $recommended = false;
                   85816:         if ($xsdversion == '1.0') {
                   85817:             switch ($dependency['rel']) {
                   85818:                 case 'ge' :
                   85819:                     $min = $dependency['version'];
                   85820:                 break;
                   85821:                 case 'gt' :
                   85822:                     $min = $dependency['version'];
                   85823:                     $exclude = array($dependency['version']);
                   85824:                 break;
                   85825:                 case 'eq' :
                   85826:                     $recommended = $dependency['version'];
                   85827:                 break;
                   85828:                 case 'lt' :
                   85829:                     $max = $dependency['version'];
                   85830:                     $exclude = array($dependency['version']);
                   85831:                 break;
                   85832:                 case 'le' :
                   85833:                     $max = $dependency['version'];
                   85834:                 break;
                   85835:                 case 'ne' :
                   85836:                     $exclude = array($dependency['version']);
                   85837:                 break;
                   85838:             }
                   85839:         } else {
                   85840:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   85841:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   85842:             $recommended = isset($dependency['recommended']) ?
                   85843:                 $dependency['recommended'] : false;
                   85844:             if (isset($dependency['exclude'])) {
                   85845:                 if (!isset($dependency['exclude'][0])) {
                   85846:                     $exclude = array($dependency['exclude']);
                   85847:                 }
                   85848:             }
                   85849:         }
                   85850:         $release = $found = false;
                   85851:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   85852:             $info['r'] = array($info['r']);
                   85853:         }
                   85854:         foreach ($info['r'] as $release) {
                   85855:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   85856:                   version_compare($release['v'], $installed, '<'))) {
                   85857:                 continue;
                   85858:             }
                   85859:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   85860:                 continue;
                   85861:             }
                   85862:             // allow newer releases to say "I'm OK with the dependent package"
                   85863:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   85864:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   85865:                     $release['co'] = array($release['co']);
                   85866:                 }
                   85867:                 foreach ($release['co'] as $entry) {
                   85868:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   85869:                         $entry['x'] = array($entry['x']);
                   85870:                     } elseif (!isset($entry['x'])) {
                   85871:                         $entry['x'] = array();
                   85872:                     }
                   85873:                     if ($entry['c'] == $deppackage['channel'] &&
                   85874:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   85875:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   85876:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   85877:                           !in_array($release['v'], $entry['x'])) {
                   85878:                         $recommended = $release['v'];
                   85879:                         break;
                   85880:                     }
                   85881:                 }
                   85882:             }
                   85883:             if ($recommended) {
                   85884:                 if ($release['v'] != $recommended) { // if we want a specific
                   85885:                     // version, then skip all others
                   85886:                     continue;
                   85887:                 } else {
                   85888:                     if (!in_array($release['s'], $states)) {
                   85889:                         // the stability is too low, but we must return the
                   85890:                         // recommended version if possible
                   85891:                         return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                   85892:                     }
                   85893:                 }
                   85894:             }
                   85895:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   85896:                 continue;
                   85897:             }
                   85898:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   85899:                 continue;
                   85900:             }
                   85901:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   85902:                 continue;
                   85903:             }
                   85904:             if (in_array($release['s'], $states)) { // if in the preferred state...
                   85905:                 $found = true; // ... then use it
                   85906:                 break;
                   85907:             }
                   85908:         }
                   85909:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   85910:     }
                   85911: 
                   85912:     /**
                   85913:      * Take raw data and return the array needed for processing a download URL
                   85914:      *
                   85915:      * @param string $base REST base uri
                   85916:      * @param string $package Package name
                   85917:      * @param array $release an array of format array('v' => version, 's' => state)
                   85918:      *                       describing the release to download
                   85919:      * @param array $info list of all releases as defined by allreleases.xml
                   85920:      * @param bool|null $found determines whether the release was found or this is the next
                   85921:      *                    best alternative.  If null, then versions were skipped because
                   85922:      *                    of PHP dependency
                   85923:      * @return array|PEAR_Error
                   85924:      * @access private
                   85925:      */
                   85926:     function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
                   85927:     {
                   85928:         if (!$found) {
                   85929:             $release = $info['r'][0];
                   85930:         }
                   85931: 
                   85932:         $packageLower = strtolower($package);
                   85933:         $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
                   85934:             'info.xml', false, false, $channel);
                   85935:         if (PEAR::isError($pinfo)) {
                   85936:             return PEAR::raiseError('Package "' . $package .
                   85937:                 '" does not have REST info xml available');
                   85938:         }
                   85939: 
                   85940:         $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   85941:             $release['v'] . '.xml', false, false, $channel);
                   85942:         if (PEAR::isError($releaseinfo)) {
                   85943:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   85944:                 '" does not have REST xml available');
                   85945:         }
                   85946: 
                   85947:         $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   85948:             'deps.' . $release['v'] . '.txt', false, true, $channel);
                   85949:         if (PEAR::isError($packagexml)) {
                   85950:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   85951:                 '" does not have REST dependency information available');
                   85952:         }
                   85953: 
                   85954:         $packagexml = unserialize($packagexml);
                   85955:         if (!$packagexml) {
                   85956:             $packagexml = array();
                   85957:         }
                   85958: 
                   85959:         $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
                   85960:             '/allreleases.xml', false, false, $channel);
                   85961:         if (PEAR::isError($allinfo)) {
                   85962:             return $allinfo;
                   85963:         }
                   85964: 
                   85965:         if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
                   85966:             $allinfo['r'] = array($allinfo['r']);
                   85967:         }
                   85968: 
                   85969:         $compatible = false;
                   85970:         foreach ($allinfo['r'] as $release) {
                   85971:             if ($release['v'] != $releaseinfo['v']) {
                   85972:                 continue;
                   85973:             }
                   85974: 
                   85975:             if (!isset($release['co'])) {
                   85976:                 break;
                   85977:             }
                   85978: 
                   85979:             $compatible = array();
                   85980:             if (!is_array($release['co']) || !isset($release['co'][0])) {
                   85981:                 $release['co'] = array($release['co']);
                   85982:             }
                   85983: 
                   85984:             foreach ($release['co'] as $entry) {
                   85985:                 $comp = array();
                   85986:                 $comp['name']    = $entry['p'];
                   85987:                 $comp['channel'] = $entry['c'];
                   85988:                 $comp['min']     = $entry['min'];
                   85989:                 $comp['max']     = $entry['max'];
                   85990:                 if (isset($entry['x']) && !is_array($entry['x'])) {
                   85991:                     $comp['exclude'] = $entry['x'];
                   85992:                 }
                   85993: 
                   85994:                 $compatible[] = $comp;
                   85995:             }
                   85996: 
                   85997:             if (count($compatible) == 1) {
                   85998:                 $compatible = $compatible[0];
                   85999:             }
                   86000: 
                   86001:             break;
                   86002:         }
                   86003: 
                   86004:         $deprecated = false;
                   86005:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   86006:             if (is_array($pinfo['dp'])) {
                   86007:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   86008:                                     'package' => trim($pinfo['dp']['_content']));
                   86009:             } else {
                   86010:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   86011:                                     'package' => trim($pinfo['dp']));
                   86012:             }
                   86013:         }
                   86014: 
                   86015:         $return = array(
                   86016:             'version'    => $releaseinfo['v'],
                   86017:             'info'       => $packagexml,
                   86018:             'package'    => $releaseinfo['p']['_content'],
                   86019:             'stability'  => $releaseinfo['st'],
                   86020:             'compatible' => $compatible,
                   86021:             'deprecated' => $deprecated,
                   86022:         );
                   86023: 
                   86024:         if ($found) {
                   86025:             $return['url'] = $releaseinfo['g'];
                   86026:             return $return;
                   86027:         }
                   86028: 
                   86029:         $return['php'] = $phpversion;
                   86030:         return $return;
                   86031:     }
                   86032: 
                   86033:     function listPackages($base, $channel = false)
                   86034:     {
                   86035:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   86036:         if (PEAR::isError($packagelist)) {
                   86037:             return $packagelist;
                   86038:         }
                   86039: 
                   86040:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   86041:             return array();
                   86042:         }
                   86043: 
                   86044:         if (!is_array($packagelist['p'])) {
                   86045:             $packagelist['p'] = array($packagelist['p']);
                   86046:         }
                   86047: 
                   86048:         return $packagelist['p'];
                   86049:     }
                   86050: 
                   86051:     /**
                   86052:      * List all categories of a REST server
                   86053:      *
                   86054:      * @param string $base base URL of the server
                   86055:      * @return array of categorynames
                   86056:      */
                   86057:     function listCategories($base, $channel = false)
                   86058:     {
                   86059:         $categories = array();
                   86060: 
                   86061:         // c/categories.xml does not exist;
                   86062:         // check for every package its category manually
                   86063:         // This is SLOOOWWWW : ///
                   86064:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   86065:         if (PEAR::isError($packagelist)) {
                   86066:             return $packagelist;
                   86067:         }
                   86068: 
                   86069:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   86070:             $ret = array();
                   86071:             return $ret;
                   86072:         }
                   86073: 
                   86074:         if (!is_array($packagelist['p'])) {
                   86075:             $packagelist['p'] = array($packagelist['p']);
                   86076:         }
                   86077: 
                   86078:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   86079:         foreach ($packagelist['p'] as $package) {
                   86080:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   86081:                 if (PEAR::isError($inf)) {
                   86082:                     PEAR::popErrorHandling();
                   86083:                     return $inf;
                   86084:                 }
                   86085:                 $cat = $inf['ca']['_content'];
                   86086:                 if (!isset($categories[$cat])) {
                   86087:                     $categories[$cat] = $inf['ca'];
                   86088:                 }
                   86089:         }
                   86090: 
                   86091:         return array_values($categories);
                   86092:     }
                   86093: 
                   86094:     /**
                   86095:      * List a category of a REST server
                   86096:      *
                   86097:      * @param string $base base URL of the server
                   86098:      * @param string $category name of the category
                   86099:      * @param boolean $info also download full package info
                   86100:      * @return array of packagenames
                   86101:      */
                   86102:     function listCategory($base, $category, $info = false, $channel = false)
                   86103:     {
                   86104:         // gives '404 Not Found' error when category doesn't exist
                   86105:         $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
                   86106:         if (PEAR::isError($packagelist)) {
                   86107:             return $packagelist;
                   86108:         }
                   86109: 
                   86110:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   86111:             return array();
                   86112:         }
                   86113: 
                   86114:         if (!is_array($packagelist['p']) ||
                   86115:             !isset($packagelist['p'][0])) { // only 1 pkg
                   86116:             $packagelist = array($packagelist['p']);
                   86117:         } else {
                   86118:             $packagelist = $packagelist['p'];
                   86119:         }
                   86120: 
                   86121:         if ($info == true) {
                   86122:             // get individual package info
                   86123:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   86124:             foreach ($packagelist as $i => $packageitem) {
                   86125:                 $url = sprintf('%s'.'r/%s/latest.txt',
                   86126:                         $base,
                   86127:                         strtolower($packageitem['_content']));
                   86128:                 $version = $this->_rest->retrieveData($url, false, false, $channel);
                   86129:                 if (PEAR::isError($version)) {
                   86130:                     break; // skipit
                   86131:                 }
                   86132:                 $url = sprintf('%s'.'r/%s/%s.xml',
                   86133:                         $base,
                   86134:                         strtolower($packageitem['_content']),
                   86135:                         $version);
                   86136:                 $info = $this->_rest->retrieveData($url, false, false, $channel);
                   86137:                 if (PEAR::isError($info)) {
                   86138:                     break; // skipit
                   86139:                 }
                   86140:                 $packagelist[$i]['info'] = $info;
                   86141:             }
                   86142:             PEAR::popErrorHandling();
                   86143:         }
                   86144: 
                   86145:         return $packagelist;
                   86146:     }
                   86147: 
                   86148: 
                   86149:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
                   86150:     {
                   86151:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   86152:         if (PEAR::isError($packagelist)) {
                   86153:             return $packagelist;
                   86154:         }
                   86155:         if ($this->_rest->config->get('verbose') > 0) {
                   86156:             $ui = &PEAR_Frontend::singleton();
                   86157:             $ui->log('Retrieving data...0%', true);
                   86158:         }
                   86159:         $ret = array();
                   86160:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   86161:             return $ret;
                   86162:         }
                   86163:         if (!is_array($packagelist['p'])) {
                   86164:             $packagelist['p'] = array($packagelist['p']);
                   86165:         }
                   86166: 
                   86167:         // only search-packagename = quicksearch !
                   86168:         if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
                   86169:             $newpackagelist = array();
                   86170:             foreach ($packagelist['p'] as $package) {
                   86171:                 if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
                   86172:                     $newpackagelist[] = $package;
                   86173:                 }
                   86174:             }
                   86175:             $packagelist['p'] = $newpackagelist;
                   86176:         }
                   86177:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   86178:         $next = .1;
                   86179:         foreach ($packagelist['p'] as $progress => $package) {
                   86180:             if ($this->_rest->config->get('verbose') > 0) {
                   86181:                 if ($progress / count($packagelist['p']) >= $next) {
                   86182:                     if ($next == .5) {
                   86183:                         $ui->log('50%', false);
                   86184:                     } else {
                   86185:                         $ui->log('.', false);
                   86186:                     }
                   86187:                     $next += .1;
                   86188:                 }
                   86189:             }
                   86190: 
                   86191:             if ($basic) { // remote-list command
                   86192:                 if ($dostable) {
                   86193:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   86194:                         '/stable.txt', false, false, $channel);
                   86195:                 } else {
                   86196:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   86197:                         '/latest.txt', false, false, $channel);
                   86198:                 }
                   86199:                 if (PEAR::isError($latest)) {
                   86200:                     $latest = false;
                   86201:                 }
                   86202:                 $info = array('stable' => $latest);
                   86203:             } else { // list-all command
                   86204:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   86205:                 if (PEAR::isError($inf)) {
                   86206:                     PEAR::popErrorHandling();
                   86207:                     return $inf;
                   86208:                 }
                   86209:                 if ($searchpackage) {
                   86210:                     $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
                   86211:                     if (!$found && !(isset($searchsummary) && !empty($searchsummary)
                   86212:                         && (stristr($inf['s'], $searchsummary) !== false
                   86213:                             || stristr($inf['d'], $searchsummary) !== false)))
                   86214:                     {
                   86215:                         continue;
                   86216:                     };
                   86217:                 }
                   86218:                 $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   86219:                     '/allreleases.xml', false, false, $channel);
                   86220:                 if (PEAR::isError($releases)) {
                   86221:                     continue;
                   86222:                 }
                   86223:                 if (!isset($releases['r'][0])) {
                   86224:                     $releases['r'] = array($releases['r']);
                   86225:                 }
                   86226:                 unset($latest);
                   86227:                 unset($unstable);
                   86228:                 unset($stable);
                   86229:                 unset($state);
                   86230:                 foreach ($releases['r'] as $release) {
                   86231:                     if (!isset($latest)) {
                   86232:                         if ($dostable && $release['s'] == 'stable') {
                   86233:                             $latest = $release['v'];
                   86234:                             $state = 'stable';
                   86235:                         }
                   86236:                         if (!$dostable) {
                   86237:                             $latest = $release['v'];
                   86238:                             $state = $release['s'];
                   86239:                         }
                   86240:                     }
                   86241:                     if (!isset($stable) && $release['s'] == 'stable') {
                   86242:                         $stable = $release['v'];
                   86243:                         if (!isset($unstable)) {
                   86244:                             $unstable = $stable;
                   86245:                         }
                   86246:                     }
                   86247:                     if (!isset($unstable) && $release['s'] != 'stable') {
                   86248:                         $latest = $unstable = $release['v'];
                   86249:                         $state = $release['s'];
                   86250:                     }
                   86251:                     if (isset($latest) && !isset($state)) {
                   86252:                         $state = $release['s'];
                   86253:                     }
                   86254:                     if (isset($latest) && isset($stable) && isset($unstable)) {
                   86255:                         break;
                   86256:                     }
                   86257:                 }
                   86258:                 $deps = array();
                   86259:                 if (!isset($unstable)) {
                   86260:                     $unstable = false;
                   86261:                     $state = 'stable';
                   86262:                     if (isset($stable)) {
                   86263:                         $latest = $unstable = $stable;
                   86264:                     }
                   86265:                 } else {
                   86266:                     $latest = $unstable;
                   86267:                 }
                   86268:                 if (!isset($latest)) {
                   86269:                     $latest = false;
                   86270:                 }
                   86271:                 if ($latest) {
                   86272:                     $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   86273:                         $latest . '.txt', false, false, $channel);
                   86274:                     if (!PEAR::isError($d)) {
                   86275:                         $d = unserialize($d);
                   86276:                         if ($d) {
                   86277:                             if (isset($d['required'])) {
                   86278:                                 if (!class_exists('PEAR_PackageFile_v2')) {
                   86279:                                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   86280:                                 }
                   86281:                                 if (!isset($pf)) {
                   86282:                                     $pf = new PEAR_PackageFile_v2;
                   86283:                                 }
                   86284:                                 $pf->setDeps($d);
                   86285:                                 $tdeps = $pf->getDeps();
                   86286:                             } else {
                   86287:                                 $tdeps = $d;
                   86288:                             }
                   86289:                             foreach ($tdeps as $dep) {
                   86290:                                 if ($dep['type'] !== 'pkg') {
                   86291:                                     continue;
                   86292:                                 }
                   86293:                                 $deps[] = $dep;
                   86294:                             }
                   86295:                         }
                   86296:                     }
                   86297:                 }
                   86298:                 if (!isset($stable)) {
                   86299:                     $stable = '-n/a-';
                   86300:                 }
                   86301:                 if (!$searchpackage) {
                   86302:                     $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
                   86303:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   86304:                         'unstable' => $unstable, 'state' => $state);
                   86305:                 } else {
                   86306:                     $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
                   86307:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   86308:                         'unstable' => $unstable, 'state' => $state);
                   86309:                 }
                   86310:             }
                   86311:             $ret[$package] = $info;
                   86312:         }
                   86313:         PEAR::popErrorHandling();
                   86314:         return $ret;
                   86315:     }
                   86316: 
                   86317:     function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
                   86318:     {
                   86319:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   86320:         if (PEAR::isError($packagelist)) {
                   86321:             return $packagelist;
                   86322:         }
                   86323: 
                   86324:         $ret = array();
                   86325:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   86326:             return $ret;
                   86327:         }
                   86328: 
                   86329:         if (!is_array($packagelist['p'])) {
                   86330:             $packagelist['p'] = array($packagelist['p']);
                   86331:         }
                   86332: 
                   86333:         foreach ($packagelist['p'] as $package) {
                   86334:             if (!isset($installed[strtolower($package)])) {
                   86335:                 continue;
                   86336:             }
                   86337: 
                   86338:             $inst_version = $reg->packageInfo($package, 'version', $channel);
                   86339:             $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                   86340:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   86341:             $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   86342:                 '/allreleases.xml', false, false, $channel);
                   86343:             PEAR::popErrorHandling();
                   86344:             if (PEAR::isError($info)) {
                   86345:                 continue; // no remote releases
                   86346:             }
                   86347: 
                   86348:             if (!isset($info['r'])) {
                   86349:                 continue;
                   86350:             }
                   86351: 
                   86352:             $release = $found = false;
                   86353:             if (!is_array($info['r']) || !isset($info['r'][0])) {
                   86354:                 $info['r'] = array($info['r']);
                   86355:             }
                   86356: 
                   86357:             // $info['r'] is sorted by version number
                   86358:             usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
                   86359:             foreach ($info['r'] as $release) {
                   86360:                 if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
                   86361:                     // not newer than the one installed
                   86362:                     break;
                   86363:                 }
                   86364: 
                   86365:                 // new version > installed version
                   86366:                 if (!$pref_state) {
                   86367:                     // every state is a good state
                   86368:                     $found = true;
                   86369:                     break;
                   86370:                 } else {
                   86371:                     $new_state = $release['s'];
                   86372:                     // if new state >= installed state: go
                   86373:                     if (in_array($new_state, $this->betterStates($inst_state, true))) {
                   86374:                         $found = true;
                   86375:                         break;
                   86376:                     } else {
                   86377:                         // only allow to lower the state of package,
                   86378:                         // if new state >= preferred state: go
                   86379:                         if (in_array($new_state, $this->betterStates($pref_state, true))) {
                   86380:                             $found = true;
                   86381:                             break;
                   86382:                         }
                   86383:                     }
                   86384:                 }
                   86385:             }
                   86386: 
                   86387:             if (!$found) {
                   86388:                 continue;
                   86389:             }
                   86390: 
                   86391:             $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
                   86392:                 $release['v'] . '.xml', false, false, $channel);
                   86393:             if (PEAR::isError($relinfo)) {
                   86394:                 return $relinfo;
                   86395:             }
                   86396: 
                   86397:             $ret[$package] = array(
                   86398:                 'version'  => $release['v'],
                   86399:                 'state'    => $release['s'],
                   86400:                 'filesize' => $relinfo['f'],
                   86401:             );
                   86402:         }
                   86403: 
                   86404:         return $ret;
                   86405:     }
                   86406: 
                   86407:     function packageInfo($base, $package, $channel = false)
                   86408:     {
                   86409:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   86410:         $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   86411:         if (PEAR::isError($pinfo)) {
                   86412:             PEAR::popErrorHandling();
                   86413:             return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
                   86414:                 $pinfo->getMessage());
                   86415:         }
                   86416: 
                   86417:         $releases = array();
                   86418:         $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   86419:             '/allreleases.xml', false, false, $channel);
                   86420:         if (!PEAR::isError($allreleases)) {
                   86421:             if (!class_exists('PEAR_PackageFile_v2')) {
                   86422:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
                   86423:             }
                   86424: 
                   86425:             if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
                   86426:                 $allreleases['r'] = array($allreleases['r']);
                   86427:             }
                   86428: 
                   86429:             $pf = new PEAR_PackageFile_v2;
                   86430:             foreach ($allreleases['r'] as $release) {
                   86431:                 $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   86432:                     $release['v'] . '.txt', false, false, $channel);
                   86433:                 if (PEAR::isError($ds)) {
                   86434:                     continue;
                   86435:                 }
                   86436: 
                   86437:                 if (!isset($latest)) {
                   86438:                     $latest = $release['v'];
                   86439:                 }
                   86440: 
                   86441:                 $pf->setDeps(unserialize($ds));
                   86442:                 $ds = $pf->getDeps();
                   86443:                 $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
                   86444:                     . '/' . $release['v'] . '.xml', false, false, $channel);
                   86445: 
                   86446:                 if (PEAR::isError($info)) {
                   86447:                     continue;
                   86448:                 }
                   86449: 
                   86450:                 $releases[$release['v']] = array(
                   86451:                     'doneby' => $info['m'],
                   86452:                     'license' => $info['l'],
                   86453:                     'summary' => $info['s'],
                   86454:                     'description' => $info['d'],
                   86455:                     'releasedate' => $info['da'],
                   86456:                     'releasenotes' => $info['n'],
                   86457:                     'state' => $release['s'],
                   86458:                     'deps' => $ds ? $ds : array(),
                   86459:                 );
                   86460:             }
                   86461:         } else {
                   86462:             $latest = '';
                   86463:         }
                   86464: 
                   86465:         PEAR::popErrorHandling();
                   86466:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   86467:             if (is_array($pinfo['dp'])) {
                   86468:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   86469:                                     'package' => trim($pinfo['dp']['_content']));
                   86470:             } else {
                   86471:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   86472:                                     'package' => trim($pinfo['dp']));
                   86473:             }
                   86474:         } else {
                   86475:             $deprecated = false;
                   86476:         }
                   86477: 
                   86478:         if (!isset($latest)) {
                   86479:             $latest = '';
                   86480:         }
                   86481: 
                   86482:         return array(
                   86483:             'name' => $pinfo['n'],
                   86484:             'channel' => $pinfo['c'],
                   86485:             'category' => $pinfo['ca']['_content'],
                   86486:             'stable' => $latest,
                   86487:             'license' => $pinfo['l'],
                   86488:             'summary' => $pinfo['s'],
                   86489:             'description' => $pinfo['d'],
                   86490:             'releases' => $releases,
                   86491:             'deprecated' => $deprecated,
                   86492:             );
                   86493:     }
                   86494: 
                   86495:     /**
                   86496:      * Return an array containing all of the states that are more stable than
                   86497:      * or equal to the passed in state
                   86498:      *
                   86499:      * @param string Release state
                   86500:      * @param boolean Determines whether to include $state in the list
                   86501:      * @return false|array False if $state is not a valid release state
                   86502:      */
                   86503:     function betterStates($state, $include = false)
                   86504:     {
                   86505:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   86506:         $i = array_search($state, $states);
                   86507:         if ($i === false) {
                   86508:             return false;
                   86509:         }
                   86510: 
                   86511:         if ($include) {
                   86512:             $i--;
                   86513:         }
                   86514: 
                   86515:         return array_slice($states, $i + 1);
                   86516:     }
                   86517: 
                   86518:     /**
                   86519:      * Sort releases by version number
                   86520:      *
                   86521:      * @access private
                   86522:      */
                   86523:     function _sortReleasesByVersionNumber($a, $b)
                   86524:     {
                   86525:         if (version_compare($a['v'], $b['v'], '=')) {
                   86526:             return 0;
                   86527:         }
                   86528: 
                   86529:         if (version_compare($a['v'], $b['v'], '>')) {
                   86530:             return -1;
                   86531:         }
                   86532: 
                   86533:         if (version_compare($a['v'], $b['v'], '<')) {
                   86534:             return 1;
                   86535:         }
                   86536:     }
                   86537: }<?php
                   86538: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   86539: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   86540: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
                   86541: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command.php';
                   86542: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   86543: class PEAR_Start extends PEAR
                   86544: {
                   86545:     var $bin_dir;
                   86546:     var $data_dir;
                   86547:     var $cfg_dir;
                   86548:     var $www_dir;
                   86549:     var $install_pfc;
                   86550:     var $corePackages =
                   86551:         array(
                   86552:             'Archive_Tar',
                   86553:             'Console_Getopt',
                   86554:             'PEAR',
                   86555:             'Structures_Graph',
                   86556:             'XML_Util',
                   86557:         );
                   86558:     var $local_dir = array();
                   86559:     var $origpwd;
                   86560:     var $pfc_packages = array(
                   86561:             'DB',
                   86562:             'Net_Socket',
                   86563:             'Net_SMTP',
                   86564:             'Mail',
                   86565:             'XML_Parser',
                   86566:             'XML_RPC',
                   86567:             'PHPUnit'
                   86568:         );
                   86569:     var $php_dir;
                   86570:     var $php_bin;
                   86571:     var $pear_conf;
                   86572:     var $validPHPBin = false;
                   86573:     var $test_dir;
                   86574:     var $download_dir;
                   86575:     var $temp_dir;
                   86576:     var $config =
                   86577:         array(
                   86578:             'prefix',
                   86579:             'bin_dir',
                   86580:             'php_dir',
                   86581:             'doc_dir',
                   86582:             'data_dir',
                   86583:             'cfg_dir',
                   86584:             'www_dir',
                   86585:             'test_dir',
                   86586:             'temp_dir',
                   86587:             'download_dir',
                   86588:             'pear_conf',
                   86589:         );
                   86590:     var $prefix;
                   86591:     var $progress = 0;
                   86592:     var $configPrompt =
                   86593:         array(
                   86594:             'prefix' => 'Installation base ($prefix)',
                   86595:             'temp_dir' => 'Temporary directory for processing',
                   86596:             'download_dir' => 'Temporary directory for downloads',
                   86597:             'bin_dir' => 'Binaries directory',
                   86598:             'php_dir' => 'PHP code directory ($php_dir)',
                   86599:             'doc_dir' => 'Documentation directory',
                   86600:             'data_dir' => 'Data directory',
                   86601:             'cfg_dir' => 'User-modifiable configuration files directory',
                   86602:             'www_dir' => 'Public Web Files directory',
                   86603:             'test_dir' => 'Tests directory',
                   86604:             'pear_conf' => 'Name of configuration file',
                   86605:         );
                   86606: 
                   86607:     var $localInstall;
                   86608:     var $PEARConfig;
                   86609:     var $tarball = array();
                   86610: 
                   86611:     function PEAR_Start()
                   86612:     {
                   86613:         parent::PEAR();
                   86614:         if (OS_WINDOWS) {
                   86615:             $this->configPrompt['php_bin'] = 'Path to CLI php.exe';
                   86616:             $this->config[] = 'php_bin';
                   86617:             $this->prefix = getcwd();
                   86618: 
                   86619:             if (!@is_dir($this->prefix)) {
                   86620:                 if (@is_dir('c:\php5')) {
                   86621:                     $this->prefix = 'c:\php5';
                   86622:                 } elseif (@is_dir('c:\php4')) {
                   86623:                     $this->prefix = 'c:\php4';
                   86624:                 } elseif (@is_dir('c:\php')) {
                   86625:                     $this->prefix = 'c:\php';
                   86626:                 }
                   86627:             }
                   86628: 
                   86629:             $slash = "\\";
                   86630:             if (strrpos($this->prefix, '\\') === (strlen($this->prefix) - 1)) {
                   86631:                 $slash = '';
                   86632:             }
                   86633: 
                   86634:             $this->localInstall = false;
                   86635:             $this->bin_dir   = '$prefix';
                   86636:             $this->temp_dir   = '$prefix' . $slash . 'tmp';
                   86637:             $this->download_dir   = '$prefix' . $slash . 'tmp';
                   86638:             $this->php_dir   = '$prefix' . $slash . 'pear';
                   86639:             $this->doc_dir   = '$prefix' . $slash . 'docs';
                   86640:             $this->data_dir  = '$prefix' . $slash . 'data';
                   86641:             $this->test_dir  = '$prefix' . $slash . 'tests';
                   86642:             $this->www_dir  = '$prefix' . $slash . 'www';
                   86643:             $this->cfg_dir  = '$prefix' . $slash . 'cfg';
                   86644:             $this->pear_conf = PEAR_CONFIG_SYSCONFDIR . '\\pear.ini';
                   86645:             /*
                   86646:              * Detects php.exe
                   86647:              */
                   86648:             $this->validPHPBin = true;
                   86649:             if ($t = $this->safeGetenv('PHP_PEAR_PHP_BIN')) {
                   86650:                 $this->php_bin   = dirname($t);
                   86651:             } elseif ($t = $this->safeGetenv('PHP_BIN')) {
                   86652:                 $this->php_bin   = dirname($t);
                   86653:             } elseif ($t = System::which('php')) {
                   86654:                 $this->php_bin = dirname($t);
                   86655:             } elseif (is_file($this->prefix . '\cli\php.exe')) {
                   86656:                 $this->php_bin = $this->prefix . '\cli';
                   86657:             } elseif (is_file($this->prefix . '\php.exe')) {
                   86658:                 $this->php_bin = $this->prefix;
                   86659:             }
                   86660:             $phpexe = OS_WINDOWS ? '\\php.exe' : '/php';
                   86661:             if ($this->php_bin && !is_file($this->php_bin . $phpexe)) {
                   86662:                 $this->php_bin = '';
                   86663:             } else {
                   86664:                 if (strpos($this->php_bin, ':') === 0) {
                   86665:                     $this->php_bin = getcwd() . DIRECTORY_SEPARATOR . $this->php_bin;
                   86666:                 }
                   86667:             }
                   86668:             if (!is_file($this->php_bin . $phpexe)) {
                   86669:                 if (is_file('c:/php/cli/php.exe')) {
                   86670:                     $this->php_bin = 'c"\\php\\cli';
                   86671:                 } elseif (is_file('c:/php5/php.exe')) {
                   86672:                     $this->php_bin = 'c:\\php5';
                   86673:                 } elseif (is_file('c:/php4/cli/php.exe')) {
                   86674:                     $this->php_bin = 'c:\\php4\\cli';
                   86675:                 } else {
                   86676:                     $this->validPHPBin = false;
                   86677:                 }
                   86678:             }
                   86679:         } else {
                   86680:             $this->prefix = dirname(PHP_BINDIR);
                   86681:             $this->pear_conf = PEAR_CONFIG_SYSCONFDIR . '/pear.conf';
                   86682:             if (get_current_user() != 'root') {
                   86683:                 $this->prefix = $this->safeGetenv('HOME') . '/pear';
                   86684:                 $this->pear_conf = $this->safeGetenv('HOME') . '.pearrc';
                   86685:             }
                   86686:             $this->bin_dir   = '$prefix/bin';
                   86687:             $this->php_dir   = '$prefix/share/pear';
                   86688:             $this->temp_dir  = '/tmp/pear/install';
                   86689:             $this->download_dir  = '/tmp/pear/install';
                   86690:             $this->doc_dir   = '$prefix/docs';
                   86691:             $this->www_dir   = '$prefix/www';
                   86692:             $this->cfg_dir   = '$prefix/cfg';
                   86693:             $this->data_dir  = '$prefix/data';
                   86694:             $this->test_dir  = '$prefix/tests';
                   86695:             // check if the user has installed PHP with PHP or GNU layout
                   86696:             if (@is_dir("$this->prefix/lib/php/.registry")) {
                   86697:                 $this->php_dir = '$prefix/lib/php';
                   86698:             } elseif (@is_dir("$this->prefix/share/pear/lib/.registry")) {
                   86699:                 $this->php_dir = '$prefix/share/pear/lib';
                   86700:                 $this->doc_dir   = '$prefix/share/pear/docs';
                   86701:                 $this->data_dir  = '$prefix/share/pear/data';
                   86702:                 $this->test_dir  = '$prefix/share/pear/tests';
                   86703:             } elseif (@is_dir("$this->prefix/share/php/.registry")) {
                   86704:                 $this->php_dir = '$prefix/share/php';
                   86705:             }
                   86706:         }
                   86707:     }
                   86708: 
                   86709:     function safeGetenv($var)
                   86710:     {
                   86711:         if (is_array($_ENV) && isset($_ENV[$var])) {
                   86712:             return $_ENV[$var];
                   86713:         }
                   86714: 
                   86715:         return getenv($var);
                   86716:     }
                   86717: 
                   86718:     function show($stuff)
                   86719:     {
                   86720:         print $stuff;
                   86721:     }
                   86722: 
                   86723:     function locatePackagesToInstall()
                   86724:     {
                   86725:         $dp = @opendir(dirname(__FILE__) . '/go-pear-tarballs');
                   86726:         if (empty($dp)) {
                   86727:             return PEAR::raiseError("while locating packages to install: opendir('" .
                   86728:                 dirname(__FILE__) . "/go-pear-tarballs') failed");
                   86729:         }
                   86730: 
                   86731:         $potentials = array();
                   86732:         while (false !== ($entry = readdir($dp))) {
                   86733:             if ($entry{0} == '.' || !in_array(substr($entry, -4), array('.tar', '.tgz'))) {
                   86734:                 continue;
                   86735:             }
                   86736:             $potentials[] = $entry;
                   86737:         }
                   86738: 
                   86739:         closedir($dp);
                   86740:         $notfound = array();
                   86741:         foreach ($this->corePackages as $package) {
                   86742:             foreach ($potentials as $i => $candidate) {
                   86743:                 if (preg_match('/^' . $package . '-' . _PEAR_COMMON_PACKAGE_VERSION_PREG
                   86744:                       . '\.(tar|tgz)\\z/', $candidate)) {
                   86745:                     $this->tarball[$package] = dirname(__FILE__) . '/go-pear-tarballs/' . $candidate;
                   86746:                     unset($potentials[$i]);
                   86747:                     continue 2;
                   86748:                 }
                   86749:             }
                   86750: 
                   86751:             $notfound[] = $package;
                   86752:         }
                   86753: 
                   86754:         if (count($notfound)) {
                   86755:             return PEAR::raiseError("No tarballs found for core packages: " .
                   86756:                     implode(', ', $notfound));
                   86757:         }
                   86758: 
                   86759:         $this->tarball = array_merge($this->tarball, $potentials);
                   86760:     }
                   86761: 
                   86762:     function setupTempStuff()
                   86763:     {
                   86764:         if (!($this->ptmp = System::mktemp(array('-d')))) {
                   86765:             $this->show("System's Tempdir failed, trying to use \$prefix/tmp ...");
                   86766:             $res = System::mkDir(array($this->prefix . '/tmp'));
                   86767:             if (!$res) {
                   86768:                 return PEAR::raiseError('mkdir ' . $this->prefix . '/tmp ... failed');
                   86769:             }
                   86770: 
                   86771:             $_temp = tempnam($this->prefix . '/tmp', 'gope');
                   86772:             System::rm(array('-rf', $_temp));
                   86773:             System::mkdir(array('-p','-m', '0700', $_temp));
                   86774:             $this->ptmp = $this->prefix . '/tmp';
                   86775:             $ok = @chdir($this->ptmp);
                   86776: 
                   86777:             if (!$ok) { // This should not happen, really ;)
                   86778:                 $this->bail('chdir ' . $this->ptmp . ' ... failed');
                   86779:             }
                   86780: 
                   86781:             print "ok\n";
                   86782: 
                   86783:             // Adjust TEMPDIR envvars
                   86784:             if (!isset($_ENV)) {
                   86785:                 $_ENV = array();
                   86786:             };
                   86787:             $_ENV['TMPDIR'] = $_ENV['TEMP'] = $this->prefix . '/tmp';
                   86788:         }
                   86789: 
                   86790:         return @chdir($this->ptmp);
                   86791:     }
                   86792: 
                   86793:     /**
                   86794:      * Try to detect the kind of SAPI used by the
                   86795:      * the given php.exe.
                   86796:      * @author Pierrre-Alain Joye
                   86797:      */
                   86798:     function win32DetectPHPSAPI()
                   86799:     {
                   86800:         if ($this->php_bin != '') {
                   86801:             if (OS_WINDOWS) {
                   86802:                 exec('"' . $this->php_bin . '\\php.exe" -v', $res);
                   86803:             } else {
                   86804:                 exec('"' . $this->php_bin . '/php" -v', $res);
                   86805:             }
                   86806: 
                   86807:             if (is_array($res)) {
                   86808:                 if (isset($res[0]) && strpos($res[0],"(cli)")) {
                   86809:                     return 'cli';
                   86810:                 }
                   86811: 
                   86812:                 if (isset($res[0]) && strpos($res[0],"cgi")) {
                   86813:                     return 'cgi';
                   86814:                 }
                   86815: 
                   86816:                 if (isset($res[0]) && strpos($res[0],"cgi-fcgi")) {
                   86817:                     return 'cgi';
                   86818:                 }
                   86819: 
                   86820:                 return 'unknown';
                   86821:             }
                   86822:         }
                   86823: 
                   86824:         return 'unknown';
                   86825:     }
                   86826: 
                   86827:     function doInstall()
                   86828:     {
                   86829:         print "Beginning install...\n";
                   86830:         // finish php_bin config
                   86831:         if (OS_WINDOWS) {
                   86832:             $this->php_bin .= '\\php.exe';
                   86833:         } else {
                   86834:             $this->php_bin .= '/php';
                   86835:         }
                   86836:         $this->PEARConfig = &PEAR_Config::singleton($this->pear_conf, $this->pear_conf);
                   86837:         $this->PEARConfig->set('preferred_state', 'stable');
                   86838:         foreach ($this->config as $var) {
                   86839:             if ($var == 'pear_conf' || $var == 'prefix') {
                   86840:                 continue;
                   86841:             }
                   86842:             $this->PEARConfig->set($var, $this->$var);
                   86843:         }
                   86844: 
                   86845:         $this->PEARConfig->store();
                   86846: //       $this->PEARConfig->set('verbose', 6);
                   86847:         print "Configuration written to $this->pear_conf...\n";
                   86848:         $this->registry = &$this->PEARConfig->getRegistry();
                   86849:         print "Initialized registry...\n";
                   86850:         $install = &PEAR_Command::factory('install', $this->PEARConfig);
                   86851:         print "Preparing to install...\n";
                   86852:         $options = array(
                   86853:             'nodeps' => true,
                   86854:             'force' => true,
                   86855:             'upgrade' => true,
                   86856:             );
                   86857:         foreach ($this->tarball as $pkg => $src) {
                   86858:             print "installing $src...\n";
                   86859:         }
                   86860:         $install->run('install', $options, array_values($this->tarball));
                   86861:     }
                   86862: 
                   86863:     function postProcessConfigVars()
                   86864:     {
                   86865:         foreach ($this->config as $n => $var) {
                   86866:             for ($m = 1; $m <= count($this->config); $m++) {
                   86867:                 $var2 = $this->config[$m];
                   86868:                 $this->$var = str_replace('$'.$var2, $this->$var2, $this->$var);
                   86869:             }
                   86870:         }
                   86871: 
                   86872:         foreach ($this->config as $var) {
                   86873:             $dir = $this->$var;
                   86874: 
                   86875:             if (!preg_match('/_dir\\z/', $var)) {
                   86876:                 continue;
                   86877:             }
                   86878: 
                   86879:             if (!@is_dir($dir)) {
                   86880:                 if (!System::mkDir(array('-p', $dir))) {
                   86881:                     $root = OS_WINDOWS ? 'administrator' : 'root';
                   86882:                     return PEAR::raiseError("Unable to create {$this->configPrompt[$var]} $dir.
                   86883: Run this script as $root or pick another location.\n");
                   86884:                 }
                   86885:             }
                   86886:         }
                   86887:     }
                   86888: 
                   86889:     /**
                   86890:      * Get the php.ini file used with the current
                   86891:      * process or with the given php.exe
                   86892:      *
                   86893:      * Horrible hack, but well ;)
                   86894:      *
                   86895:      * Not used yet, will add the support later
                   86896:      * @author Pierre-Alain Joye <paj@pearfr.org>
                   86897:      */
                   86898:     function getPhpiniPath()
                   86899:     {
                   86900:         $pathIni = get_cfg_var('cfg_file_path');
                   86901:         if ($pathIni && is_file($pathIni)) {
                   86902:             return $pathIni;
                   86903:         }
                   86904: 
                   86905:         // Oh well, we can keep this too :)
                   86906:         // I dunno if get_cfg_var() is safe on every OS
                   86907:         if (OS_WINDOWS) {
                   86908:             // on Windows, we can be pretty sure that there is a php.ini
                   86909:             // file somewhere
                   86910:             do {
                   86911:                 $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini';
                   86912:                 if (@file_exists($php_ini)) {
                   86913:                     break;
                   86914:                 }
                   86915:                 $php_ini = 'c:\winnt\php.ini';
                   86916:                 if (@file_exists($php_ini)) {
                   86917:                     break;
                   86918:                 }
                   86919:                 $php_ini = 'c:\windows\php.ini';
                   86920:             } while (false);
                   86921:         } else {
                   86922:             $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini';
                   86923:         }
                   86924: 
                   86925:         if (@is_file($php_ini)) {
                   86926:             return $php_ini;
                   86927:         }
                   86928: 
                   86929:         // We re running in hackz&troubles :)
                   86930:         ob_implicit_flush(false);
                   86931:         ob_start();
                   86932:         phpinfo(INFO_GENERAL);
                   86933:         $strInfo = ob_get_contents();
                   86934:         ob_end_clean();
                   86935:         ob_implicit_flush(true);
                   86936: 
                   86937:         if (php_sapi_name() != 'cli') {
                   86938:             $strInfo = strip_tags($strInfo,'<td>');
                   86939:             $arrayInfo = explode("</td>", $strInfo );
                   86940:             $cli = false;
                   86941:         } else {
                   86942:             $arrayInfo = explode("\n", $strInfo);
                   86943:             $cli = true;
                   86944:         }
                   86945: 
                   86946:         foreach ($arrayInfo as $val) {
                   86947:             if (strpos($val,"php.ini")) {
                   86948:                 if ($cli) {
                   86949:                     list(,$pathIni) = explode('=>', $val);
                   86950:                 } else {
                   86951:                     $pathIni = strip_tags(trim($val));
                   86952:                 }
                   86953:                 $pathIni = trim($pathIni);
                   86954:                 if (is_file($pathIni)) {
                   86955:                     return $pathIni;
                   86956:                 }
                   86957:             }
                   86958:         }
                   86959: 
                   86960:         return false;
                   86961:     }
                   86962: }
                   86963: ?>
                   86964: <?php
                   86965: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Start.php';
                   86966: class PEAR_Start_CLI extends PEAR_Start
                   86967: {
                   86968: 
                   86969:     var $descLength;
                   86970:     var $descFormat;
                   86971:     var $first;
                   86972:     var $last;
                   86973:     var $origpwd;
                   86974:     var $tty;
                   86975: 
                   86976:     function PEAR_Start_CLI()
                   86977:     {
                   86978:         parent::PEAR_Start();
                   86979:         ini_set('html_errors', 0);
                   86980:         define('WIN32GUI', OS_WINDOWS && php_sapi_name() == 'cli' && System::which('cscript'));
                   86981:         $this->tty = OS_WINDOWS ? @fopen('\con', 'r') : @fopen('/dev/tty', 'r');
                   86982: 
                   86983:         if (!$this->tty) {
                   86984:             $this->tty = fopen('php://stdin', 'r');
                   86985:         }
                   86986:         $this->origpwd = getcwd();
                   86987:         $this->config = array_keys($this->configPrompt);
                   86988: 
                   86989:         // make indices run from 1...
                   86990:         array_unshift($this->config, "");
                   86991:         unset($this->config[0]);
                   86992:         reset($this->config);
                   86993:         $this->descLength = max(array_map('strlen', $this->configPrompt));
                   86994:         $this->descFormat = "%-{$this->descLength}s";
                   86995:         $this->first = key($this->config);
                   86996:         end($this->config);
                   86997:         $this->last = key($this->config);
                   86998:         PEAR_Command::setFrontendType('CLI');
                   86999:     }
                   87000: 
                   87001:     function _PEAR_Start_CLI()
                   87002:     {
                   87003:         if ($this->tty) {
                   87004:             @fclose($this->tty);
                   87005:         }
                   87006:     }
                   87007: 
                   87008:     function run()
                   87009:     {
                   87010:         if (PEAR::isError($err = $this->locatePackagesToInstall())) {
                   87011:             return $err;
                   87012:         }
                   87013:         $this->startupQuestion();
                   87014:         $this->setupTempStuff();
                   87015:         $this->getInstallLocations();
                   87016:         $this->displayPreamble();
                   87017:         if (PEAR::isError($err = $this->postProcessConfigVars())) {
                   87018:             return $err;
                   87019:         }
                   87020:         $this->doInstall();
                   87021:         $this->finishInstall();
                   87022:     }
                   87023: 
                   87024:     function startupQuestion()
                   87025:     {
                   87026:         if (OS_WINDOWS) {
                   87027:             print "
                   87028: Are you installing a system-wide PEAR or a local copy?
                   87029: (system|local) [system] : ";
                   87030:             $tmp = trim(fgets($this->tty, 1024));
                   87031:             if (!empty($tmp) && strtolower($tmp) !== 'system') {
                   87032:                 print "Please confirm local copy by typing 'yes' : ";
                   87033:                 $tmp = trim(fgets($this->tty, 1024));
                   87034:                 if (strtolower($tmp) == 'yes') {
                   87035:                     $slash = "\\";
                   87036:                     if (strrpos($this->prefix, '\\') === (strlen($this->prefix) - 1)) {
                   87037:                         $slash = '';
                   87038:                     }
                   87039: 
                   87040:                     $this->localInstall = true;
                   87041:                     $this->pear_conf = '$prefix' . $slash . 'pear.ini';
                   87042:                 }
                   87043:             }
                   87044:         } else {
                   87045:             if (get_current_user() == 'root') {
                   87046:                 return;
                   87047:             }
                   87048:             $this->pear_conf = $this->safeGetenv('HOME') . '/.pearrc';
                   87049:         }
                   87050:     }
                   87051: 
                   87052:     function getInstallLocations()
                   87053:     {
                   87054:         while (true) {
                   87055:             print "
                   87056: Below is a suggested file layout for your new PEAR installation.  To
                   87057: change individual locations, type the number in front of the
                   87058: directory.  Type 'all' to change all of them or simply press Enter to
                   87059: accept these locations.
                   87060: 
                   87061: ";
                   87062: 
                   87063:             foreach ($this->config as $n => $var) {
                   87064:                 $fullvar = $this->$var;
                   87065:                 foreach ($this->config as $blah => $unused) {
                   87066:                     foreach ($this->config as $m => $var2) {
                   87067:                         $fullvar = str_replace('$'.$var2, $this->$var2, $fullvar);
                   87068:                     }
                   87069:                 }
                   87070:                 printf("%2d. $this->descFormat : %s\n", $n, $this->configPrompt[$var], $fullvar);
                   87071:             }
                   87072: 
                   87073:             print "\n$this->first-$this->last, 'all' or Enter to continue: ";
                   87074:             $tmp = trim(fgets($this->tty, 1024));
                   87075:             if (empty($tmp)) {
                   87076:                 if (OS_WINDOWS && !$this->validPHPBin) {
                   87077:                     echo "**ERROR**
                   87078: Please, enter the php.exe path.
                   87079: 
                   87080: ";
                   87081:                 } else {
                   87082:                     break;
                   87083:                 }
                   87084:             }
                   87085: 
                   87086:             if (isset($this->config[(int)$tmp])) {
                   87087:                 $var = $this->config[(int)$tmp];
                   87088:                 $desc = $this->configPrompt[$var];
                   87089:                 $current = $this->$var;
                   87090:                 if (WIN32GUI && $var != 'pear_conf'){
                   87091:                     $tmp = $this->win32BrowseForFolder("Choose a Folder for $desc [$current] :");
                   87092:                     $tmp.= '\\';
                   87093:                 } else {
                   87094:                     print "(Use \$prefix as a shortcut for '$this->prefix', etc.)
                   87095: $desc [$current] : ";
                   87096:                     $tmp = trim(fgets($this->tty, 1024));
                   87097:                 }
                   87098:                 $old = $this->$var;
                   87099:                 $this->$var = $$var = $tmp;
                   87100:                 if (OS_WINDOWS && $var=='php_bin') {
                   87101:                     if ($this->validatePhpExecutable($tmp)) {
                   87102:                         $this->php_bin = $tmp;
                   87103:                     } else {
                   87104:                         $this->php_bin = $old;
                   87105:                     }
                   87106:                 }
                   87107:             } elseif ($tmp == 'all') {
                   87108:                 foreach ($this->config as $n => $var) {
                   87109:                     $desc = $this->configPrompt[$var];
                   87110:                     $current = $this->$var;
                   87111:                     print "$desc [$current] : ";
                   87112:                     $tmp = trim(fgets($this->tty, 1024));
                   87113:                     if (!empty($tmp)) {
                   87114:                         $this->$var = $tmp;
                   87115:                     }
                   87116:                 }
                   87117:             }
                   87118:         }
                   87119:     }
                   87120: 
                   87121:     function validatePhpExecutable($tmp)
                   87122:     {
                   87123:         if (OS_WINDOWS) {
                   87124:             if (strpos($tmp, 'php.exe')) {
                   87125:                 $tmp = str_replace('php.exe', '', $tmp);
                   87126:             }
                   87127:             if (file_exists($tmp . DIRECTORY_SEPARATOR . 'php.exe')) {
                   87128:                 $tmp = $tmp . DIRECTORY_SEPARATOR . 'php.exe';
                   87129:                 $this->php_bin_sapi = $this->win32DetectPHPSAPI();
                   87130:                 if ($this->php_bin_sapi=='cgi'){
                   87131:                     print "
                   87132: ******************************************************************************
                   87133: NOTICE! We found php.exe under $this->php_bin, it uses a $this->php_bin_sapi SAPI.
                   87134: PEAR commandline tool works well with it.
                   87135: If you have a CLI php.exe available, we recommend using it.
                   87136: 
                   87137: Press Enter to continue...";
                   87138:                     $tmp = trim(fgets($this->tty, 1024));
                   87139:                 } elseif ($this->php_bin_sapi=='unknown') {
                   87140:                     print "
                   87141: ******************************************************************************
                   87142: WARNING! We found php.exe under $this->php_bin, it uses an $this->php_bin_sapi SAPI.
                   87143: PEAR commandline tool has NOT been tested with it.
                   87144: If you have a CLI (or CGI) php.exe available, we strongly recommend using it.
                   87145: 
                   87146: Press Enter to continue...";
                   87147:                     $tmp = trim(fgets($this->tty, 1024));
                   87148:                 }
                   87149:                 echo "php.exe (sapi: $this->php_bin_sapi) found.\n\n";
                   87150:                 return $this->validPHPBin = true;
                   87151:             } else {
                   87152:                 echo "**ERROR**: not a folder, or no php.exe found in this folder.
                   87153: Press Enter to continue...";
                   87154:                 $tmp = trim(fgets($this->tty, 1024));
                   87155:                 return $this->validPHPBin = false;
                   87156:             }
                   87157:         }
                   87158:     }
                   87159: 
                   87160:     /**
                   87161:      * Create a vbs script to browse the getfolder dialog, called
                   87162:      * by cscript, if it's available.
                   87163:      * $label is the label text in the header of the dialog box
                   87164:      *
                   87165:      * TODO:
                   87166:      * - Do not show Control panel
                   87167:      * - Replace WSH with calls to w32 as soon as callbacks work
                   87168:      * @author Pierrre-Alain Joye
                   87169:      */
                   87170:     function win32BrowseForFolder($label)
                   87171:     {
                   87172:         static $wshSaved=false;
                   87173:         static $cscript='';
                   87174:     $wsh_browserfolder = 'Option Explicit
                   87175: Dim ArgObj, var1, var2, sa, sFld
                   87176: Set ArgObj = WScript.Arguments
                   87177: Const BIF_EDITBOX = &H10
                   87178: Const BIF_NEWDIALOGSTYLE = &H40
                   87179: Const BIF_RETURNONLYFSDIRS   = &H0001
                   87180: Const BIF_DONTGOBELOWDOMAIN  = &H0002
                   87181: Const BIF_STATUSTEXT         = &H0004
                   87182: Const BIF_RETURNFSANCESTORS  = &H0008
                   87183: Const BIF_VALIDATE           = &H0020
                   87184: Const BIF_BROWSEFORCOMPUTER  = &H1000
                   87185: Const BIF_BROWSEFORPRINTER   = &H2000
                   87186: Const BIF_BROWSEINCLUDEFILES = &H4000
                   87187: Const OFN_LONGNAMES = &H200000
                   87188: Const OFN_NOLONGNAMES = &H40000
                   87189: Const ssfDRIVES = &H11
                   87190: Const ssfNETWORK = &H12
                   87191: Set sa = CreateObject("Shell.Application")
                   87192: var1=ArgObj(0)
                   87193: Set sFld = sa.BrowseForFolder(0, var1, BIF_EDITBOX + BIF_VALIDATE + BIF_BROWSEINCLUDEFILES + BIF_RETURNFSANCESTORS+BIF_NEWDIALOGSTYLE , ssfDRIVES )
                   87194: if not sFld is nothing Then
                   87195:     if not left(sFld.items.item.path,1)=":" Then
                   87196:         WScript.Echo sFld.items.item.path
                   87197:     Else
                   87198:         WScript.Echo "invalid"
                   87199:     End If
                   87200: Else
                   87201:     WScript.Echo "cancel"
                   87202: End If
                   87203: ';
                   87204:         if( !$wshSaved){
                   87205:             $cscript = $this->ptmp . DIRECTORY_SEPARATOR . "bf.vbs";
                   87206:             $fh = fopen($cscript, "wb+");
                   87207:             fwrite($fh, $wsh_browserfolder, strlen($wsh_browserfolder));
                   87208:             fclose($fh);
                   87209:             $wshSaved  = true;
                   87210:         }
                   87211: 
                   87212:         exec('cscript ' . escapeshellarg($cscript) . ' "' . escapeshellarg($label) . '" //noLogo', $arPath);
                   87213:         if (!count($arPath) || $arPath[0]=='' || $arPath[0]=='cancel') {
                   87214:             return '';
                   87215:         } elseif ($arPath[0]=='invalid') {
                   87216:             echo "Invalid Path.\n";
                   87217:             return '';
                   87218:         }
                   87219: 
                   87220:         @unlink($cscript);
                   87221:         return $arPath[0];
                   87222:     }
                   87223: 
                   87224:     function displayPreamble()
                   87225:     {
                   87226:         if (OS_WINDOWS) {
                   87227:             /*
                   87228:              * Checks PHP SAPI version under windows/CLI
                   87229:              */
                   87230:             if ($this->php_bin == '') {
                   87231:                 print "
                   87232: We did not find any php.exe, please select the php.exe folder (CLI is
                   87233: recommended, usually in c:\php\cli\php.exe)
                   87234: ";
                   87235:                 $this->validPHPBin = false;
                   87236:             } elseif (strlen($this->php_bin)) {
                   87237:                 $this->php_bin_sapi = $this->win32DetectPHPSAPI();
                   87238:                 $this->validPHPBin = true;
                   87239:                 switch ($this->php_bin_sapi) {
                   87240:                     case 'cli':
                   87241:                     break;
                   87242:                     case 'cgi':
                   87243:                     case 'cgi-fcgi':
                   87244:                         print "
                   87245: *NOTICE*
                   87246: We found php.exe under $this->php_bin, it uses a $this->php_bin_sapi SAPI. PEAR commandline
                   87247: tool works well with it, if you have a CLI php.exe available, we
                   87248: recommend using it.
                   87249: ";
                   87250:                     break;
                   87251:                     default:
                   87252:                         print "
                   87253: *WARNING*
                   87254: We found php.exe under $this->php_bin, it uses an unknown SAPI. PEAR commandline
                   87255: tool has not been tested with it, if you have a CLI (or CGI) php.exe available,
                   87256: we strongly recommend using it.
                   87257: 
                   87258: ";
                   87259:                     break;
                   87260:                 }
                   87261:             }
                   87262:         }
                   87263:     }
                   87264: 
                   87265:     function finishInstall()
                   87266:     {
                   87267:         $sep = OS_WINDOWS ? ';' : ':';
                   87268:         $include_path = explode($sep, ini_get('include_path'));
                   87269:         if (OS_WINDOWS) {
                   87270:             $found = false;
                   87271:             $t = strtolower($this->php_dir);
                   87272:             foreach ($include_path as $path) {
                   87273:                 if ($t == strtolower($path)) {
                   87274:                     $found = true;
                   87275:                     break;
                   87276:                 }
                   87277:             }
                   87278:         } else {
                   87279:             $found = in_array($this->php_dir, $include_path);
                   87280:         }
                   87281:         if (!$found) {
                   87282:             print "
                   87283: ******************************************************************************
                   87284: WARNING!  The include_path defined in the currently used php.ini does not
                   87285: contain the PEAR PHP directory you just specified:
                   87286: <$this->php_dir>
                   87287: If the specified directory is also not in the include_path used by
                   87288: your scripts, you will have problems getting any PEAR packages working.
                   87289: ";
                   87290: 
                   87291:             if ($php_ini = $this->getPhpiniPath()) {
                   87292:                 print "\n\nWould you like to alter php.ini <$php_ini>? [Y/n] : ";
                   87293:                 $alter_phpini = !stristr(fgets($this->tty, 1024), "n");
                   87294:                 if ($alter_phpini) {
                   87295:                     $this->alterPhpIni($php_ini);
                   87296:                 } else {
                   87297:                     if (OS_WINDOWS) {
                   87298:                         print "
                   87299: Please look over your php.ini file to make sure
                   87300: $this->php_dir is in your include_path.";
                   87301:                     } else {
                   87302:                         print "
                   87303: I will add a workaround for this in the 'pear' command to make sure
                   87304: the installer works, but please look over your php.ini or Apache
                   87305: configuration to make sure $this->php_dir is in your include_path.
                   87306: ";
                   87307:                     }
                   87308:                 }
                   87309:             }
                   87310: 
                   87311:         print "
                   87312: Current include path           : ".ini_get('include_path')."
                   87313: Configured directory           : $this->php_dir
                   87314: Currently used php.ini (guess) : $php_ini
                   87315: ";
                   87316: 
                   87317:             print "Press Enter to continue: ";
                   87318:             fgets($this->tty, 1024);
                   87319:         }
                   87320: 
                   87321:         $pear_cmd = $this->bin_dir . DIRECTORY_SEPARATOR . 'pear';
                   87322:         $pear_cmd = OS_WINDOWS ? strtolower($pear_cmd).'.bat' : $pear_cmd;
                   87323: 
                   87324:         // check that the installed pear and the one in the path are the same (if any)
                   87325:         $pear_old = System::which(OS_WINDOWS ? 'pear.bat' : 'pear', $this->bin_dir);
                   87326:         if ($pear_old && ($pear_old != $pear_cmd)) {
                   87327:             // check if it is a link or symlink
                   87328:             $islink = OS_WINDOWS ? false : is_link($pear_old) ;
                   87329:             if ($islink && readlink($pear_old) != $pear_cmd) {
                   87330:                 print "\n** WARNING! The link $pear_old does not point to the " .
                   87331:                       "installed $pear_cmd\n";
                   87332:             } elseif (!$this->localInstall && is_writable($pear_old) && !is_dir($pear_old)) {
                   87333:                 rename($pear_old, "{$pear_old}_old");
                   87334:                 print "\n** WARNING! Backed up old pear to {$pear_old}_old\n";
                   87335:             } else {
                   87336:                 print "\n** WARNING! Old version found at $pear_old, please remove it or ".
                   87337:                       "be sure to use the new $pear_cmd command\n";
                   87338:             }
                   87339:         }
                   87340: 
                   87341:         print "\nThe 'pear' command is now at your service at $pear_cmd\n";
                   87342: 
                   87343:         // Alert the user if the pear cmd is not in PATH
                   87344:         $old_dir = $pear_old ? dirname($pear_old) : false;
                   87345:         if (!$this->which('pear', $old_dir)) {
                   87346:             print "
                   87347: ** The 'pear' command is not currently in your PATH, so you need to
                   87348: ** use '$pear_cmd' until you have added
                   87349: ** '$this->bin_dir' to your PATH environment variable.
                   87350: 
                   87351: ";
                   87352: 
                   87353:         print "Run it without parameters to see the available actions, try 'pear list'
                   87354: to see what packages are installed, or 'pear help' for help.
                   87355: 
                   87356: For more information about PEAR, see:
                   87357: 
                   87358:   http://pear.php.net/faq.php
                   87359:   http://pear.php.net/manual/
                   87360: 
                   87361: Thanks for using go-pear!
                   87362: 
                   87363: ";
                   87364:         }
                   87365: 
                   87366:         if (OS_WINDOWS && !$this->localInstall) {
                   87367:             $this->win32CreateRegEnv();
                   87368:         }
                   87369:     }
                   87370: 
                   87371:     /**
                   87372:      * System::which() does not allow path exclusion
                   87373:      */
                   87374:     function which($program, $dont_search_in = false)
                   87375:     {
                   87376:         if (OS_WINDOWS) {
                   87377:             if ($_path = $this->safeGetEnv('Path')) {
                   87378:                 $dirs = explode(';', $_path);
                   87379:             } else {
                   87380:                 $dirs = explode(';', $this->safeGetEnv('PATH'));
                   87381:             }
                   87382:             foreach ($dirs as $i => $dir) {
                   87383:                 $dirs[$i] = strtolower(realpath($dir));
                   87384:             }
                   87385:             if ($dont_search_in) {
                   87386:                 $dont_search_in = strtolower(realpath($dont_search_in));
                   87387:             }
                   87388:             if ($dont_search_in &&
                   87389:                 ($key = array_search($dont_search_in, $dirs)) !== false)
                   87390:             {
                   87391:                 unset($dirs[$key]);
                   87392:             }
                   87393: 
                   87394:             foreach ($dirs as $dir) {
                   87395:                 $dir = str_replace('\\\\', '\\', $dir);
                   87396:                 if (!strlen($dir)) {
                   87397:                     continue;
                   87398:                 }
                   87399:                 if ($dir{strlen($dir) - 1} != '\\') {
                   87400:                     $dir .= '\\';
                   87401:                 }
                   87402:                 $tmp = $dir . $program;
                   87403:                 $info = pathinfo($tmp);
                   87404:                 if (isset($info['extension']) && in_array(strtolower($info['extension']),
                   87405:                       array('exe', 'com', 'bat', 'cmd'))) {
                   87406:                     if (file_exists($tmp)) {
                   87407:                         return strtolower($tmp);
                   87408:                     }
                   87409:                 } elseif (file_exists($ret = $tmp . '.exe') ||
                   87410:                     file_exists($ret = $tmp . '.com') ||
                   87411:                     file_exists($ret = $tmp . '.bat') ||
                   87412:                     file_exists($ret = $tmp . '.cmd')) {
                   87413:                     return strtolower($ret);
                   87414:                 }
                   87415:             }
                   87416:         } else {
                   87417:             $dirs = explode(':', $this->safeGetEnv('PATH'));
                   87418:             if ($dont_search_in &&
                   87419:                 ($key = array_search($dont_search_in, $dirs)) !== false)
                   87420:             {
                   87421:                 unset($dirs[$key]);
                   87422:             }
                   87423:             foreach ($dirs as $dir) {
                   87424:                 if (is_executable("$dir/$program")) {
                   87425:                     return "$dir/$program";
                   87426:                 }
                   87427:             }
                   87428:         }
                   87429:         return false;
                   87430:     }
                   87431: 
                   87432:     /**
                   87433:      * Not optimized, but seems to work, if some nice
                   87434:      * peardev will test it? :)
                   87435:      *
                   87436:      * @author Pierre-Alain Joye <paj@pearfr.org>
                   87437:      */
                   87438:     function alterPhpIni($pathIni='')
                   87439:     {
                   87440:         $foundAt = array();
                   87441:         $iniSep = OS_WINDOWS ? ';' : ':';
                   87442: 
                   87443:         if ($pathIni=='') {
                   87444:             $pathIni =  $this->getPhpiniPath();
                   87445:         }
                   87446: 
                   87447:         $arrayIni = file($pathIni);
                   87448:         $i=0;
                   87449:         $found=0;
                   87450: 
                   87451:         // Looks for each active include_path directives
                   87452:         foreach ($arrayIni as $iniLine) {
                   87453:             $iniLine = trim($iniLine);
                   87454:             $iniLine = str_replace(array("\n", "\r"), array('', ''), $iniLine);
                   87455:             if (preg_match("/^\s*include_path/", $iniLine)) {
                   87456:                 $foundAt[] = $i;
                   87457:                 $found++;
                   87458:             }
                   87459:             $i++;
                   87460:         }
                   87461: 
                   87462:         if ($found) {
                   87463:             $includeLine = $arrayIni[$foundAt[0]];
                   87464:             list(, $currentPath) = explode('=', $includeLine);
                   87465: 
                   87466:             $currentPath = trim($currentPath);
                   87467:             if (substr($currentPath,0,1) == '"') {
                   87468:                 $currentPath = substr($currentPath, 1, strlen($currentPath) - 2);
                   87469:             }
                   87470: 
                   87471:             $arrayPath = explode($iniSep, $currentPath);
                   87472:             $newPath = array();
                   87473:             if ($arrayPath[0]=='.') {
                   87474:                 $newPath[0] = '.';
                   87475:                 $newPath[1] = $this->php_dir;
                   87476:                 array_shift($arrayPath);
                   87477:             } else {
                   87478:                 $newPath[0] = $this->php_dir;
                   87479:             }
                   87480: 
                   87481:             foreach ($arrayPath as $path) {
                   87482:                 $newPath[]= $path;
                   87483:             }
                   87484:         } else {
                   87485:             $newPath = array();
                   87486:             $newPath[0] = '.';
                   87487:             $newPath[1] = $this->php_dir;
                   87488:             $foundAt[] = count($arrayIni); // add a new line if none is present
                   87489:         }
                   87490:         $nl = OS_WINDOWS ? "\r\n" : "\n";
                   87491:         $includepath = 'include_path="' . implode($iniSep,$newPath) . '"';
                   87492:         $newInclude = "$nl$nl;***** Added by go-pear$nl" .
                   87493:                        $includepath .
                   87494:                        $nl . ";*****" .
                   87495:                        $nl . $nl;
                   87496: 
                   87497:         $arrayIni[$foundAt[0]] = $newInclude;
                   87498: 
                   87499:         for ($i=1; $i<$found; $i++) {
                   87500:             $arrayIni[$foundAt[$i]]=';' . trim($arrayIni[$foundAt[$i]]);
                   87501:         }
                   87502: 
                   87503:         $newIni = implode("", $arrayIni);
                   87504:         if (!($fh = @fopen($pathIni, "wb+"))) {
                   87505:             $prefixIni = $this->prefix . DIRECTORY_SEPARATOR . "php.ini-gopear";
                   87506:             $fh = fopen($prefixIni, "wb+");
                   87507:             if (!$fh) {
                   87508:                 echo "
                   87509: ******************************************************************************
                   87510: WARNING: Cannot write to $pathIni nor in $this->prefix/php.ini-gopear. Please
                   87511: modify manually your php.ini by adding:
                   87512: 
                   87513: $includepath
                   87514: 
                   87515: ";
                   87516:                 return false;
                   87517:             } else {
                   87518:                 fwrite($fh, $newIni, strlen($newIni));
                   87519:                 fclose($fh);
                   87520:                 echo "
                   87521: ******************************************************************************
                   87522: WARNING: Cannot write to $pathIni, but php.ini was successfully created
                   87523: at <$this->prefix/php.ini-gopear>. Please replace the file <$pathIni> with
                   87524: <$prefixIni> or modify your php.ini by adding:
                   87525: 
                   87526: $includepath
                   87527: 
                   87528: ";
                   87529: 
                   87530:             }
                   87531:         } else {
                   87532:             fwrite($fh, $newIni, strlen($newIni));
                   87533:             fclose($fh);
                   87534:             echo "
                   87535: php.ini <$pathIni> include_path updated.
                   87536: ";
                   87537:         }
                   87538:         return true;
                   87539:     }
                   87540: 
                   87541:     /**
                   87542:      * Generates a registry addOn for Win32 platform
                   87543:      * This addon set PEAR environment variables
                   87544:      * @author Pierrre-Alain Joye
                   87545:      */
                   87546:     function win32CreateRegEnv()
                   87547:     {
                   87548:         $nl = "\r\n";
                   87549:         $reg ='REGEDIT4'.$nl.
                   87550:                 '[HKEY_CURRENT_USER\Environment]'. $nl .
                   87551:                 '"PHP_PEAR_SYSCONF_DIR"="' . addslashes($this->prefix) . '"' . $nl .
                   87552:                 '"PHP_PEAR_INSTALL_DIR"="' . addslashes($this->php_dir) . '"' . $nl .
                   87553:                 '"PHP_PEAR_DOC_DIR"="' . addslashes($this->doc_dir) . '"' . $nl .
                   87554:                 '"PHP_PEAR_BIN_DIR"="' . addslashes($this->bin_dir) . '"' . $nl .
                   87555:                 '"PHP_PEAR_DATA_DIR"="' . addslashes($this->data_dir) . '"' . $nl .
                   87556:                 '"PHP_PEAR_PHP_BIN"="' . addslashes($this->php_bin) . '"' . $nl .
                   87557:                 '"PHP_PEAR_TEST_DIR"="' . addslashes($this->test_dir) . '"' . $nl;
                   87558: 
                   87559:         $fh = fopen($this->prefix . DIRECTORY_SEPARATOR . 'PEAR_ENV.reg', 'wb');
                   87560:         if($fh){
                   87561:             fwrite($fh, $reg, strlen($reg));
                   87562:             fclose($fh);
                   87563:             echo "
                   87564: 
                   87565: * WINDOWS ENVIRONMENT VARIABLES *
                   87566: For convenience, a REG file is available under {$this->prefix}PEAR_ENV.reg .
                   87567: This file creates ENV variables for the current user.
                   87568: 
                   87569: Double-click this file to add it to the current user registry.
                   87570: 
                   87571: ";
                   87572:         }
                   87573:     }
                   87574: 
                   87575:     function displayHTMLProgress()
                   87576:     {
                   87577:     }
                   87578: }
                   87579: ?><?php
                   87580: /**
                   87581:  * PEAR_Task_Common, base class for installer tasks
                   87582:  *
                   87583:  * PHP versions 4 and 5
                   87584:  *
                   87585:  * @category   pear
                   87586:  * @package    PEAR
                   87587:  * @author     Greg Beaver <cellog@php.net>
                   87588:  * @copyright  1997-2009 The Authors
                   87589:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   87590:  * @version    CVS: $Id: Common.php 276394 2009-02-25 00:15:49Z dufuz $
                   87591:  * @link       http://pear.php.net/package/PEAR
                   87592:  * @since      File available since Release 1.4.0a1
                   87593:  */
                   87594: /**#@+
                   87595:  * Error codes for task validation routines
                   87596:  */
                   87597: define('PEAR_TASK_ERROR_NOATTRIBS', 1);
                   87598: define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
                   87599: define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
                   87600: define('PEAR_TASK_ERROR_INVALID', 4);
                   87601: /**#@-*/
                   87602: define('PEAR_TASK_PACKAGE', 1);
                   87603: define('PEAR_TASK_INSTALL', 2);
                   87604: define('PEAR_TASK_PACKAGEANDINSTALL', 3);
                   87605: /**
                   87606:  * A task is an operation that manipulates the contents of a file.
                   87607:  *
                   87608:  * Simple tasks operate on 1 file.  Multiple tasks are executed after all files have been
                   87609:  * processed and installed, and are designed to operate on all files containing the task.
                   87610:  * The Post-install script task simply takes advantage of the fact that it will be run
                   87611:  * after installation, replace is a simple task.
                   87612:  *
                   87613:  * Combining tasks is possible, but ordering is significant.
                   87614:  *
                   87615:  * <file name="test.php" role="php">
                   87616:  *  <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
                   87617:  *  <tasks:postinstallscript/>
                   87618:  * </file>
                   87619:  *
                   87620:  * This will first replace any instance of @data-dir@ in the test.php file
                   87621:  * with the path to the current data directory.  Then, it will include the
                   87622:  * test.php file and run the script it contains to configure the package post-installation.
                   87623:  * @category   pear
                   87624:  * @package    PEAR
                   87625:  * @author     Greg Beaver <cellog@php.net>
                   87626:  * @copyright  1997-2009 The Authors
                   87627:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   87628:  * @version    Release: 1.10.0beta1
                   87629:  * @link       http://pear.php.net/package/PEAR
                   87630:  * @since      Class available since Release 1.4.0a1
                   87631:  * @abstract
                   87632:  */
                   87633: class PEAR_Task_Common
                   87634: {
                   87635:     /**
                   87636:      * Valid types for this version are 'simple' and 'multiple'
                   87637:      *
                   87638:      * - simple tasks operate on the contents of a file and write out changes to disk
                   87639:      * - multiple tasks operate on the contents of many files and write out the
                   87640:      *   changes directly to disk
                   87641:      *
                   87642:      * Child task classes must override this property.
                   87643:      * @access protected
                   87644:      */
                   87645:     var $type = 'simple';
                   87646:     /**
                   87647:      * Determines which install phase this task is executed under
                   87648:      */
                   87649:     var $phase = PEAR_TASK_INSTALL;
                   87650:     /**
                   87651:      * @access protected
                   87652:      */
                   87653:     var $config;
                   87654:     /**
                   87655:      * @access protected
                   87656:      */
                   87657:     var $registry;
                   87658:     /**
                   87659:      * @access protected
                   87660:      */
                   87661:     var $logger;
                   87662:     /**
                   87663:      * @access protected
                   87664:      */
                   87665:     var $installphase;
                   87666:     /**
                   87667:      * @param PEAR_Config
                   87668:      * @param PEAR_Common
                   87669:      */
                   87670:     function PEAR_Task_Common(&$config, &$logger, $phase)
                   87671:     {
                   87672:         $this->config = &$config;
                   87673:         $this->registry = &$config->getRegistry();
                   87674:         $this->logger = &$logger;
                   87675:         $this->installphase = $phase;
                   87676:         if ($this->type == 'multiple') {
                   87677:             $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
                   87678:         }
                   87679:     }
                   87680: 
                   87681:     /**
                   87682:      * Validate the basic contents of a task tag.
                   87683:      * @param PEAR_PackageFile_v2
                   87684:      * @param array
                   87685:      * @param PEAR_Config
                   87686:      * @param array the entire parsed <file> tag
                   87687:      * @return true|array On error, return an array in format:
                   87688:      *    array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
                   87689:      *
                   87690:      *    For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
                   87691:      *    For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and an array
                   87692:      *    of legal values in
                   87693:      * @static
                   87694:      * @abstract
                   87695:      */
                   87696:     function validateXml($pkg, $xml, $config, $fileXml)
                   87697:     {
                   87698:     }
                   87699: 
                   87700:     /**
                   87701:      * Initialize a task instance with the parameters
                   87702:      * @param array raw, parsed xml
                   87703:      * @param array attributes from the <file> tag containing this task
                   87704:      * @param string|null last installed version of this package
                   87705:      * @abstract
                   87706:      */
                   87707:     function init($xml, $fileAttributes, $lastVersion)
                   87708:     {
                   87709:     }
                   87710: 
                   87711:     /**
                   87712:      * Begin a task processing session.  All multiple tasks will be processed after each file
                   87713:      * has been successfully installed, all simple tasks should perform their task here and
                   87714:      * return any errors using the custom throwError() method to allow forward compatibility
                   87715:      *
                   87716:      * This method MUST NOT write out any changes to disk
                   87717:      * @param PEAR_PackageFile_v2
                   87718:      * @param string file contents
                   87719:      * @param string the eventual final file location (informational only)
                   87720:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   87721:      *         (use $this->throwError), otherwise return the new contents
                   87722:      * @abstract
                   87723:      */
                   87724:     function startSession($pkg, $contents, $dest)
                   87725:     {
                   87726:     }
                   87727: 
                   87728:     /**
                   87729:      * This method is used to process each of the tasks for a particular multiple class
                   87730:      * type.  Simple tasks need not implement this method.
                   87731:      * @param array an array of tasks
                   87732:      * @access protected
                   87733:      * @static
                   87734:      * @abstract
                   87735:      */
                   87736:     function run($tasks)
                   87737:     {
                   87738:     }
                   87739: 
                   87740:     /**
                   87741:      * @static
                   87742:      * @final
                   87743:      */
                   87744:     function hasPostinstallTasks()
                   87745:     {
                   87746:         return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   87747:     }
                   87748: 
                   87749:     /**
                   87750:      * @static
                   87751:      * @final
                   87752:      */
                   87753:      function runPostinstallTasks()
                   87754:      {
                   87755:          foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
                   87756:              $err = call_user_func(array($class, 'run'),
                   87757:                   $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]);
                   87758:              if ($err) {
                   87759:                  return PEAR_Task_Common::throwError($err);
                   87760:              }
                   87761:          }
                   87762:          unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   87763:     }
                   87764: 
                   87765:     /**
                   87766:      * Determines whether a role is a script
                   87767:      * @return bool
                   87768:      */
                   87769:     function isScript()
                   87770:     {
                   87771:         return $this->type == 'script';
                   87772:     }
                   87773: 
                   87774:     function throwError($msg, $code = -1)
                   87775:     {
                   87776:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   87777:         return PEAR::raiseError($msg, $code);
                   87778:     }
                   87779: }
                   87780: ?><?php
                   87781: /**
                   87782:  * <tasks:postinstallscript>
                   87783:  *
                   87784:  * PHP versions 4 and 5
                   87785:  *
                   87786:  * @category   pear
                   87787:  * @package    PEAR
                   87788:  * @author     Greg Beaver <cellog@php.net>
                   87789:  * @copyright  1997-2009 The Authors
                   87790:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   87791:  * @version    CVS: $Id: Postinstallscript.php 276385 2009-02-24 23:46:03Z dufuz $
                   87792:  * @link       http://pear.php.net/package/PEAR
                   87793:  * @since      File available since Release 1.4.0a1
                   87794:  */
                   87795: /**
                   87796:  * Base class
                   87797:  */
                   87798: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   87799: /**
                   87800:  * Implements the postinstallscript file task.
                   87801:  *
                   87802:  * Note that post-install scripts are handled separately from installation, by the
                   87803:  * "pear run-scripts" command
                   87804:  * @category   pear
                   87805:  * @package    PEAR
                   87806:  * @author     Greg Beaver <cellog@php.net>
                   87807:  * @copyright  1997-2009 The Authors
                   87808:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   87809:  * @version    Release: 1.10.0beta1
                   87810:  * @link       http://pear.php.net/package/PEAR
                   87811:  * @since      Class available since Release 1.4.0a1
                   87812:  */
                   87813: class PEAR_Task_Postinstallscript extends PEAR_Task_Common
                   87814: {
                   87815:     var $type = 'script';
                   87816:     var $_class;
                   87817:     var $_params;
                   87818:     var $_obj;
                   87819:     /**
                   87820:      *
                   87821:      * @var PEAR_PackageFile_v2
                   87822:      */
                   87823:     var $_pkg;
                   87824:     var $_contents;
                   87825:     var $phase = PEAR_TASK_INSTALL;
                   87826: 
                   87827:     /**
                   87828:      * Validate the raw xml at parsing-time.
                   87829:      *
                   87830:      * This also attempts to validate the script to make sure it meets the criteria
                   87831:      * for a post-install script
                   87832:      * @param PEAR_PackageFile_v2
                   87833:      * @param array The XML contents of the <postinstallscript> tag
                   87834:      * @param PEAR_Config
                   87835:      * @param array the entire parsed <file> tag
                   87836:      * @static
                   87837:      */
                   87838:     function validateXml($pkg, $xml, $config, $fileXml)
                   87839:     {
                   87840:         if ($fileXml['role'] != 'php') {
                   87841:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87842:             $fileXml['name'] . '" must be role="php"');
                   87843:         }
                   87844:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   87845:         $file = $pkg->getFileContents($fileXml['name']);
                   87846:         if (PEAR::isError($file)) {
                   87847:             PEAR::popErrorHandling();
                   87848:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87849:                 $fileXml['name'] . '" is not valid: ' .
                   87850:                 $file->getMessage());
                   87851:         } elseif ($file === null) {
                   87852:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87853:                 $fileXml['name'] . '" could not be retrieved for processing!');
                   87854:         } else {
                   87855:             $analysis = $pkg->analyzeSourceCode($file, true);
                   87856:             if (!$analysis) {
                   87857:                 PEAR::popErrorHandling();
                   87858:                 $warnings = '';
                   87859:                 foreach ($pkg->getValidationWarnings() as $warn) {
                   87860:                     $warnings .= $warn['message'] . "\n";
                   87861:                 }
                   87862:                 return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' .
                   87863:                     $fileXml['name'] . '" failed: ' . $warnings);
                   87864:             }
                   87865:             if (count($analysis['declared_classes']) != 1) {
                   87866:                 PEAR::popErrorHandling();
                   87867:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87868:                     $fileXml['name'] . '" must declare exactly 1 class');
                   87869:             }
                   87870:             $class = $analysis['declared_classes'][0];
                   87871:             if ($class != str_replace(array('/', '.php'), array('_', ''),
                   87872:                   $fileXml['name']) . '_postinstall') {
                   87873:                 PEAR::popErrorHandling();
                   87874:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87875:                     $fileXml['name'] . '" class "' . $class . '" must be named "' .
                   87876:                     str_replace(array('/', '.php'), array('_', ''),
                   87877:                     $fileXml['name']) . '_postinstall"');
                   87878:             }
                   87879:             if (!isset($analysis['declared_methods'][$class])) {
                   87880:                 PEAR::popErrorHandling();
                   87881:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87882:                     $fileXml['name'] . '" must declare methods init() and run()');
                   87883:             }
                   87884:             $methods = array('init' => 0, 'run' => 1);
                   87885:             foreach ($analysis['declared_methods'][$class] as $method) {
                   87886:                 if (isset($methods[$method])) {
                   87887:                     unset($methods[$method]);
                   87888:                 }
                   87889:             }
                   87890:             if (count($methods)) {
                   87891:                 PEAR::popErrorHandling();
                   87892:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87893:                     $fileXml['name'] . '" must declare methods init() and run()');
                   87894:             }
                   87895:         }
                   87896:         PEAR::popErrorHandling();
                   87897:         $definedparams = array();
                   87898:         $tasksNamespace = $pkg->getTasksNs() . ':';
                   87899:         if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) {
                   87900:             // in order to support the older betas, which did not expect internal tags
                   87901:             // to also use the namespace
                   87902:             $tasksNamespace = '';
                   87903:         }
                   87904:         if (isset($xml[$tasksNamespace . 'paramgroup'])) {
                   87905:             $params = $xml[$tasksNamespace . 'paramgroup'];
                   87906:             if (!is_array($params) || !isset($params[0])) {
                   87907:                 $params = array($params);
                   87908:             }
                   87909:             foreach ($params as $param) {
                   87910:                 if (!isset($param[$tasksNamespace . 'id'])) {
                   87911:                     return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87912:                         $fileXml['name'] . '" <paramgroup> must have ' .
                   87913:                         'an ' . $tasksNamespace . 'id> tag');
                   87914:                 }
                   87915:                 if (isset($param[$tasksNamespace . 'name'])) {
                   87916:                     if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) {
                   87917:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87918:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   87919:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   87920:                             '" parameter "' . $param[$tasksNamespace . 'name'] .
                   87921:                             '" has not been previously defined');
                   87922:                     }
                   87923:                     if (!isset($param[$tasksNamespace . 'conditiontype'])) {
                   87924:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87925:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   87926:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   87927:                             '" must have a ' . $tasksNamespace .
                   87928:                             'conditiontype> tag containing either "=", ' .
                   87929:                             '"!=", or "preg_match"');
                   87930:                     }
                   87931:                     if (!in_array($param[$tasksNamespace . 'conditiontype'],
                   87932:                           array('=', '!=', 'preg_match'))) {
                   87933:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87934:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   87935:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   87936:                             '" must have a ' . $tasksNamespace .
                   87937:                             'conditiontype> tag containing either "=", ' .
                   87938:                             '"!=", or "preg_match"');
                   87939:                     }
                   87940:                     if (!isset($param[$tasksNamespace . 'value'])) {
                   87941:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87942:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   87943:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   87944:                             '" must have a ' . $tasksNamespace .
                   87945:                             'value> tag containing expected parameter value');
                   87946:                     }
                   87947:                 }
                   87948:                 if (isset($param[$tasksNamespace . 'instructions'])) {
                   87949:                     if (!is_string($param[$tasksNamespace . 'instructions'])) {
                   87950:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87951:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   87952:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   87953:                             '" ' . $tasksNamespace . 'instructions> must be simple text');
                   87954:                     }
                   87955:                 }
                   87956:                 if (!isset($param[$tasksNamespace . 'param'])) {
                   87957:                     continue; // <param> is no longer required
                   87958:                 }
                   87959:                 $subparams = $param[$tasksNamespace . 'param'];
                   87960:                 if (!is_array($subparams) || !isset($subparams[0])) {
                   87961:                     $subparams = array($subparams);
                   87962:                 }
                   87963:                 foreach ($subparams as $subparam) {
                   87964:                     if (!isset($subparam[$tasksNamespace . 'name'])) {
                   87965:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87966:                             $fileXml['name'] . '" parameter for ' .
                   87967:                             $tasksNamespace . 'paramgroup> id "' .
                   87968:                             $param[$tasksNamespace . 'id'] . '" must have ' .
                   87969:                             'a ' . $tasksNamespace . 'name> tag');
                   87970:                     }
                   87971:                     if (!preg_match('/[a-zA-Z0-9]+/',
                   87972:                           $subparam[$tasksNamespace . 'name'])) {
                   87973:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87974:                             $fileXml['name'] . '" parameter "' .
                   87975:                             $subparam[$tasksNamespace . 'name'] .
                   87976:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   87977:                             $param[$tasksNamespace . 'id'] .
                   87978:                             '" is not a valid name.  Must contain only alphanumeric characters');
                   87979:                     }
                   87980:                     if (!isset($subparam[$tasksNamespace . 'prompt'])) {
                   87981:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87982:                             $fileXml['name'] . '" parameter "' .
                   87983:                             $subparam[$tasksNamespace . 'name'] .
                   87984:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   87985:                             $param[$tasksNamespace . 'id'] .
                   87986:                             '" must have a ' . $tasksNamespace . 'prompt> tag');
                   87987:                     }
                   87988:                     if (!isset($subparam[$tasksNamespace . 'type'])) {
                   87989:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   87990:                             $fileXml['name'] . '" parameter "' .
                   87991:                             $subparam[$tasksNamespace . 'name'] .
                   87992:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   87993:                             $param[$tasksNamespace . 'id'] .
                   87994:                             '" must have a ' . $tasksNamespace . 'type> tag');
                   87995:                     }
                   87996:                     $definedparams[] = $param[$tasksNamespace . 'id'] . '::' .
                   87997:                     $subparam[$tasksNamespace . 'name'];
                   87998:                 }
                   87999:             }
                   88000:         }
                   88001:         return true;
                   88002:     }
                   88003: 
                   88004:     /**
                   88005:      * Initialize a task instance with the parameters
                   88006:      * @param array raw, parsed xml
                   88007:      * @param array attributes from the <file> tag containing this task
                   88008:      * @param string|null last installed version of this package, if any (useful for upgrades)
                   88009:      */
                   88010:     function init($xml, $fileattribs, $lastversion)
                   88011:     {
                   88012:         $this->_class = str_replace('/', '_', $fileattribs['name']);
                   88013:         $this->_filename = $fileattribs['name'];
                   88014:         $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall';
                   88015:         $this->_params = $xml;
                   88016:         $this->_lastversion = $lastversion;
                   88017:     }
                   88018: 
                   88019:     /**
                   88020:      * Strip the tasks: namespace from internal params
                   88021:      *
                   88022:      * @access private
                   88023:      */
                   88024:     function _stripNamespace($params = null)
                   88025:     {
                   88026:         if ($params === null) {
                   88027:             $params = array();
                   88028:             if (!is_array($this->_params)) {
                   88029:                 return;
                   88030:             }
                   88031:             foreach ($this->_params as $i => $param) {
                   88032:                 if (is_array($param)) {
                   88033:                     $param = $this->_stripNamespace($param);
                   88034:                 }
                   88035:                 $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   88036:             }
                   88037:             $this->_params = $params;
                   88038:         } else {
                   88039:             $newparams = array();
                   88040:             foreach ($params as $i => $param) {
                   88041:                 if (is_array($param)) {
                   88042:                     $param = $this->_stripNamespace($param);
                   88043:                 }
                   88044:                 $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   88045:             }
                   88046:             return $newparams;
                   88047:         }
                   88048:     }
                   88049: 
                   88050:     /**
                   88051:      * Unlike other tasks, the installed file name is passed in instead of the file contents,
                   88052:      * because this task is handled post-installation
                   88053:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88054:      * @param string file name
                   88055:      * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
                   88056:      *         (use $this->throwError)
                   88057:      */
                   88058:     function startSession($pkg, $contents)
                   88059:     {
                   88060:         if ($this->installphase != PEAR_TASK_INSTALL) {
                   88061:             return false;
                   88062:         }
                   88063:         // remove the tasks: namespace if present
                   88064:         $this->_pkg = $pkg;
                   88065:         $this->_stripNamespace();
                   88066:         $this->logger->log(0, 'Including external post-installation script "' .
                   88067:             $contents . '" - any errors are in this script');
                   88068:         include_once 'phar://install-pear-nozlib.phar/' . $contents;
                   88069:         if (class_exists($this->_class)) {
                   88070:             $this->logger->log(0, 'Inclusion succeeded');
                   88071:         } else {
                   88072:             return $this->throwError('init of post-install script class "' . $this->_class
                   88073:                 . '" failed');
                   88074:         }
                   88075:         $this->_obj = new $this->_class;
                   88076:         $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"');
                   88077:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   88078:         $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
                   88079:         PEAR::popErrorHandling();
                   88080:         if ($res) {
                   88081:             $this->logger->log(0, 'init succeeded');
                   88082:         } else {
                   88083:             return $this->throwError('init of post-install script "' . $this->_class .
                   88084:                 '->init()" failed');
                   88085:         }
                   88086:         $this->_contents = $contents;
                   88087:         return true;
                   88088:     }
                   88089: 
                   88090:     /**
                   88091:      * No longer used
                   88092:      * @see PEAR_PackageFile_v2::runPostinstallScripts()
                   88093:      * @param array an array of tasks
                   88094:      * @param string install or upgrade
                   88095:      * @access protected
                   88096:      * @static
                   88097:      */
                   88098:     function run()
                   88099:     {
                   88100:     }
                   88101: }
                   88102: ?><?php
                   88103: /**
                   88104:  * <tasks:postinstallscript> - read/write version
                   88105:  *
                   88106:  * PHP versions 4 and 5
                   88107:  *
                   88108:  * @category   pear
                   88109:  * @package    PEAR
                   88110:  * @author     Greg Beaver <cellog@php.net>
                   88111:  * @copyright  1997-2009 The Authors
                   88112:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88113:  * @version    CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
                   88114:  * @link       http://pear.php.net/package/PEAR
                   88115:  * @since      File available since Release 1.4.0a10
                   88116:  */
                   88117: /**
                   88118:  * Base class
                   88119:  */
                   88120: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Postinstallscript.php';
                   88121: /**
                   88122:  * Abstracts the postinstallscript file task xml.
                   88123:  * @category   pear
                   88124:  * @package    PEAR
                   88125:  * @author     Greg Beaver <cellog@php.net>
                   88126:  * @copyright  1997-2009 The Authors
                   88127:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88128:  * @version    Release: 1.10.0beta1
                   88129:  * @link       http://pear.php.net/package/PEAR
                   88130:  * @since      Class available since Release 1.4.0a10
                   88131:  */
                   88132: class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
                   88133: {
                   88134:     /**
                   88135:      * parent package file object
                   88136:      *
                   88137:      * @var PEAR_PackageFile_v2_rw
                   88138:      */
                   88139:     var $_pkg;
                   88140:     /**
                   88141:      * Enter description here...
                   88142:      *
                   88143:      * @param PEAR_PackageFile_v2_rw $pkg
                   88144:      * @param PEAR_Config $config
                   88145:      * @param PEAR_Frontend $logger
                   88146:      * @param array $fileXml
                   88147:      * @return PEAR_Task_Postinstallscript_rw
                   88148:      */
                   88149:     function PEAR_Task_Postinstallscript_rw(&$pkg, &$config, &$logger, $fileXml)
                   88150:     {
                   88151:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   88152:         $this->_contents = $fileXml;
                   88153:         $this->_pkg = &$pkg;
                   88154:         $this->_params = array();
                   88155:     }
                   88156: 
                   88157:     function validate()
                   88158:     {
                   88159:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   88160:     }
                   88161: 
                   88162:     function getName()
                   88163:     {
                   88164:         return 'postinstallscript';
                   88165:     }
                   88166: 
                   88167:     /**
                   88168:      * add a simple <paramgroup> to the post-install script
                   88169:      *
                   88170:      * Order is significant, so call this method in the same
                   88171:      * sequence the users should see the paramgroups.  The $params
                   88172:      * parameter should either be the result of a call to {@link getParam()}
                   88173:      * or an array of calls to getParam().
                   88174:      *
                   88175:      * Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
                   88176:      * a <conditiontype> tag
                   88177:      * @param string $id <paramgroup> id as seen by the script
                   88178:      * @param array|false $params array of getParam() calls, or false for no params
                   88179:      * @param string|false $instructions
                   88180:      */
                   88181:     function addParamGroup($id, $params = false, $instructions = false)
                   88182:     {
                   88183:         if ($params && isset($params[0]) && !isset($params[1])) {
                   88184:             $params = $params[0];
                   88185:         }
                   88186:         $stuff =
                   88187:             array(
                   88188:                 $this->_pkg->getTasksNs() . ':id' => $id,
                   88189:             );
                   88190:         if ($instructions) {
                   88191:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   88192:         }
                   88193:         if ($params) {
                   88194:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   88195:         }
                   88196:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   88197:     }
                   88198: 
                   88199:     /**
                   88200:      * add a complex <paramgroup> to the post-install script with conditions
                   88201:      *
                   88202:      * This inserts a <paramgroup> with
                   88203:      *
                   88204:      * Order is significant, so call this method in the same
                   88205:      * sequence the users should see the paramgroups.  The $params
                   88206:      * parameter should either be the result of a call to {@link getParam()}
                   88207:      * or an array of calls to getParam().
                   88208:      *
                   88209:      * Use {@link addParamGroup()} to add a simple <paramgroup>
                   88210:      *
                   88211:      * @param string $id <paramgroup> id as seen by the script
                   88212:      * @param string $oldgroup <paramgroup> id of the section referenced by
                   88213:      *                         <conditiontype>
                   88214:      * @param string $param name of the <param> from the older section referenced
                   88215:      *                      by <contitiontype>
                   88216:      * @param string $value value to match of the parameter
                   88217:      * @param string $conditiontype one of '=', '!=', 'preg_match'
                   88218:      * @param array|false $params array of getParam() calls, or false for no params
                   88219:      * @param string|false $instructions
                   88220:      */
                   88221:     function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=',
                   88222:                                    $params = false, $instructions = false)
                   88223:     {
                   88224:         if ($params && isset($params[0]) && !isset($params[1])) {
                   88225:             $params = $params[0];
                   88226:         }
                   88227:         $stuff = array(
                   88228:             $this->_pkg->getTasksNs() . ':id' => $id,
                   88229:         );
                   88230:         if ($instructions) {
                   88231:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   88232:         }
                   88233:         $stuff[$this->_pkg->getTasksNs() . ':name'] = $oldgroup . '::' . $param;
                   88234:         $stuff[$this->_pkg->getTasksNs() . ':conditiontype'] = $conditiontype;
                   88235:         $stuff[$this->_pkg->getTasksNs() . ':value'] = $value;
                   88236:         if ($params) {
                   88237:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   88238:         }
                   88239:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   88240:     }
                   88241: 
                   88242:     function getXml()
                   88243:     {
                   88244:         return $this->_params;
                   88245:     }
                   88246: 
                   88247:     /**
                   88248:      * Use to set up a param tag for use in creating a paramgroup
                   88249:      * @static
                   88250:      */
                   88251:     function getParam($name, $prompt, $type = 'string', $default = null)
                   88252:     {
                   88253:         if ($default !== null) {
                   88254:             return
                   88255:             array(
                   88256:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   88257:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   88258:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   88259:                 $this->_pkg->getTasksNs() . ':default' => $default
                   88260:             );
                   88261:         }
                   88262:         return
                   88263:             array(
                   88264:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   88265:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   88266:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   88267:             );
                   88268:     }
                   88269: }
                   88270: ?><?php
                   88271: /**
                   88272:  * <tasks:replace>
                   88273:  *
                   88274:  * PHP versions 4 and 5
                   88275:  *
                   88276:  * @category   pear
                   88277:  * @package    PEAR
                   88278:  * @author     Greg Beaver <cellog@php.net>
                   88279:  * @copyright  1997-2009 The Authors
                   88280:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88281:  * @version    CVS: $Id: Replace.php 276394 2009-02-25 00:15:49Z dufuz $
                   88282:  * @link       http://pear.php.net/package/PEAR
                   88283:  * @since      File available since Release 1.4.0a1
                   88284:  */
                   88285: /**
                   88286:  * Base class
                   88287:  */
                   88288: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   88289: /**
                   88290:  * Implements the replace file task.
                   88291:  * @category   pear
                   88292:  * @package    PEAR
                   88293:  * @author     Greg Beaver <cellog@php.net>
                   88294:  * @copyright  1997-2009 The Authors
                   88295:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88296:  * @version    Release: 1.10.0beta1
                   88297:  * @link       http://pear.php.net/package/PEAR
                   88298:  * @since      Class available since Release 1.4.0a1
                   88299:  */
                   88300: class PEAR_Task_Replace extends PEAR_Task_Common
                   88301: {
                   88302:     var $type = 'simple';
                   88303:     var $phase = PEAR_TASK_PACKAGEANDINSTALL;
                   88304:     var $_replacements;
                   88305: 
                   88306:     /**
                   88307:      * Validate the raw xml at parsing-time.
                   88308:      * @param PEAR_PackageFile_v2
                   88309:      * @param array raw, parsed xml
                   88310:      * @param PEAR_Config
                   88311:      * @static
                   88312:      */
                   88313:     function validateXml($pkg, $xml, $config, $fileXml)
                   88314:     {
                   88315:         if (!isset($xml['attribs'])) {
                   88316:             return array(PEAR_TASK_ERROR_NOATTRIBS);
                   88317:         }
                   88318:         if (!isset($xml['attribs']['type'])) {
                   88319:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
                   88320:         }
                   88321:         if (!isset($xml['attribs']['to'])) {
                   88322:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
                   88323:         }
                   88324:         if (!isset($xml['attribs']['from'])) {
                   88325:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
                   88326:         }
                   88327:         if ($xml['attribs']['type'] == 'pear-config') {
                   88328:             if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                   88329:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   88330:                     $config->getKeys());
                   88331:             }
                   88332:         } elseif ($xml['attribs']['type'] == 'php-const') {
                   88333:             if (defined($xml['attribs']['to'])) {
                   88334:                 return true;
                   88335:             } else {
                   88336:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   88337:                     array('valid PHP constant'));
                   88338:             }
                   88339:         } elseif ($xml['attribs']['type'] == 'package-info') {
                   88340:             if (in_array($xml['attribs']['to'],
                   88341:                 array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   88342:                     'release_notes', 'license', 'release-license', 'license-uri',
                   88343:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   88344:                     'date', 'time'))) {
                   88345:                 return true;
                   88346:             } else {
                   88347:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   88348:                     array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   88349:                     'release_notes', 'license', 'release-license', 'license-uri',
                   88350:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   88351:                     'date', 'time'));
                   88352:             }
                   88353:         } else {
                   88354:             return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                   88355:                 array('pear-config', 'package-info', 'php-const'));
                   88356:         }
                   88357:         return true;
                   88358:     }
                   88359: 
                   88360:     /**
                   88361:      * Initialize a task instance with the parameters
                   88362:      * @param array raw, parsed xml
                   88363:      * @param unused
                   88364:      */
                   88365:     function init($xml, $attribs)
                   88366:     {
                   88367:         $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
                   88368:     }
                   88369: 
                   88370:     /**
                   88371:      * Do a package.xml 1.0 replacement, with additional package-info fields available
                   88372:      *
                   88373:      * See validateXml() source for the complete list of allowed fields
                   88374:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88375:      * @param string file contents
                   88376:      * @param string the eventual final file location (informational only)
                   88377:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   88378:      *         (use $this->throwError), otherwise return the new contents
                   88379:      */
                   88380:     function startSession($pkg, $contents, $dest)
                   88381:     {
                   88382:         $subst_from = $subst_to = array();
                   88383:         foreach ($this->_replacements as $a) {
                   88384:             $a = $a['attribs'];
                   88385:             $to = '';
                   88386:             if ($a['type'] == 'pear-config') {
                   88387:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   88388:                     return false;
                   88389:                 }
                   88390:                 if ($a['to'] == 'master_server') {
                   88391:                     $chan = $this->registry->getChannel($pkg->getChannel());
                   88392:                     if (!PEAR::isError($chan)) {
                   88393:                         $to = $chan->getServer();
                   88394:                     } else {
                   88395:                         $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   88396:                         return false;
                   88397:                     }
                   88398:                 } else {
                   88399:                     if ($this->config->isDefinedLayer('ftp')) {
                   88400:                         // try the remote config file first
                   88401:                         $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                   88402:                         if (is_null($to)) {
                   88403:                             // then default to local
                   88404:                             $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   88405:                         }
                   88406:                     } else {
                   88407:                         $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   88408:                     }
                   88409:                 }
                   88410:                 if (is_null($to)) {
                   88411:                     $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   88412:                     return false;
                   88413:                 }
                   88414:             } elseif ($a['type'] == 'php-const') {
                   88415:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   88416:                     return false;
                   88417:                 }
                   88418:                 if (defined($a['to'])) {
                   88419:                     $to = constant($a['to']);
                   88420:                 } else {
                   88421:                     $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
                   88422:                     return false;
                   88423:                 }
                   88424:             } else {
                   88425:                 if ($t = $pkg->packageInfo($a['to'])) {
                   88426:                     $to = $t;
                   88427:                 } else {
                   88428:                     $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
                   88429:                     return false;
                   88430:                 }
                   88431:             }
                   88432:             if (!is_null($to)) {
                   88433:                 $subst_from[] = $a['from'];
                   88434:                 $subst_to[] = $to;
                   88435:             }
                   88436:         }
                   88437:         $this->logger->log(3, "doing " . sizeof($subst_from) .
                   88438:             " substitution(s) for $dest");
                   88439:         if (sizeof($subst_from)) {
                   88440:             $contents = str_replace($subst_from, $subst_to, $contents);
                   88441:         }
                   88442:         return $contents;
                   88443:     }
                   88444: }
                   88445: ?><?php
                   88446: /**
                   88447:  * <tasks:replace> - read/write version
                   88448:  *
                   88449:  * PHP versions 4 and 5
                   88450:  *
                   88451:  * @category   pear
                   88452:  * @package    PEAR
                   88453:  * @author     Greg Beaver <cellog@php.net>
                   88454:  * @copyright  1997-2009 The Authors
                   88455:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88456:  * @version    CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
                   88457:  * @link       http://pear.php.net/package/PEAR
                   88458:  * @since      File available since Release 1.4.0a10
                   88459:  */
                   88460: /**
                   88461:  * Base class
                   88462:  */
                   88463: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Replace.php';
                   88464: /**
                   88465:  * Abstracts the replace task xml.
                   88466:  * @category   pear
                   88467:  * @package    PEAR
                   88468:  * @author     Greg Beaver <cellog@php.net>
                   88469:  * @copyright  1997-2009 The Authors
                   88470:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88471:  * @version    Release: 1.10.0beta1
                   88472:  * @link       http://pear.php.net/package/PEAR
                   88473:  * @since      Class available since Release 1.4.0a10
                   88474:  */
                   88475: class PEAR_Task_Replace_rw extends PEAR_Task_Replace
                   88476: {
                   88477:     function PEAR_Task_Replace_rw(&$pkg, &$config, &$logger, $fileXml)
                   88478:     {
                   88479:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   88480:         $this->_contents = $fileXml;
                   88481:         $this->_pkg = &$pkg;
                   88482:         $this->_params = array();
                   88483:     }
                   88484: 
                   88485:     function validate()
                   88486:     {
                   88487:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   88488:     }
                   88489: 
                   88490:     function setInfo($from, $to, $type)
                   88491:     {
                   88492:         $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
                   88493:     }
                   88494: 
                   88495:     function getName()
                   88496:     {
                   88497:         return 'replace';
                   88498:     }
                   88499: 
                   88500:     function getXml()
                   88501:     {
                   88502:         return $this->_params;
                   88503:     }
                   88504: }
                   88505: ?><?php
                   88506: /**
                   88507:  * <tasks:unixeol>
                   88508:  *
                   88509:  * PHP versions 4 and 5
                   88510:  *
                   88511:  * @category   pear
                   88512:  * @package    PEAR
                   88513:  * @author     Greg Beaver <cellog@php.net>
                   88514:  * @copyright  1997-2009 The Authors
                   88515:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88516:  * @version    CVS: $Id: Unixeol.php 276394 2009-02-25 00:15:49Z dufuz $
                   88517:  * @link       http://pear.php.net/package/PEAR
                   88518:  * @since      File available since Release 1.4.0a1
                   88519:  */
                   88520: /**
                   88521:  * Base class
                   88522:  */
                   88523: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   88524: /**
                   88525:  * Implements the unix line endings file task.
                   88526:  * @category   pear
                   88527:  * @package    PEAR
                   88528:  * @author     Greg Beaver <cellog@php.net>
                   88529:  * @copyright  1997-2009 The Authors
                   88530:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88531:  * @version    Release: 1.10.0beta1
                   88532:  * @link       http://pear.php.net/package/PEAR
                   88533:  * @since      Class available since Release 1.4.0a1
                   88534:  */
                   88535: class PEAR_Task_Unixeol extends PEAR_Task_Common
                   88536: {
                   88537:     var $type = 'simple';
                   88538:     var $phase = PEAR_TASK_PACKAGE;
                   88539:     var $_replacements;
                   88540: 
                   88541:     /**
                   88542:      * Validate the raw xml at parsing-time.
                   88543:      * @param PEAR_PackageFile_v2
                   88544:      * @param array raw, parsed xml
                   88545:      * @param PEAR_Config
                   88546:      * @static
                   88547:      */
                   88548:     function validateXml($pkg, $xml, $config, $fileXml)
                   88549:     {
                   88550:         if ($xml != '') {
                   88551:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   88552:         }
                   88553:         return true;
                   88554:     }
                   88555: 
                   88556:     /**
                   88557:      * Initialize a task instance with the parameters
                   88558:      * @param array raw, parsed xml
                   88559:      * @param unused
                   88560:      */
                   88561:     function init($xml, $attribs)
                   88562:     {
                   88563:     }
                   88564: 
                   88565:     /**
                   88566:      * Replace all line endings with line endings customized for the current OS
                   88567:      *
                   88568:      * See validateXml() source for the complete list of allowed fields
                   88569:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88570:      * @param string file contents
                   88571:      * @param string the eventual final file location (informational only)
                   88572:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   88573:      *         (use $this->throwError), otherwise return the new contents
                   88574:      */
                   88575:     function startSession($pkg, $contents, $dest)
                   88576:     {
                   88577:         $this->logger->log(3, "replacing all line endings with \\n in $dest");
                   88578:         return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
                   88579:     }
                   88580: }
                   88581: ?><?php
                   88582: /**
                   88583:  * <tasks:unixeol> - read/write version
                   88584:  *
                   88585:  * PHP versions 4 and 5
                   88586:  *
                   88587:  * @category   pear
                   88588:  * @package    PEAR
                   88589:  * @author     Greg Beaver <cellog@php.net>
                   88590:  * @copyright  1997-2009 The Authors
                   88591:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88592:  * @version    CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
                   88593:  * @link       http://pear.php.net/package/PEAR
                   88594:  * @since      File available since Release 1.4.0a10
                   88595:  */
                   88596: /**
                   88597:  * Base class
                   88598:  */
                   88599: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Unixeol.php';
                   88600: /**
                   88601:  * Abstracts the unixeol task xml.
                   88602:  * @category   pear
                   88603:  * @package    PEAR
                   88604:  * @author     Greg Beaver <cellog@php.net>
                   88605:  * @copyright  1997-2009 The Authors
                   88606:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88607:  * @version    Release: 1.10.0beta1
                   88608:  * @link       http://pear.php.net/package/PEAR
                   88609:  * @since      Class available since Release 1.4.0a10
                   88610:  */
                   88611: class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
                   88612: {
                   88613:     function PEAR_Task_Unixeol_rw(&$pkg, &$config, &$logger, $fileXml)
                   88614:     {
                   88615:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   88616:         $this->_contents = $fileXml;
                   88617:         $this->_pkg = &$pkg;
                   88618:         $this->_params = array();
                   88619:     }
                   88620: 
                   88621:     function validate()
                   88622:     {
                   88623:         return true;
                   88624:     }
                   88625: 
                   88626:     function getName()
                   88627:     {
                   88628:         return 'unixeol';
                   88629:     }
                   88630: 
                   88631:     function getXml()
                   88632:     {
                   88633:         return '';
                   88634:     }
                   88635: }
                   88636: ?><?php
                   88637: /**
                   88638:  * <tasks:windowseol>
                   88639:  *
                   88640:  * PHP versions 4 and 5
                   88641:  *
                   88642:  * @category   pear
                   88643:  * @package    PEAR
                   88644:  * @author     Greg Beaver <cellog@php.net>
                   88645:  * @copyright  1997-2009 The Authors
                   88646:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88647:  * @version    CVS: $Id: Windowseol.php 276394 2009-02-25 00:15:49Z dufuz $
                   88648:  * @link       http://pear.php.net/package/PEAR
                   88649:  * @since      File available since Release 1.4.0a1
                   88650:  */
                   88651: /**
                   88652:  * Base class
                   88653:  */
                   88654: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   88655: /**
                   88656:  * Implements the windows line endsings file task.
                   88657:  * @category   pear
                   88658:  * @package    PEAR
                   88659:  * @author     Greg Beaver <cellog@php.net>
                   88660:  * @copyright  1997-2009 The Authors
                   88661:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88662:  * @version    Release: 1.10.0beta1
                   88663:  * @link       http://pear.php.net/package/PEAR
                   88664:  * @since      Class available since Release 1.4.0a1
                   88665:  */
                   88666: class PEAR_Task_Windowseol extends PEAR_Task_Common
                   88667: {
                   88668:     var $type = 'simple';
                   88669:     var $phase = PEAR_TASK_PACKAGE;
                   88670:     var $_replacements;
                   88671: 
                   88672:     /**
                   88673:      * Validate the raw xml at parsing-time.
                   88674:      * @param PEAR_PackageFile_v2
                   88675:      * @param array raw, parsed xml
                   88676:      * @param PEAR_Config
                   88677:      * @static
                   88678:      */
                   88679:     function validateXml($pkg, $xml, $config, $fileXml)
                   88680:     {
                   88681:         if ($xml != '') {
                   88682:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   88683:         }
                   88684:         return true;
                   88685:     }
                   88686: 
                   88687:     /**
                   88688:      * Initialize a task instance with the parameters
                   88689:      * @param array raw, parsed xml
                   88690:      * @param unused
                   88691:      */
                   88692:     function init($xml, $attribs)
                   88693:     {
                   88694:     }
                   88695: 
                   88696:     /**
                   88697:      * Replace all line endings with windows line endings
                   88698:      *
                   88699:      * See validateXml() source for the complete list of allowed fields
                   88700:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88701:      * @param string file contents
                   88702:      * @param string the eventual final file location (informational only)
                   88703:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   88704:      *         (use $this->throwError), otherwise return the new contents
                   88705:      */
                   88706:     function startSession($pkg, $contents, $dest)
                   88707:     {
                   88708:         $this->logger->log(3, "replacing all line endings with \\r\\n in $dest");
                   88709:         return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
                   88710:     }
                   88711: }
                   88712: ?><?php
                   88713: /**
                   88714:  * <tasks:windowseol> - read/write version
                   88715:  *
                   88716:  * PHP versions 4 and 5
                   88717:  *
                   88718:  * @category   pear
                   88719:  * @package    PEAR
                   88720:  * @author     Greg Beaver <cellog@php.net>
                   88721:  * @copyright  1997-2009 The Authors
                   88722:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88723:  * @version    CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
                   88724:  * @link       http://pear.php.net/package/PEAR
                   88725:  * @since      File available since Release 1.4.0a10
                   88726:  */
                   88727: /**
                   88728:  * Base class
                   88729:  */
                   88730: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Windowseol.php';
                   88731: /**
                   88732:  * Abstracts the windowseol task xml.
                   88733:  * @category   pear
                   88734:  * @package    PEAR
                   88735:  * @author     Greg Beaver <cellog@php.net>
                   88736:  * @copyright  1997-2009 The Authors
                   88737:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88738:  * @version    Release: 1.10.0beta1
                   88739:  * @link       http://pear.php.net/package/PEAR
                   88740:  * @since      Class available since Release 1.4.0a10
                   88741:  */
                   88742: class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
                   88743: {
                   88744:     function PEAR_Task_Windowseol_rw(&$pkg, &$config, &$logger, $fileXml)
                   88745:     {
                   88746:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   88747:         $this->_contents = $fileXml;
                   88748:         $this->_pkg = &$pkg;
                   88749:         $this->_params = array();
                   88750:     }
                   88751: 
                   88752:     function validate()
                   88753:     {
                   88754:         return true;
                   88755:     }
                   88756: 
                   88757:     function getName()
                   88758:     {
                   88759:         return 'windowseol';
                   88760:     }
                   88761: 
                   88762:     function getXml()
                   88763:     {
                   88764:         return '';
                   88765:     }
                   88766: }
                   88767: ?><?php
                   88768: /**
                   88769:  * PEAR_Validate
                   88770:  *
                   88771:  * PHP versions 4 and 5
                   88772:  *
                   88773:  * @category   pear
                   88774:  * @package    PEAR
                   88775:  * @author     Greg Beaver <cellog@php.net>
                   88776:  * @copyright  1997-2009 The Authors
                   88777:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88778:  * @version    CVS: $Id: Validate.php 276383 2009-02-24 23:39:37Z dufuz $
                   88779:  * @link       http://pear.php.net/package/PEAR
                   88780:  * @since      File available since Release 1.4.0a1
                   88781:  */
                   88782: /**#@+
                   88783:  * Constants for install stage
                   88784:  */
                   88785: define('PEAR_VALIDATE_INSTALLING', 1);
                   88786: define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
                   88787: define('PEAR_VALIDATE_NORMAL', 3);
                   88788: define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
                   88789: define('PEAR_VALIDATE_PACKAGING', 7);
                   88790: /**#@-*/
                   88791: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   88792: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validator/PECL.php';
                   88793: 
                   88794: /**
                   88795:  * Validation class for package.xml - channel-level advanced validation
                   88796:  * @category   pear
                   88797:  * @package    PEAR
                   88798:  * @author     Greg Beaver <cellog@php.net>
                   88799:  * @copyright  1997-2009 The Authors
                   88800:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   88801:  * @version    Release: 1.10.0beta1
                   88802:  * @link       http://pear.php.net/package/PEAR
                   88803:  * @since      Class available since Release 1.4.0a1
                   88804:  */
                   88805: class PEAR_Validate
                   88806: {
                   88807:     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
                   88808:     /**
                   88809:      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88810:      */
                   88811:     var $_packagexml;
                   88812:     /**
                   88813:      * @var int one of the PEAR_VALIDATE_* constants
                   88814:      */
                   88815:     var $_state = PEAR_VALIDATE_NORMAL;
                   88816:     /**
                   88817:      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
                   88818:      * @var array
                   88819:      * @access private
                   88820:      */
                   88821:     var $_failures = array('error' => array(), 'warning' => array());
                   88822: 
                   88823:     /**
                   88824:      * Override this method to handle validation of normal package names
                   88825:      * @param string
                   88826:      * @return bool
                   88827:      * @access protected
                   88828:      */
                   88829:     function _validPackageName($name)
                   88830:     {
                   88831:         return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
                   88832:     }
                   88833: 
                   88834:     /**
                   88835:      * @param string package name to validate
                   88836:      * @param string name of channel-specific validation package
                   88837:      * @final
                   88838:      */
                   88839:     function validPackageName($name, $validatepackagename = false)
                   88840:     {
                   88841:         if ($validatepackagename) {
                   88842:             if (strtolower($name) == strtolower($validatepackagename)) {
                   88843:                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
                   88844:             }
                   88845:         }
                   88846:         return $this->_validPackageName($name);
                   88847:     }
                   88848: 
                   88849:     /**
                   88850:      * This validates a bundle name, and bundle names must conform
                   88851:      * to the PEAR naming convention, so the method is final and static.
                   88852:      * @param string
                   88853:      * @final
                   88854:      * @static
                   88855:      */
                   88856:     function validGroupName($name)
                   88857:     {
                   88858:         return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
                   88859:     }
                   88860: 
                   88861:     /**
                   88862:      * Determine whether $state represents a valid stability level
                   88863:      * @param string
                   88864:      * @return bool
                   88865:      * @static
                   88866:      * @final
                   88867:      */
                   88868:     function validState($state)
                   88869:     {
                   88870:         return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
                   88871:     }
                   88872: 
                   88873:     /**
                   88874:      * Get a list of valid stability levels
                   88875:      * @return array
                   88876:      * @static
                   88877:      * @final
                   88878:      */
                   88879:     function getValidStates()
                   88880:     {
                   88881:         return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   88882:     }
                   88883: 
                   88884:     /**
                   88885:      * Determine whether a version is a properly formatted version number that can be used
                   88886:      * by version_compare
                   88887:      * @param string
                   88888:      * @return bool
                   88889:      * @static
                   88890:      * @final
                   88891:      */
                   88892:     function validVersion($ver)
                   88893:     {
                   88894:         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   88895:     }
                   88896: 
                   88897:     /**
                   88898:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   88899:      */
                   88900:     function setPackageFile(&$pf)
                   88901:     {
                   88902:         $this->_packagexml = &$pf;
                   88903:     }
                   88904: 
                   88905:     /**
                   88906:      * @access private
                   88907:      */
                   88908:     function _addFailure($field, $reason)
                   88909:     {
                   88910:         $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
                   88911:     }
                   88912: 
                   88913:     /**
                   88914:      * @access private
                   88915:      */
                   88916:     function _addWarning($field, $reason)
                   88917:     {
                   88918:         $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
                   88919:     }
                   88920: 
                   88921:     function getFailures()
                   88922:     {
                   88923:         $failures = $this->_failures;
                   88924:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   88925:         return $failures;
                   88926:     }
                   88927: 
                   88928:     /**
                   88929:      * @param int one of the PEAR_VALIDATE_* constants
                   88930:      */
                   88931:     function validate($state = null)
                   88932:     {
                   88933:         if (!isset($this->_packagexml)) {
                   88934:             return false;
                   88935:         }
                   88936:         if ($state !== null) {
                   88937:             $this->_state = $state;
                   88938:         }
                   88939:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   88940:         $this->validatePackageName();
                   88941:         $this->validateVersion();
                   88942:         $this->validateMaintainers();
                   88943:         $this->validateDate();
                   88944:         $this->validateSummary();
                   88945:         $this->validateDescription();
                   88946:         $this->validateLicense();
                   88947:         $this->validateNotes();
                   88948:         if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
                   88949:             $this->validateState();
                   88950:             $this->validateFilelist();
                   88951:         } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   88952:                   $this->_packagexml->getPackagexmlVersion() == '2.1') {
                   88953:             $this->validateTime();
                   88954:             $this->validateStability();
                   88955:             $this->validateDeps();
                   88956:             $this->validateMainFilelist();
                   88957:             $this->validateReleaseFilelist();
                   88958:             //$this->validateGlobalTasks();
                   88959:             $this->validateChangelog();
                   88960:         }
                   88961:         return !((bool) count($this->_failures['errors']));
                   88962:     }
                   88963: 
                   88964:     /**
                   88965:      * @access protected
                   88966:      */
                   88967:     function validatePackageName()
                   88968:     {
                   88969:         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
                   88970:               $this->_state == PEAR_VALIDATE_NORMAL) {
                   88971:             if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   88972:                  $this->_packagexml->getPackagexmlVersion() == '2.1') &&
                   88973:                   $this->_packagexml->getExtends()) {
                   88974:                 $version = $this->_packagexml->getVersion() . '';
                   88975:                 $name = $this->_packagexml->getPackage();
                   88976:                 $test = array_shift($a = explode('.', $version));
                   88977:                 if ($test == '0') {
                   88978:                     return true;
                   88979:                 }
                   88980:                 $vlen = strlen($test);
                   88981:                 $majver = substr($name, strlen($name) - $vlen);
                   88982:                 while ($majver && !is_numeric($majver{0})) {
                   88983:                     $majver = substr($majver, 1);
                   88984:                 }
                   88985:                 if ($majver != $test) {
                   88986:                     $this->_addWarning('package', "package $name extends package " .
                   88987:                         $this->_packagexml->getExtends() . ' and so the name should ' .
                   88988:                         'have a postfix equal to the major version like "' .
                   88989:                         $this->_packagexml->getExtends() . $test . '"');
                   88990:                     return true;
                   88991:                 } elseif (substr($name, 0, strlen($name) - $vlen) !=
                   88992:                             $this->_packagexml->getExtends()) {
                   88993:                     $this->_addWarning('package', "package $name extends package " .
                   88994:                         $this->_packagexml->getExtends() . ' and so the name must ' .
                   88995:                         'be an extension like "' . $this->_packagexml->getExtends() .
                   88996:                         $test . '"');
                   88997:                     return true;
                   88998:                 }
                   88999:             }
                   89000:         }
                   89001:         if (!$this->validPackageName($this->_packagexml->getPackage())) {
                   89002:             $this->_addFailure('name', 'package name "' .
                   89003:                 $this->_packagexml->getPackage() . '" is invalid');
                   89004:             return false;
                   89005:         }
                   89006:     }
                   89007: 
                   89008:     /**
                   89009:      * @access protected
                   89010:      */
                   89011:     function validateVersion()
                   89012:     {
                   89013:         if ($this->_state != PEAR_VALIDATE_PACKAGING) {
                   89014:             if (!$this->validVersion($this->_packagexml->getVersion())) {
                   89015:                 $this->_addFailure('version',
                   89016:                     'Invalid version number "' . $this->_packagexml->getVersion() . '"');
                   89017:             }
                   89018:             return false;
                   89019:         }
                   89020:         $version = $this->_packagexml->getVersion();
                   89021:         $versioncomponents = explode('.', $version);
                   89022:         if (count($versioncomponents) != 3) {
                   89023:             $this->_addWarning('version',
                   89024:                 'A version number should have 3 decimals (x.y.z)');
                   89025:             return true;
                   89026:         }
                   89027:         $name = $this->_packagexml->getPackage();
                   89028:         // version must be based upon state
                   89029:         switch ($this->_packagexml->getState()) {
                   89030:             case 'snapshot' :
                   89031:                 return true;
                   89032:             case 'devel' :
                   89033:                 if ($versioncomponents[0] . 'a' == '0a') {
                   89034:                     return true;
                   89035:                 }
                   89036:                 if ($versioncomponents[0] == 0) {
                   89037:                     $versioncomponents[0] = '0';
                   89038:                     $this->_addWarning('version',
                   89039:                         'version "' . $version . '" should be "' .
                   89040:                         implode('.' ,$versioncomponents) . '"');
                   89041:                 } else {
                   89042:                     $this->_addWarning('version',
                   89043:                         'packages with devel stability must be < version 1.0.0');
                   89044:                 }
                   89045:                 return true;
                   89046:             break;
                   89047:             case 'alpha' :
                   89048:             case 'beta' :
                   89049:                 // check for a package that extends a package,
                   89050:                 // like Foo and Foo2
                   89051:                 if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   89052:                     if (substr($versioncomponents[2], 1, 2) == 'rc') {
                   89053:                         $this->_addFailure('version', 'Release Candidate versions ' .
                   89054:                             'must have capital RC, not lower-case rc');
                   89055:                         return false;
                   89056:                     }
                   89057:                 }
                   89058:                 if (!$this->_packagexml->getExtends()) {
                   89059:                     if ($versioncomponents[0] == '1') {
                   89060:                         if ($versioncomponents[2]{0} == '0') {
                   89061:                             if ($versioncomponents[2] == '0') {
                   89062:                                 // version 1.*.0000
                   89063:                                 $this->_addWarning('version',
                   89064:                                     'version 1.' . $versioncomponents[1] .
                   89065:                                         '.0 probably should not be alpha or beta');
                   89066:                                 return true;
                   89067:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   89068:                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
                   89069:                                 return true;
                   89070:                             } else {
                   89071:                                 // version 1.*.0
                   89072:                                 $this->_addWarning('version',
                   89073:                                     'version 1.' . $versioncomponents[1] .
                   89074:                                         '.0 probably should not be alpha or beta');
                   89075:                                 return true;
                   89076:                             }
                   89077:                         } else {
                   89078:                             $this->_addWarning('version',
                   89079:                                 'bugfix versions (1.3.x where x > 0) probably should ' .
                   89080:                                 'not be alpha or beta');
                   89081:                             return true;
                   89082:                         }
                   89083:                     } elseif ($versioncomponents[0] != '0') {
                   89084:                         $this->_addWarning('version',
                   89085:                             'major versions greater than 1 are not allowed for packages ' .
                   89086:                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
                   89087:                         return true;
                   89088:                     }
                   89089:                     if ($versioncomponents[0] . 'a' == '0a') {
                   89090:                         return true;
                   89091:                     }
                   89092:                     if ($versioncomponents[0] == 0) {
                   89093:                         $versioncomponents[0] = '0';
                   89094:                         $this->_addWarning('version',
                   89095:                             'version "' . $version . '" should be "' .
                   89096:                             implode('.' ,$versioncomponents) . '"');
                   89097:                     }
                   89098:                 } else {
                   89099:                     $vlen = strlen($versioncomponents[0] . '');
                   89100:                     $majver = substr($name, strlen($name) - $vlen);
                   89101:                     while ($majver && !is_numeric($majver{0})) {
                   89102:                         $majver = substr($majver, 1);
                   89103:                     }
                   89104:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   89105:                         $this->_addWarning('version', 'first version number "' .
                   89106:                             $versioncomponents[0] . '" must match the postfix of ' .
                   89107:                             'package name "' . $name . '" (' .
                   89108:                             $majver . ')');
                   89109:                         return true;
                   89110:                     }
                   89111:                     if ($versioncomponents[0] == $majver) {
                   89112:                         if ($versioncomponents[2]{0} == '0') {
                   89113:                             if ($versioncomponents[2] == '0') {
                   89114:                                 // version 2.*.0000
                   89115:                                 $this->_addWarning('version',
                   89116:                                     "version $majver." . $versioncomponents[1] .
                   89117:                                         '.0 probably should not be alpha or beta');
                   89118:                                 return false;
                   89119:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   89120:                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
                   89121:                                 return true;
                   89122:                             } else {
                   89123:                                 // version 2.*.0
                   89124:                                 $this->_addWarning('version',
                   89125:                                     "version $majver." . $versioncomponents[1] .
                   89126:                                         '.0 cannot be alpha or beta');
                   89127:                                 return true;
                   89128:                             }
                   89129:                         } else {
                   89130:                             $this->_addWarning('version',
                   89131:                                 "bugfix versions ($majver.x.y where y > 0) should " .
                   89132:                                 'not be alpha or beta');
                   89133:                             return true;
                   89134:                         }
                   89135:                     } elseif ($versioncomponents[0] != '0') {
                   89136:                         $this->_addWarning('version',
                   89137:                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
                   89138:                         return true;
                   89139:                     }
                   89140:                     if ($versioncomponents[0] . 'a' == '0a') {
                   89141:                         return true;
                   89142:                     }
                   89143:                     if ($versioncomponents[0] == 0) {
                   89144:                         $versioncomponents[0] = '0';
                   89145:                         $this->_addWarning('version',
                   89146:                             'version "' . $version . '" should be "' .
                   89147:                             implode('.' ,$versioncomponents) . '"');
                   89148:                     }
                   89149:                 }
                   89150:                 return true;
                   89151:             break;
                   89152:             case 'stable' :
                   89153:                 if ($versioncomponents[0] == '0') {
                   89154:                     $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
                   89155:                     'be stable');
                   89156:                     return true;
                   89157:                 }
                   89158:                 if (!is_numeric($versioncomponents[2])) {
                   89159:                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
                   89160:                           $versioncomponents[2])) {
                   89161:                         $this->_addWarning('version', 'version "' . $version . '" or any ' .
                   89162:                             'RC/beta/alpha version cannot be stable');
                   89163:                         return true;
                   89164:                     }
                   89165:                 }
                   89166:                 // check for a package that extends a package,
                   89167:                 // like Foo and Foo2
                   89168:                 if ($this->_packagexml->getExtends()) {
                   89169:                     $vlen = strlen($versioncomponents[0] . '');
                   89170:                     $majver = substr($name, strlen($name) - $vlen);
                   89171:                     while ($majver && !is_numeric($majver{0})) {
                   89172:                         $majver = substr($majver, 1);
                   89173:                     }
                   89174:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   89175:                         $this->_addWarning('version', 'first version number "' .
                   89176:                             $versioncomponents[0] . '" must match the postfix of ' .
                   89177:                             'package name "' . $name . '" (' .
                   89178:                             $majver . ')');
                   89179:                         return true;
                   89180:                     }
                   89181:                 } elseif ($versioncomponents[0] > 1) {
                   89182:                     $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
                   89183:                         '1 for any package that does not have an <extends> tag');
                   89184:                 }
                   89185:                 return true;
                   89186:             break;
                   89187:             default :
                   89188:                 return false;
                   89189:             break;
                   89190:         }
                   89191:     }
                   89192: 
                   89193:     /**
                   89194:      * @access protected
                   89195:      */
                   89196:     function validateMaintainers()
                   89197:     {
                   89198:         // maintainers can only be truly validated server-side for most channels
                   89199:         // but allow this customization for those who wish it
                   89200:         return true;
                   89201:     }
                   89202: 
                   89203:     /**
                   89204:      * @access protected
                   89205:      */
                   89206:     function validateDate()
                   89207:     {
                   89208:         if ($this->_state == PEAR_VALIDATE_NORMAL ||
                   89209:               $this->_state == PEAR_VALIDATE_PACKAGING) {
                   89210: 
                   89211:             if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
                   89212:                   $this->_packagexml->getDate(), $res) ||
                   89213:                   count($res) < 4
                   89214:                   || !checkdate($res[2], $res[3], $res[1])
                   89215:                 ) {
                   89216:                 $this->_addFailure('date', 'invalid release date "' .
                   89217:                     $this->_packagexml->getDate() . '"');
                   89218:                 return false;
                   89219:             }
                   89220: 
                   89221:             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
                   89222:                   $this->_packagexml->getDate() != date('Y-m-d')) {
                   89223:                 $this->_addWarning('date', 'Release Date "' .
                   89224:                     $this->_packagexml->getDate() . '" is not today');
                   89225:             }
                   89226:         }
                   89227:         return true;
                   89228:     }
                   89229: 
                   89230:     /**
                   89231:      * @access protected
                   89232:      */
                   89233:     function validateTime()
                   89234:     {
                   89235:         if (!$this->_packagexml->getTime()) {
                   89236:             // default of no time value set
                   89237:             return true;
                   89238:         }
                   89239: 
                   89240:         // packager automatically sets time, so only validate if pear validate is called
                   89241:         if ($this->_state = PEAR_VALIDATE_NORMAL) {
                   89242:             if (!preg_match('/\d\d:\d\d:\d\d/',
                   89243:                   $this->_packagexml->getTime())) {
                   89244:                 $this->_addFailure('time', 'invalid release time "' .
                   89245:                     $this->_packagexml->getTime() . '"');
                   89246:                 return false;
                   89247:             }
                   89248: 
                   89249:             $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
                   89250:             if ($result === false || empty($matches)) {
                   89251:                 $this->_addFailure('time', 'invalid release time "' .
                   89252:                     $this->_packagexml->getTime() . '"');
                   89253:                 return false;
                   89254:             }
                   89255:         }
                   89256: 
                   89257:         return true;
                   89258:     }
                   89259: 
                   89260:     /**
                   89261:      * @access protected
                   89262:      */
                   89263:     function validateState()
                   89264:     {
                   89265:         // this is the closest to "final" php4 can get
                   89266:         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
                   89267:             if (strtolower($this->_packagexml->getState() == 'rc')) {
                   89268:                 $this->_addFailure('state', 'RC is not a state, it is a version ' .
                   89269:                     'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
                   89270:             }
                   89271:             $this->_addFailure('state', 'invalid release state "' .
                   89272:                 $this->_packagexml->getState() . '", must be one of: ' .
                   89273:                 implode(', ', PEAR_Validate::getValidStates()));
                   89274:             return false;
                   89275:         }
                   89276:         return true;
                   89277:     }
                   89278: 
                   89279:     /**
                   89280:      * @access protected
                   89281:      */
                   89282:     function validateStability()
                   89283:     {
                   89284:         $ret = true;
                   89285:         $packagestability = $this->_packagexml->getState();
                   89286:         $apistability = $this->_packagexml->getState('api');
                   89287:         if (!PEAR_Validate::validState($packagestability)) {
                   89288:             $this->_addFailure('state', 'invalid release stability "' .
                   89289:                 $this->_packagexml->getState() . '", must be one of: ' .
                   89290:                 implode(', ', PEAR_Validate::getValidStates()));
                   89291:             $ret = false;
                   89292:         }
                   89293:         $apistates = PEAR_Validate::getValidStates();
                   89294:         array_shift($apistates); // snapshot is not allowed
                   89295:         if (!in_array($apistability, $apistates)) {
                   89296:             $this->_addFailure('state', 'invalid API stability "' .
                   89297:                 $this->_packagexml->getState('api') . '", must be one of: ' .
                   89298:                 implode(', ', $apistates));
                   89299:             $ret = false;
                   89300:         }
                   89301:         return $ret;
                   89302:     }
                   89303: 
                   89304:     /**
                   89305:      * @access protected
                   89306:      */
                   89307:     function validateSummary()
                   89308:     {
                   89309:         return true;
                   89310:     }
                   89311: 
                   89312:     /**
                   89313:      * @access protected
                   89314:      */
                   89315:     function validateDescription()
                   89316:     {
                   89317:         return true;
                   89318:     }
                   89319: 
                   89320:     /**
                   89321:      * @access protected
                   89322:      */
                   89323:     function validateLicense()
                   89324:     {
                   89325:         return true;
                   89326:     }
                   89327: 
                   89328:     /**
                   89329:      * @access protected
                   89330:      */
                   89331:     function validateNotes()
                   89332:     {
                   89333:         return true;
                   89334:     }
                   89335: 
                   89336:     /**
                   89337:      * for package.xml 2.0 only - channels can't use package.xml 1.0
                   89338:      * @access protected
                   89339:      */
                   89340:     function validateDependencies()
                   89341:     {
                   89342:         return true;
                   89343:     }
                   89344: 
                   89345:     /**
                   89346:      * for package.xml 1.0 only
                   89347:      * @access private
                   89348:      */
                   89349:     function _validateFilelist()
                   89350:     {
                   89351:         return true; // placeholder for now
                   89352:     }
                   89353: 
                   89354:     /**
                   89355:      * for package.xml 2.0 only
                   89356:      * @access protected
                   89357:      */
                   89358:     function validateMainFilelist()
                   89359:     {
                   89360:         return true; // placeholder for now
                   89361:     }
                   89362: 
                   89363:     /**
                   89364:      * for package.xml 2.0 only
                   89365:      * @access protected
                   89366:      */
                   89367:     function validateReleaseFilelist()
                   89368:     {
                   89369:         return true; // placeholder for now
                   89370:     }
                   89371: 
                   89372:     /**
                   89373:      * @access protected
                   89374:      */
                   89375:     function validateChangelog()
                   89376:     {
                   89377:         return true;
                   89378:     }
                   89379: 
                   89380:     /**
                   89381:      * @access protected
                   89382:      */
                   89383:     function validateFilelist()
                   89384:     {
                   89385:         return true;
                   89386:     }
                   89387: 
                   89388:     /**
                   89389:      * @access protected
                   89390:      */
                   89391:     function validateDeps()
                   89392:     {
                   89393:         return true;
                   89394:     }
                   89395: }<?php
                   89396: /**
                   89397:  * Channel Validator for the pecl.php.net channel
                   89398:  *
                   89399:  * PHP 4 and PHP 5
                   89400:  *
                   89401:  * @category   pear
                   89402:  * @package    PEAR
                   89403:  * @author     Greg Beaver <cellog@php.net>
                   89404:  * @copyright  1997-2006 The PHP Group
                   89405:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   89406:  * @version    CVS: $Id: PECL.php 276383 2009-02-24 23:39:37Z dufuz $
                   89407:  * @link       http://pear.php.net/package/PEAR
                   89408:  * @since      File available since Release 1.4.0a5
                   89409:  */
                   89410: /**
                   89411:  * This is the parent class for all validators
                   89412:  */
                   89413: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   89414: /**
                   89415:  * Channel Validator for the pecl.php.net channel
                   89416:  * @category   pear
                   89417:  * @package    PEAR
                   89418:  * @author     Greg Beaver <cellog@php.net>
                   89419:  * @copyright  1997-2009 The Authors
                   89420:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   89421:  * @version    Release: 1.10.0beta1
                   89422:  * @link       http://pear.php.net/package/PEAR
                   89423:  * @since      Class available since Release 1.4.0a5
                   89424:  */
                   89425: class PEAR_Validator_PECL extends PEAR_Validate
                   89426: {
                   89427:     function validateVersion()
                   89428:     {
                   89429:         if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   89430:             $version = $this->_packagexml->getVersion();
                   89431:             $versioncomponents = explode('.', $version);
                   89432:             $last = array_pop($versioncomponents);
                   89433:             if (substr($last, 1, 2) == 'rc') {
                   89434:                 $this->_addFailure('version', 'Release Candidate versions must have ' .
                   89435:                 'upper-case RC, not lower-case rc');
                   89436:                 return false;
                   89437:             }
                   89438:         }
                   89439:         return true;
                   89440:     }
                   89441: 
                   89442:     function validatePackageName()
                   89443:     {
                   89444:         $ret = parent::validatePackageName();
                   89445:         if ($this->_packagexml->getPackageType() == 'extsrc' ||
                   89446:               $this->_packagexml->getPackageType() == 'zendextsrc') {
                   89447:             if (strtolower($this->_packagexml->getPackage()) !=
                   89448:                   strtolower($this->_packagexml->getProvidesExtension())) {
                   89449:                 $this->_addWarning('providesextension', 'package name "' .
                   89450:                     $this->_packagexml->getPackage() . '" is different from extension name "' .
                   89451:                     $this->_packagexml->getProvidesExtension() . '"');
                   89452:             }
                   89453:         }
                   89454:         return $ret;
                   89455:     }
                   89456: }
                   89457: ?><?php
                   89458: /**
                   89459:  * PEAR_XMLParser
                   89460:  *
                   89461:  * PHP versions 4 and 5
                   89462:  *
                   89463:  * @category   pear
                   89464:  * @package    PEAR
                   89465:  * @author     Greg Beaver <cellog@php.net>
                   89466:  * @author     Stephan Schmidt (original XML_Unserializer code)
                   89467:  * @copyright  1997-2009 The Authors
                   89468:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   89469:  * @version    CVS: $Id: XMLParser.php 282970 2009-06-28 23:10:07Z dufuz $
                   89470:  * @link       http://pear.php.net/package/PEAR
                   89471:  * @since      File available since Release 1.4.0a1
                   89472:  */
                   89473: 
                   89474: /**
                   89475:  * Parser for any xml file
                   89476:  * @category  pear
                   89477:  * @package   PEAR
                   89478:  * @author    Greg Beaver <cellog@php.net>
                   89479:  * @author    Stephan Schmidt (original XML_Unserializer code)
                   89480:  * @copyright 1997-2009 The Authors
                   89481:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   89482:  * @version   Release: 1.10.0beta1
                   89483:  * @link      http://pear.php.net/package/PEAR
                   89484:  * @since     Class available since Release 1.4.0a1
                   89485:  */
                   89486: class PEAR_XMLParser
                   89487: {
                   89488:     /**
                   89489:      * unserilialized data
                   89490:      * @var string $_serializedData
                   89491:      */
                   89492:     var $_unserializedData = null;
                   89493: 
                   89494:     /**
                   89495:      * name of the root tag
                   89496:      * @var string $_root
                   89497:      */
                   89498:     var $_root = null;
                   89499: 
                   89500:     /**
                   89501:      * stack for all data that is found
                   89502:      * @var array    $_dataStack
                   89503:      */
                   89504:     var $_dataStack = array();
                   89505: 
                   89506:     /**
                   89507:      * stack for all values that are generated
                   89508:      * @var array    $_valStack
                   89509:      */
                   89510:     var $_valStack = array();
                   89511: 
                   89512:     /**
                   89513:      * current tag depth
                   89514:      * @var int    $_depth
                   89515:      */
                   89516:     var $_depth = 0;
                   89517: 
                   89518:     /**
                   89519:      * The XML encoding to use
                   89520:      * @var string $encoding
                   89521:      */
                   89522:     var $encoding = 'ISO-8859-1';
                   89523: 
                   89524:     /**
                   89525:      * @return array
                   89526:      */
                   89527:     function getData()
                   89528:     {
                   89529:         return $this->_unserializedData;
                   89530:     }
                   89531: 
                   89532:     /**
                   89533:      * @param string xml content
                   89534:      * @return true|PEAR_Error
                   89535:      */
                   89536:     function parse($data)
                   89537:     {
                   89538:         if (!extension_loaded('xml')) {
                   89539:             include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   89540:             return PEAR::raiseError("XML Extension not found", 1);
                   89541:         }
                   89542:         $this->_dataStack =  $this->_valStack = array();
                   89543:         $this->_depth = 0;
                   89544: 
                   89545:         if (
                   89546:             strpos($data, 'encoding="UTF-8"')
                   89547:             || strpos($data, 'encoding="utf-8"')
                   89548:             || strpos($data, "encoding='UTF-8'")
                   89549:             || strpos($data, "encoding='utf-8'")
                   89550:         ) {
                   89551:             $this->encoding = 'UTF-8';
                   89552:         }
                   89553: 
                   89554:         if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
                   89555:             $data = utf8_decode($data);
                   89556:             $this->encoding = 'ISO-8859-1';
                   89557:         }
                   89558: 
                   89559:         $xp = xml_parser_create($this->encoding);
                   89560:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
                   89561:         xml_set_object($xp, $this);
                   89562:         xml_set_element_handler($xp, 'startHandler', 'endHandler');
                   89563:         xml_set_character_data_handler($xp, 'cdataHandler');
                   89564:         if (!xml_parse($xp, $data)) {
                   89565:             $msg = xml_error_string(xml_get_error_code($xp));
                   89566:             $line = xml_get_current_line_number($xp);
                   89567:             xml_parser_free($xp);
                   89568:             include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   89569:             return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
                   89570:         }
                   89571:         xml_parser_free($xp);
                   89572:         return true;
                   89573:     }
                   89574: 
                   89575:     /**
                   89576:      * Start element handler for XML parser
                   89577:      *
                   89578:      * @access private
                   89579:      * @param  object $parser  XML parser object
                   89580:      * @param  string $element XML element
                   89581:      * @param  array  $attribs attributes of XML tag
                   89582:      * @return void
                   89583:      */
                   89584:     function startHandler($parser, $element, $attribs)
                   89585:     {
                   89586:         $this->_depth++;
                   89587:         $this->_dataStack[$this->_depth] = null;
                   89588: 
                   89589:         $val = array(
                   89590:             'name'         => $element,
                   89591:             'value'        => null,
                   89592:             'type'         => 'string',
                   89593:             'childrenKeys' => array(),
                   89594:             'aggregKeys'   => array()
                   89595:        );
                   89596: 
                   89597:         if (count($attribs) > 0) {
                   89598:             $val['children'] = array();
                   89599:             $val['type'] = 'array';
                   89600:             $val['children']['attribs'] = $attribs;
                   89601:         }
                   89602: 
                   89603:         array_push($this->_valStack, $val);
                   89604:     }
                   89605: 
                   89606:     /**
                   89607:      * post-process data
                   89608:      *
                   89609:      * @param string $data
                   89610:      * @param string $element element name
                   89611:      */
                   89612:     function postProcess($data, $element)
                   89613:     {
                   89614:         return trim($data);
                   89615:     }
                   89616: 
                   89617:     /**
                   89618:      * End element handler for XML parser
                   89619:      *
                   89620:      * @access private
                   89621:      * @param  object XML parser object
                   89622:      * @param  string
                   89623:      * @return void
                   89624:      */
                   89625:     function endHandler($parser, $element)
                   89626:     {
                   89627:         $value = array_pop($this->_valStack);
                   89628:         $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);
                   89629: 
                   89630:         // adjust type of the value
                   89631:         switch (strtolower($value['type'])) {
                   89632:             // unserialize an array
                   89633:             case 'array':
                   89634:                 if ($data !== '') {
                   89635:                     $value['children']['_content'] = $data;
                   89636:                 }
                   89637: 
                   89638:                 $value['value'] = isset($value['children']) ? $value['children'] : array();
                   89639:                 break;
                   89640: 
                   89641:             /*
                   89642:              * unserialize a null value
                   89643:              */
                   89644:             case 'null':
                   89645:                 $data = null;
                   89646:                 break;
                   89647: 
                   89648:             /*
                   89649:              * unserialize any scalar value
                   89650:              */
                   89651:             default:
                   89652:                 settype($data, $value['type']);
                   89653:                 $value['value'] = $data;
                   89654:                 break;
                   89655:         }
                   89656: 
                   89657:         $parent = array_pop($this->_valStack);
                   89658:         if ($parent === null) {
                   89659:             $this->_unserializedData = &$value['value'];
                   89660:             $this->_root = &$value['name'];
                   89661:             return true;
                   89662:         }
                   89663: 
                   89664:         // parent has to be an array
                   89665:         if (!isset($parent['children']) || !is_array($parent['children'])) {
                   89666:             $parent['children'] = array();
                   89667:             if ($parent['type'] != 'array') {
                   89668:                 $parent['type'] = 'array';
                   89669:             }
                   89670:         }
                   89671: 
                   89672:         if (!empty($value['name'])) {
                   89673:             // there already has been a tag with this name
                   89674:             if (in_array($value['name'], $parent['childrenKeys'])) {
                   89675:                 // no aggregate has been created for this tag
                   89676:                 if (!in_array($value['name'], $parent['aggregKeys'])) {
                   89677:                     if (isset($parent['children'][$value['name']])) {
                   89678:                         $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                   89679:                     } else {
                   89680:                         $parent['children'][$value['name']] = array();
                   89681:                     }
                   89682:                     array_push($parent['aggregKeys'], $value['name']);
                   89683:                 }
                   89684:                 array_push($parent['children'][$value['name']], $value['value']);
                   89685:             } else {
                   89686:                 $parent['children'][$value['name']] = &$value['value'];
                   89687:                 array_push($parent['childrenKeys'], $value['name']);
                   89688:             }
                   89689:         } else {
                   89690:             array_push($parent['children'],$value['value']);
                   89691:         }
                   89692:         array_push($this->_valStack, $parent);
                   89693: 
                   89694:         $this->_depth--;
                   89695:     }
                   89696: 
                   89697:     /**
                   89698:      * Handler for character data
                   89699:      *
                   89700:      * @access private
                   89701:      * @param  object XML parser object
                   89702:      * @param  string CDATA
                   89703:      * @return void
                   89704:      */
                   89705:     function cdataHandler($parser, $cdata)
                   89706:     {
                   89707:         $this->_dataStack[$this->_depth] .= $cdata;
                   89708:     }
                   89709: }<?php
                   89710: /**
                   89711:  * This is only meant for PHP 5 to get rid of certain strict warning
                   89712:  * that doesn't get hidden since it's in the shutdown function
                   89713:  */
                   89714: class PEAR5
                   89715: {
                   89716:     /**
                   89717:     * If you have a class that's mostly/entirely static, and you need static
                   89718:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   89719:     * do this: $myVar = &PEAR5::getStaticProperty('myclass', 'myVar');
                   89720:     * You MUST use a reference, or they will not persist!
                   89721:     *
                   89722:     * @access public
                   89723:     * @param  string $class  The calling classname, to prevent clashes
                   89724:     * @param  string $var    The variable to retrieve.
                   89725:     * @return mixed   A reference to the variable. If not set it will be
                   89726:     *                 auto initialised to NULL.
                   89727:     */
                   89728:     static function &getStaticProperty($class, $var)
                   89729:     {
                   89730:         static $properties;
                   89731:         if (!isset($properties[$class])) {
                   89732:             $properties[$class] = array();
                   89733:         }
                   89734: 
                   89735:         if (!array_key_exists($var, $properties[$class])) {
                   89736:             $properties[$class][$var] = null;
                   89737:         }
                   89738: 
                   89739:         return $properties[$class][$var];
                   89740:     }
                   89741: }<?php
                   89742: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   89743: // +-----------------------------------------------------------------------------+
                   89744: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   89745: // +-----------------------------------------------------------------------------+
                   89746: // | This file is part of Structures_Graph.                                      |
                   89747: // |                                                                             |
                   89748: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   89749: // | it under the terms of the GNU Lesser General Public License as published by |
                   89750: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   89751: // | (at your option) any later version.                                         |
                   89752: // |                                                                             |
                   89753: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   89754: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   89755: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   89756: // | GNU Lesser General Public License for more details.                         |
                   89757: // |                                                                             |
                   89758: // | You should have received a copy of the GNU Lesser General Public License    |
                   89759: // | along with Structures_Graph; if not, write to the Free Software             |
                   89760: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   89761: // | 02111-1307 USA                                                              |
                   89762: // +-----------------------------------------------------------------------------+
                   89763: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   89764: // +-----------------------------------------------------------------------------+
                   89765: //
                   89766: /**
                   89767:  * The Graph.php file contains the definition of the Structures_Graph class 
                   89768:  *
                   89769:  * @see Structures_Graph
                   89770:  * @package Structures_Graph
                   89771:  */
                   89772: 
                   89773: /* dependencies {{{ */
                   89774: /** PEAR base classes */
                   89775: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   89776: /** Graph Node */
                   89777: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   89778: /* }}} */
                   89779: 
                   89780: define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
                   89781: 
                   89782: /* class Structures_Graph {{{ */
                   89783: /**
                   89784:  * The Structures_Graph class represents a graph data structure. 
                   89785:  *
                   89786:  * A Graph is a data structure composed by a set of nodes, connected by arcs.
                   89787:  * Graphs may either be directed or undirected. In a directed graph, arcs are 
                   89788:  * directional, and can be traveled only one way. In an undirected graph, arcs
                   89789:  * are bidirectional, and can be traveled both ways.
                   89790:  *
                   89791:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   89792:  * @copyright  (c) 2004 by S閞gio Carvalho
                   89793:  * @package Structures_Graph
                   89794:  */
                   89795: /* }}} */
                   89796: class Structures_Graph {
                   89797:     /* fields {{{ */
                   89798:     /**
                   89799:      * @access private
                   89800:      */
                   89801:     var $_nodes = array();
                   89802:     /**
                   89803:      * @access private
                   89804:      */
                   89805:     var $_directed = false;
                   89806:     /* }}} */
                   89807: 
                   89808:     /* Constructor {{{ */
                   89809:     /**
                   89810:     *
                   89811:     * Constructor
                   89812:     *
                   89813:     * @param    boolean    Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)
                   89814:     * @access  public
                   89815:     */
                   89816:     function Structures_Graph($directed = true) {
                   89817:         $this->_directed = $directed;
                   89818:     }
                   89819:     /* }}} */
                   89820: 
                   89821:     /* isDirected {{{ */
                   89822:     /**
                   89823:     *
                   89824:     * Return true if a graph is directed
                   89825:     *
                   89826:     * @return  boolean  true if the graph is directed
                   89827:     * @access  public
                   89828:     */
                   89829:     function isDirected() {
                   89830:         return (boolean) $this->_directed;
                   89831:     }
                   89832:     /* }}} */
                   89833: 
                   89834:     /* addNode {{{ */
                   89835:     /**
                   89836:     *
                   89837:     * Add a Node to the Graph
                   89838:     *
                   89839:     * @param    Structures_Graph_Node   The node to be added.
                   89840:     * @access  public
                   89841:     */
                   89842:     function addNode(&$newNode) {
                   89843:         // We only add nodes
                   89844:         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);
                   89845:         // Graphs are node *sets*, so duplicates are forbidden. We allow nodes that are exactly equal, but disallow equal references.
                   89846:         foreach($this->_nodes as $key => $node) {
                   89847:             /*
                   89848:              ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object.
                   89849:              So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in 
                   89850:              $node)
                   89851:             */
                   89852:             $savedData = $this->_nodes[$key];
                   89853:             $referenceIsEqualFlag = false;
                   89854:             $this->_nodes[$key] = true;
                   89855:             if ($node === true) {
                   89856:                 $this->_nodes[$key] = false;
                   89857:                 if ($node === false) $referenceIsEqualFlag = true;
                   89858:             }
                   89859:             $this->_nodes[$key] = $savedData;
                   89860:             if ($referenceIsEqualFlag) return Pear::raiseError('Structures_Graph::addNode received an object that is a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC);
                   89861:         }
                   89862:         $this->_nodes[] =& $newNode;
                   89863:         $newNode->setGraph($this);
                   89864:     }
                   89865:     /* }}} */
                   89866: 
                   89867:     /* removeNode (unimplemented) {{{ */
                   89868:     /**
                   89869:     *
                   89870:     * Remove a Node from the Graph
                   89871:     *
                   89872:     * @todo     This is unimplemented
                   89873:     * @param    Structures_Graph_Node   The node to be removed from the graph
                   89874:     * @access  public
                   89875:     */
                   89876:     function removeNode(&$node) {
                   89877:     }
                   89878:     /* }}} */
                   89879: 
                   89880:     /* getNodes {{{ */
                   89881:     /**
                   89882:     *
                   89883:     * Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
                   89884:     *
                   89885:     * @access   public
                   89886:     * @see      Structures_Graph_Manipulator_TopologicalSorter
                   89887:     * @return   array The set of nodes in this graph
                   89888:     */
                   89889:     function &getNodes() {
                   89890:         return $this->_nodes;
                   89891:     }
                   89892:     /* }}} */
                   89893: }
                   89894: ?>
                   89895: <?php
                   89896: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   89897: // +-----------------------------------------------------------------------------+
                   89898: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   89899: // +-----------------------------------------------------------------------------+
                   89900: // | This file is part of Structures_Graph.                                      |
                   89901: // |                                                                             |
                   89902: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   89903: // | it under the terms of the GNU Lesser General Public License as published by |
                   89904: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   89905: // | (at your option) any later version.                                         |
                   89906: // |                                                                             |
                   89907: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   89908: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   89909: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   89910: // | GNU Lesser General Public License for more details.                         |
                   89911: // |                                                                             |
                   89912: // | You should have received a copy of the GNU Lesser General Public License    |
                   89913: // | along with Structures_Graph; if not, write to the Free Software             |
                   89914: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   89915: // | 02111-1307 USA                                                              |
                   89916: // +-----------------------------------------------------------------------------+
                   89917: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   89918: // +-----------------------------------------------------------------------------+
                   89919: //
                   89920: /**
                   89921:  * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
                   89922:  * 
                   89923:  * @see Structures_Graph_Manipulator_AcyclicTest
                   89924:  * @package Structures_Graph
                   89925:  */
                   89926: 
                   89927: /* dependencies {{{ */
                   89928: /** */
                   89929: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   89930: /** */
                   89931: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   89932: /** */
                   89933: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   89934: /* }}} */
                   89935: 
                   89936: /* class Structures_Graph_Manipulator_AcyclicTest {{{ */
                   89937: /**
                   89938:  * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
                   89939:  * which tests whether a graph contains a cycle. 
                   89940:  * 
                   89941:  * The definition of an acyclic graph used in this manipulator is that of a 
                   89942:  * DAG. The graph must be directed, or else it is considered cyclic, even when 
                   89943:  * there are no arcs.
                   89944:  *
                   89945:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   89946:  * @copyright  (c) 2004 by S閞gio Carvalho
                   89947:  * @package Structures_Graph
                   89948:  */
                   89949: class Structures_Graph_Manipulator_AcyclicTest {
                   89950:     /* _nonVisitedInDegree {{{ */
                   89951:     /**
                   89952:     *
                   89953:     * This is a variant of Structures_Graph::inDegree which does 
                   89954:     * not count nodes marked as visited.
                   89955:     *
                   89956:     * @access   private
                   89957:     * @return  integer  Number of non-visited nodes that link to this one
                   89958:     */
                   89959:     function _nonVisitedInDegree(&$node) {
                   89960:         $result = 0;
                   89961:         $graphNodes =& $node->_graph->getNodes();
                   89962:         foreach (array_keys($graphNodes) as $key) {
                   89963:             if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   89964:         }
                   89965:         return $result;
                   89966:         
                   89967:     }
                   89968:     /* }}} */
                   89969: 
                   89970:     /* _isAcyclic {{{ */
                   89971:     /**
                   89972:     * @access   private
                   89973:     */
                   89974:     function _isAcyclic(&$graph) {
                   89975:         // Mark every node as not visited
                   89976:         $nodes =& $graph->getNodes();
                   89977:         $nodeKeys = array_keys($nodes);
                   89978:         $refGenerator = array();
                   89979:         foreach($nodeKeys as $key) {
                   89980:             $refGenerator[] = false;
                   89981:             $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   89982:         }
                   89983: 
                   89984:         // Iteratively peel off leaf nodes
                   89985:         do {
                   89986:             // Find out which nodes are leafs (excluding visited nodes)
                   89987:             $leafNodes = array();
                   89988:             foreach($nodeKeys as $key) {
                   89989:                 if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
                   89990:                     $leafNodes[] =& $nodes[$key];
                   89991:                 }
                   89992:             }
                   89993:             // Mark leafs as visited
                   89994:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   89995:                 $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
                   89996:                 $visited = true;
                   89997:                 $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
                   89998:             }
                   89999:         } while (sizeof($leafNodes) > 0);
                   90000: 
                   90001:         // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
                   90002:         $result = true;
                   90003:         foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
                   90004:         
                   90005:         // Cleanup visited marks
                   90006:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
                   90007: 
                   90008:         return $result;
                   90009:     }
                   90010:     /* }}} */
                   90011: 
                   90012:     /* isAcyclic {{{ */
                   90013:     /**
                   90014:     *
                   90015:     * isAcyclic returns true if a graph contains no cycles, false otherwise.
                   90016:     *
                   90017:     * @return  boolean  true iff graph is acyclic
                   90018:     * @access  public
                   90019:     */
                   90020:     function isAcyclic(&$graph) {
                   90021:         // We only test graphs
                   90022:         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);
                   90023:         if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
                   90024: 
                   90025:         return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
                   90026:     }
                   90027:     /* }}} */
                   90028: }
                   90029: /* }}} */
                   90030: ?>
                   90031: <?php
                   90032: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   90033: // +-----------------------------------------------------------------------------+
                   90034: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   90035: // +-----------------------------------------------------------------------------+
                   90036: // | This file is part of Structures_Graph.                                      |
                   90037: // |                                                                             |
                   90038: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   90039: // | it under the terms of the GNU Lesser General Public License as published by |
                   90040: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   90041: // | (at your option) any later version.                                         |
                   90042: // |                                                                             |
                   90043: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   90044: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   90045: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   90046: // | GNU Lesser General Public License for more details.                         |
                   90047: // |                                                                             |
                   90048: // | You should have received a copy of the GNU Lesser General Public License    |
                   90049: // | along with Structures_Graph; if not, write to the Free Software             |
                   90050: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   90051: // | 02111-1307 USA                                                              |
                   90052: // +-----------------------------------------------------------------------------+
                   90053: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   90054: // +-----------------------------------------------------------------------------+
                   90055: //
                   90056: /**
                   90057:  * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
                   90058:  * 
                   90059:  * @see Structures_Graph_Manipulator_TopologicalSorter
                   90060:  * @package Structures_Graph
                   90061:  */
                   90062: 
                   90063: /* dependencies {{{ */
                   90064: /** */
                   90065: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   90066: /** */
                   90067: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   90068: /** */
                   90069: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   90070: /** */
                   90071: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Manipulator/AcyclicTest.php';
                   90072: /* }}} */
                   90073: 
                   90074: /* class Structures_Graph_Manipulator_TopologicalSorter {{{ */
                   90075: /**
                   90076:  * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator 
                   90077:  * which is able to return the set of nodes in a graph, sorted by topological 
                   90078:  * order.
                   90079:  *
                   90080:  * A graph may only be sorted topologically iff it's a DAG. You can test it
                   90081:  * with the Structures_Graph_Manipulator_AcyclicTest.
                   90082:  * 
                   90083:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   90084:  * @copyright  (c) 2004 by S閞gio Carvalho
                   90085:  * @see     Structures_Graph_Manipulator_AcyclicTest
                   90086:  * @package Structures_Graph
                   90087:  */
                   90088: class Structures_Graph_Manipulator_TopologicalSorter {
                   90089:     /* _nonVisitedInDegree {{{ */
                   90090:     /**
                   90091:     *
                   90092:     * This is a variant of Structures_Graph::inDegree which does 
                   90093:     * not count nodes marked as visited.
                   90094:     *
                   90095:     * @access   private
                   90096:     * @return  integer  Number of non-visited nodes that link to this one
                   90097:     */
                   90098:     function _nonVisitedInDegree(&$node) {
                   90099:         $result = 0;
                   90100:         $graphNodes =& $node->_graph->getNodes();
                   90101:         foreach (array_keys($graphNodes) as $key) {
                   90102:             if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   90103:         }
                   90104:         return $result;
                   90105:         
                   90106:     }
                   90107:     /* }}} */
                   90108: 
                   90109:     /* _sort {{{ */
                   90110:     /**
                   90111:     * @access   private
                   90112:     */
                   90113:     function _sort(&$graph) {
                   90114:         // Mark every node as not visited
                   90115:         $nodes =& $graph->getNodes();
                   90116:         $nodeKeys = array_keys($nodes);
                   90117:         $refGenerator = array();
                   90118:         foreach($nodeKeys as $key) {
                   90119:             $refGenerator[] = false;
                   90120:             $nodes[$key]->setMetadata('topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   90121:         }
                   90122: 
                   90123:         // Iteratively peel off leaf nodes
                   90124:         $topologicalLevel = 0;
                   90125:         do {
                   90126:             // Find out which nodes are leafs (excluding visited nodes)
                   90127:             $leafNodes = array();
                   90128:             foreach($nodeKeys as $key) {
                   90129:                 if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && Structures_Graph_Manipulator_TopologicalSorter::_nonVisitedInDegree($nodes[$key]) == 0) {
                   90130:                     $leafNodes[] =& $nodes[$key];
                   90131:                 }
                   90132:             }
                   90133:             // Mark leafs as visited
                   90134:             $refGenerator[] = $topologicalLevel;
                   90135:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   90136:                 $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
                   90137:                 $visited = true;
                   90138:                 $leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
                   90139:                 $leafNodes[$i]->setMetadata('topological-sort-level', $refGenerator[sizeof($refGenerator) - 1]);
                   90140:             }
                   90141:             $topologicalLevel++;
                   90142:         } while (sizeof($leafNodes) > 0);
                   90143: 
                   90144:         // Cleanup visited marks
                   90145:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('topological-sort-visited');
                   90146:     }
                   90147:     /* }}} */
                   90148: 
                   90149:     /* sort {{{ */
                   90150:     /**
                   90151:     *
                   90152:     * sort returns the graph's nodes, sorted by topological order. 
                   90153:     * 
                   90154:     * The result is an array with 
                   90155:     * as many entries as topological levels. Each entry in this array is an array of nodes within
                   90156:     * the given topological level.
                   90157:     *
                   90158:     * @return  array    The graph's nodes, sorted by topological order.
                   90159:     * @access  public
                   90160:     */
                   90161:     function sort(&$graph) {
                   90162:         // We only sort graphs
                   90163:         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);
                   90164:         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);
                   90165: 
                   90166:         Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
                   90167:         $result = array();
                   90168: 
                   90169:         // Fill out result array
                   90170:         $nodes =& $graph->getNodes();
                   90171:         $nodeKeys = array_keys($nodes);
                   90172:         foreach($nodeKeys as $key) {
                   90173:             if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) $result[$nodes[$key]->getMetadata('topological-sort-level')] = array();
                   90174:             $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key];
                   90175:             $nodes[$key]->unsetMetadata('topological-sort-level');
                   90176:         }
                   90177: 
                   90178:         return $result;
                   90179:     }
                   90180:     /* }}} */
                   90181: }
                   90182: /* }}} */
                   90183: ?>
                   90184: <?php
                   90185: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   90186: // +-----------------------------------------------------------------------------+
                   90187: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   90188: // +-----------------------------------------------------------------------------+
                   90189: // | This file is part of Structures_Graph.                                      |
                   90190: // |                                                                             |
                   90191: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   90192: // | it under the terms of the GNU Lesser General Public License as published by |
                   90193: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   90194: // | (at your option) any later version.                                         |
                   90195: // |                                                                             |
                   90196: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   90197: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   90198: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   90199: // | GNU Lesser General Public License for more details.                         |
                   90200: // |                                                                             |
                   90201: // | You should have received a copy of the GNU Lesser General Public License    |
                   90202: // | along with Structures_Graph; if not, write to the Free Software             |
                   90203: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   90204: // | 02111-1307 USA                                                              |
                   90205: // +-----------------------------------------------------------------------------+
                   90206: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   90207: // +-----------------------------------------------------------------------------+
                   90208: //
                   90209: /**
                   90210:  * This file contains the definition of the Structures_Graph_Node class
                   90211:  * 
                   90212:  * @see Structures_Graph_Node
                   90213:  * @package Structures_Graph
                   90214:  */
                   90215: 
                   90216: /* dependencies {{{ */
                   90217: /** */
                   90218: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   90219: /** */
                   90220: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   90221: /* }}} */
                   90222: 
                   90223: /* class Structures_Graph_Node {{{ */
                   90224: /**
                   90225:  * The Structures_Graph_Node class represents a Node that can be member of a 
                   90226:  * graph node set.
                   90227:  *
                   90228:  * A graph node can contain data. Under this API, the node contains default data, 
                   90229:  * and key index data. It behaves, thus, both as a regular data node, and as a 
                   90230:  * dictionary (or associative array) node.
                   90231:  * 
                   90232:  * Regular data is accessed via getData and setData. Key indexed data is accessed
                   90233:  * via getMetadata and setMetadata.
                   90234:  *
                   90235:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   90236:  * @copyright  (c) 2004 by S閞gio Carvalho
                   90237:  * @package Structures_Graph
                   90238:  */
                   90239: /* }}} */
                   90240: class Structures_Graph_Node {
                   90241:     /* fields {{{ */
                   90242:     /** 
                   90243:      * @access private 
                   90244:      */
                   90245:     var $_data = null;
                   90246:     /** @access private */
                   90247:     var $_metadata = array();
                   90248:     /** @access private */
                   90249:     var $_arcs = array();
                   90250:     /** @access private */
                   90251:     var $_graph = null;
                   90252:     /* }}} */
                   90253: 
                   90254:     /* Constructor {{{ */
                   90255:     /**
                   90256:     *
                   90257:     * Constructor
                   90258:     *
                   90259:     * @access  public
                   90260:     */
                   90261:     function Structures_Graph_Node() {
                   90262:     }
                   90263:     /* }}} */
                   90264: 
                   90265:     /* getGraph {{{ */
                   90266:     /**
                   90267:     *
                   90268:     * Node graph getter
                   90269:     *
                   90270:     * @return  Structures_Graph        Graph where node is stored
                   90271:     * @access  public
                   90272:     */
                   90273:     function &getGraph() {
                   90274:         return $this->_graph;
                   90275:     }
                   90276:     /* }}} */
                   90277: 
                   90278:     /* setGraph {{{ */
                   90279:     /**
                   90280:     *
                   90281:     * Node graph setter. This method should not be called directly. Use Graph::addNode instead.
                   90282:     *
                   90283:     * @param    Structures_Graph   Set the graph for this node. 
                   90284:     * @see      Structures_Graph::addNode()
                   90285:     * @access  public
                   90286:     */
                   90287:     function setGraph(&$graph) {
                   90288:         $this->_graph =& $graph;
                   90289:     }
                   90290:     /* }}} */
                   90291: 
                   90292:     /* getData {{{ */
                   90293:     /**
                   90294:     *
                   90295:     * Node data getter.
                   90296:     * 
                   90297:     * Each graph node can contain a reference to one variable. This is the getter for that reference.
                   90298:     *
                   90299:     * @return  mixed   Data stored in node
                   90300:     * @access  public
                   90301:     */
                   90302:     function &getData() {
                   90303:         return $this->_data;
                   90304:     }
                   90305:     /* }}} */
                   90306: 
                   90307:     /* setData {{{ */
                   90308:     /**
                   90309:     *
                   90310:     * Node data setter
                   90311:     *
                   90312:     * Each graph node can contain a reference to one variable. This is the setter for that reference.
                   90313:     *
                   90314:     * @return  mixed   Data to store in node
                   90315:     * @access  public
                   90316:     */
                   90317:     function setData($data) {
                   90318:         $this->_data =& $data;
                   90319:     }
                   90320:     /* }}} */
                   90321: 
                   90322:     /* metadataKeyExists {{{ */
                   90323:     /**
                   90324:     *
                   90325:     * Test for existence of metadata under a given key.
                   90326:     *
                   90327:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   90328:     * associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
                   90329:     *
                   90330:     * @param    string    Key to test
                   90331:     * @return  boolean  
                   90332:     * @access  public
                   90333:     */
                   90334:     function metadataKeyExists($key) {
                   90335:         return array_key_exists($key, $this->_metadata);
                   90336:     }
                   90337:     /* }}} */
                   90338: 
                   90339:     /* getMetadata {{{ */
                   90340:     /**
                   90341:     *
                   90342:     * Node metadata getter
                   90343:     *
                   90344:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   90345:     * associative array or in a dictionary. This method gets the data under the given key. If the key does
                   90346:     * not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
                   90347:     *
                   90348:     * @param    string  Key
                   90349:     * @param    boolean nullIfNonexistent (defaults to false).
                   90350:     * @return  mixed   Metadata Data stored in node under given key
                   90351:     * @see      metadataKeyExists
                   90352:     * @access  public
                   90353:     */
                   90354:     function &getMetadata($key, $nullIfNonexistent = false) {
                   90355:         if (array_key_exists($key, $this->_metadata)) {
                   90356:             return $this->_metadata[$key];
                   90357:         } else {
                   90358:             if ($nullIfNonexistent) {
                   90359:                 $a = null;
                   90360:                 return $a;
                   90361:             } else {
                   90362:                 $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
                   90363:                 return $a;
                   90364:             }
                   90365:         }
                   90366:     }
                   90367:     /* }}} */
                   90368: 
                   90369:     /* unsetMetadata {{{ */
                   90370:     /**
                   90371:     *
                   90372:     * Delete metadata by key
                   90373:     *
                   90374:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   90375:     * associative array or in a dictionary. This method removes any data that might be stored under the provided key.
                   90376:     * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
                   90377:     *
                   90378:     * @param    string  Key
                   90379:     * @access  public
                   90380:     */
                   90381:     function unsetMetadata($key) {
                   90382:         if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
                   90383:     }
                   90384:     /* }}} */
                   90385: 
                   90386:     /* setMetadata {{{ */
                   90387:     /**
                   90388:     *
                   90389:     * Node metadata setter
                   90390:     *
                   90391:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   90392:     * associative array or in a dictionary. This method stores data under the given key. If the key already exists,
                   90393:     * previously stored data is discarded.
                   90394:     *
                   90395:     * @param    string  Key
                   90396:     * @param    mixed   Data 
                   90397:     * @access  public
                   90398:     */
                   90399:     function setMetadata($key, $data) {
                   90400:         $this->_metadata[$key] =& $data;
                   90401:     }
                   90402:     /* }}} */
                   90403: 
                   90404:     /* _connectTo {{{ */
                   90405:     /** @access private */
                   90406:     function _connectTo(&$destinationNode) {
                   90407:         $this->_arcs[] =& $destinationNode;
                   90408:     }
                   90409:     /* }}} */
                   90410: 
                   90411:     /* connectTo {{{ */
                   90412:     /**
                   90413:     *
                   90414:     * Connect this node to another one.
                   90415:     * 
                   90416:     * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
                   90417:     *
                   90418:     * @param    Structures_Graph_Node Node to connect to
                   90419:     * @access  public
                   90420:     */
                   90421:     function connectTo(&$destinationNode) {
                   90422:         // We only connect to nodes
                   90423:         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);
                   90424:         // Nodes must already be in graphs to be connected
                   90425:         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);
                   90426:         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);
                   90427:         // Connect here
                   90428:         $this->_connectTo($destinationNode);
                   90429:         // If graph is undirected, connect back
                   90430:         if (!$this->_graph->isDirected()) {
                   90431:             $destinationNode->_connectTo($this);
                   90432:         }
                   90433:     }
                   90434:     /* }}} */
                   90435: 
                   90436:     /* getNeighbours {{{ */
                   90437:     /**
                   90438:     *
                   90439:     * Return nodes connected to this one.
                   90440:     * 
                   90441:     * @return   array   Array of nodes
                   90442:     * @access  public
                   90443:     */
                   90444:     function getNeighbours() {
                   90445:         return $this->_arcs;
                   90446:     }
                   90447:     /* }}} */
                   90448: 
                   90449:     /* connectsTo {{{ */
                   90450:     /**
                   90451:     *
                   90452:     * Test wether this node has an arc to the target node
                   90453:     *
                   90454:     * @return  boolean   True if the two nodes are connected
                   90455:     * @access  public
                   90456:     */
                   90457:     function connectsTo(&$target) {
                   90458:         if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
                   90459:             return in_array($target, $this->getNeighbours(), true);
                   90460:         }
                   90461: 
                   90462:         $copy = $target;
                   90463:         $arcKeys = array_keys($this->_arcs);
                   90464:         foreach($arcKeys as $key) {
                   90465:             /* ZE1 chokes on this expression:
                   90466:                 if ($target === $arc) return true;
                   90467:               so, we'll use more convoluted stuff
                   90468:             */
                   90469:             $arc =& $this->_arcs[$key];
                   90470:             $target = true;
                   90471:             if ($arc === true) {
                   90472:                 $target = false;
                   90473:                 if ($arc === false) {
                   90474:                     $target = $copy;
                   90475:                     return true;
                   90476:                 }
                   90477:             }
                   90478:         }
                   90479:         $target = $copy;
                   90480:         return false;
                   90481:     }
                   90482:     /* }}} */
                   90483: 
                   90484:     /* inDegree {{{ */
                   90485:     /**
                   90486:     *
                   90487:     * Calculate the in degree of the node.
                   90488:     * 
                   90489:     * The indegree for a node is the number of arcs entering the node. For non directed graphs, 
                   90490:     * the indegree is equal to the outdegree.
                   90491:     *
                   90492:     * @return  integer  In degree of the node
                   90493:     * @access  public
                   90494:     */
                   90495:     function inDegree() {
                   90496:         if ($this->_graph == null) return 0;
                   90497:         if (!$this->_graph->isDirected()) return $this->outDegree();
                   90498:         $result = 0;
                   90499:         $graphNodes =& $this->_graph->getNodes();
                   90500:         foreach (array_keys($graphNodes) as $key) {
                   90501:             if ($graphNodes[$key]->connectsTo($this)) $result++;
                   90502:         }
                   90503:         return $result;
                   90504:         
                   90505:     }
                   90506:     /* }}} */
                   90507: 
                   90508:     /* outDegree {{{ */
                   90509:     /**
                   90510:     *
                   90511:     * Calculate the out degree of the node.
                   90512:     *
                   90513:     * The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
                   90514:     * the outdegree is always equal to the indegree.
                   90515:     * 
                   90516:     * @return  integer  Out degree of the node
                   90517:     * @access  public
                   90518:     */
                   90519:     function outDegree() {
                   90520:         if ($this->_graph == null) return 0;
                   90521:         return sizeof($this->_arcs);
                   90522:     }
                   90523:     /* }}} */
                   90524: }
                   90525: ?>
                   90526: package.xml0000644000076600000240000001543011461440276012461 0ustar  bbieberstaff<?xml version="1.0" encoding="UTF-8"?>
                   90527: <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">
                   90528:  <name>Structures_Graph</name>
                   90529:  <channel>pear.php.net</channel>
                   90530:  <summary>Graph datastructure manipulation library</summary>
                   90531:  <description>Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed
                   90532: and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing
                   90533: as well as for characteristic extraction from the graph topology.</description>
                   90534:  <lead>
                   90535:   <name>S茅rgio Carvalho</name>
                   90536:   <user>sergiosgc</user>
                   90537:   <email>sergio.carvalho@portugalmail.com</email>
                   90538:   <active>yes</active>
                   90539:  </lead>
                   90540:  <helper>
                   90541:   <name>Brett Bieber</name>
                   90542:   <user>saltybeagle</user>
                   90543:   <email>brett.bieber@gmail.com</email>
                   90544:   <active>yes</active>
                   90545:  </helper>
                   90546:  <date>2010-10-25</date>
                   90547:  <time>21:45:17</time>
                   90548:  <version>
                   90549:   <release>1.0.4</release>
                   90550:   <api>1.0.3</api>
                   90551:  </version>
                   90552:  <stability>
                   90553:   <release>stable</release>
                   90554:   <api>stable</api>
                   90555:  </stability>
                   90556:  <license>LGPL License</license>
                   90557:  <notes>
                   90558: Bugfix Release:
                   90559: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx]
                   90560:  </notes>
                   90561:  <contents>
                   90562:   <dir baseinstalldir="/" name="/">
                   90563:    <file baseinstalldir="/" md5sum="e43ca110d02f287cdaac6357ba539fff" name="docs/html/media/banner.css" role="doc" />
                   90564:    <file baseinstalldir="/" md5sum="296dd865297508569a6e72fcfd20fa81" name="docs/html/media/stylesheet.css" role="doc" />
                   90565:    <file baseinstalldir="/" md5sum="678ccf89e31bc7337803afd6b7c58827" name="docs/html/Structures_Graph/Structures_Graph.html" role="doc" />
                   90566:    <file baseinstalldir="/" md5sum="686b7bd7108cf5ce9b1ae5f17cea79f4" name="docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html" role="doc" />
                   90567:    <file baseinstalldir="/" md5sum="08b05a395eca4b0ca49a956fadf83da6" name="docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html" role="doc" />
                   90568:    <file baseinstalldir="/" md5sum="3fa8a9fae581fc31fd1dfbb14f475f92" name="docs/html/Structures_Graph/Structures_Graph_Node.html" role="doc" />
                   90569:    <file baseinstalldir="/" md5sum="fd9b59eb75a39d3a25a175660dfb12be" name="docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html" role="doc" />
                   90570:    <file baseinstalldir="/" md5sum="9cfeca2ff35a44b4bb921a9a818d8fa6" name="docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html" role="doc" />
                   90571:    <file baseinstalldir="/" md5sum="4faffdcc81cbc92520104e90a651a971" name="docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html" role="doc" />
                   90572:    <file baseinstalldir="/" md5sum="0337573b69355c8b7ad36cd8f40ce859" name="docs/html/Structures_Graph/_Structures_Graph_Node_php.html" role="doc" />
                   90573:    <file baseinstalldir="/" md5sum="7c1f852d7aa1a2fcada473723c8a46c2" name="docs/html/Structures_Graph/_Structures_Graph_php.html" role="doc" />
                   90574:    <file baseinstalldir="/" md5sum="238f8a9d335e49ef87a0a276bcfc7231" name="docs/html/classtrees_Structures_Graph.html" role="doc" />
                   90575:    <file baseinstalldir="/" md5sum="e302b63d3b18fa1c6e13f76816564d39" name="docs/html/elementindex.html" role="doc" />
                   90576:    <file baseinstalldir="/" md5sum="c97ebad7c5635abbbbf35a23e868649e" name="docs/html/elementindex_Structures_Graph.html" role="doc" />
                   90577:    <file baseinstalldir="/" md5sum="6f58a7616dd96fb8cc0cbf928f66dd33" name="docs/html/errors.html" role="doc" />
                   90578:    <file baseinstalldir="/" md5sum="cf5397f529a0d9a701fac13ac6aaaa69" name="docs/html/index.html" role="doc" />
                   90579:    <file baseinstalldir="/" md5sum="b206403136db1de58901f825ad9f9cb0" name="docs/html/li_Structures_Graph.html" role="doc" />
                   90580:    <file baseinstalldir="/" md5sum="a88b0fcc2f97dd2069f671ef1dc92b40" name="docs/html/packages.html" role="doc" />
                   90581:    <file baseinstalldir="/" md5sum="6fdd16675f2181b53a4d2dc2c419752b" name="docs/html/todolist.html" role="doc" />
                   90582:    <file baseinstalldir="/" md5sum="628eb6532a8047bf5962fe24c1c245df" name="docs/tutorials/Structures_Graph/Structures_Graph.pkg" role="doc" />
                   90583:    <file baseinstalldir="/" md5sum="ce2da39dbb75e21074eb5e96231a3379" name="docs/generate.sh" role="doc" />
                   90584:    <file baseinstalldir="/" md5sum="f0aff5a1efd188d63b4b8b9e9e840b97" name="Structures/Graph/Manipulator/AcyclicTest.php" role="php" />
                   90585:    <file baseinstalldir="/" md5sum="0492e677436d29228df93dca23629e06" name="Structures/Graph/Manipulator/TopologicalSorter.php" role="php" />
                   90586:    <file baseinstalldir="/" md5sum="254ebaba7537ad0f36e63eb8b975cc51" name="Structures/Graph/Node.php" role="php" />
                   90587:    <file baseinstalldir="/" md5sum="4f25a6275af156f6f8e7b4309cb9f40d" name="Structures/Graph.php" role="php" />
                   90588:    <file baseinstalldir="/" md5sum="5791baa61d5d36442be58ea5cd9d4bd0" name="tests/testCase/BasicGraph.php" role="test" />
                   90589:    <file baseinstalldir="/" md5sum="4fed49ef60db01eed800105aae4f2c8b" name="tests/AllTests.php" role="test" />
                   90590:    <file baseinstalldir="/" md5sum="7fbc338309ac38fefcd64b04bb903e34" name="LICENSE" role="data" />
                   90591:   </dir>
                   90592:  </contents>
                   90593:  <compatible>
                   90594:   <name>PEAR</name>
                   90595:   <channel>pear.php.net</channel>
                   90596:   <min>1.5.0RC3</min>
                   90597:   <max>1.9.1</max>
                   90598:  </compatible>
                   90599:  <dependencies>
                   90600:   <required>
                   90601:    <php>
                   90602:     <min>4.2.0</min>
                   90603:    </php>
                   90604:    <pearinstaller>
                   90605:     <min>1.4.3</min>
                   90606:    </pearinstaller>
                   90607:   </required>
                   90608:  </dependencies>
                   90609:  <phprelease />
                   90610:  <changelog>
                   90611:   <release>
                   90612:    <version>
                   90613:     <release>1.0.2</release>
                   90614:     <api>1.0.0</api>
                   90615:    </version>
                   90616:    <stability>
                   90617:     <release>stable</release>
                   90618:     <api>stable</api>
                   90619:    </stability>
                   90620:    <date>2007-01-07</date>
                   90621:    <license uri="http://opensource.org/licenses/lgpl-license.php">LGPL</license>
                   90622:    <notes>
                   90623: - Bug #9682 only variables can be returned by reference
                   90624: - fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()
                   90625:    </notes>
                   90626:   </release>
                   90627:   <release>
                   90628:    <version>
                   90629:     <release>1.0.3</release>
                   90630:     <api>1.0.3</api>
                   90631:    </version>
                   90632:    <stability>
                   90633:     <release>stable</release>
                   90634:     <api>stable</api>
                   90635:    </stability>
                   90636:    <date>2009-10-11</date>
                   90637:    <license>LGPL License</license>
                   90638:    <notes>
                   90639: Bugfix Release:
                   90640: Version 1.0.3 is functionally equivalent to 1.0.2 but with an updated package.xml file.
                   90641: * Correct invalid md5 sum preventing installation with pyrus [saltybeagle]
                   90642: * Add compatible tag for PEAR 1.5.0RC3-1.9.0 [saltybeagle]
                   90643: * Update package.xml
                   90644:    </notes>
                   90645:   </release>
                   90646:   <release>
                   90647:    <version>
                   90648:     <release>1.0.4</release>
                   90649:     <api>1.0.3</api>
                   90650:    </version>
                   90651:    <stability>
                   90652:     <release>stable</release>
                   90653:     <api>stable</api>
                   90654:    </stability>
                   90655:    <date>2010-10-25</date>
                   90656:    <license>LGPL License</license>
                   90657:    <notes>
                   90658: Bugfix Release:
                   90659: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx]
                   90660:    </notes>
                   90661:   </release>
                   90662:  </changelog>
                   90663: </package>
                   90664: Structures_Graph-1.0.4/docs/html/media/banner.css0000644000076600000240000000061111461440275021232 0ustar  bbieberstaffbody 
                   90665: { 
                   90666:        background-color: #CCCCFF; 
                   90667:        margin: 0px; 
                   90668:        padding: 0px;
                   90669: }
                   90670: 
                   90671: /* Banner (top bar) classes */
                   90672: 
                   90673: .banner {  }
                   90674: 
                   90675: .banner-menu 
                   90676: { 
                   90677:        clear: both;
                   90678:        padding: .5em;
                   90679:        border-top: 2px solid #6666AA;  
                   90680: }
                   90681: 
                   90682: .banner-title 
                   90683: { 
                   90684:        text-align: right; 
                   90685:        font-size: 20pt; 
                   90686:        font-weight: bold; 
                   90687:        margin: .2em;
                   90688: }
                   90689: 
                   90690: .package-selector 
                   90691: { 
                   90692:        background-color: #AAAADD; 
                   90693:        border: 1px solid black; 
                   90694:        color: yellow;
                   90695: }
                   90696: Structures_Graph-1.0.4/docs/html/media/stylesheet.css0000644000076600000240000001160411461440275022162 0ustar  bbieberstaffa { color: #336699; text-decoration: none; }
                   90697: a:hover { color: #6699CC; text-decoration: underline; }
                   90698: a:active { color: #6699CC; text-decoration: underline; }
                   90699: 
                   90700: body { background : #FFFFFF; }
                   90701: body, table { font-family: Georgia, Times New Roman, Times, serif; font-size: 10pt }
                   90702: p, li { line-height: 140% }
                   90703: a img { border: 0px; }
                   90704: dd { margin-left: 0px; padding-left: 1em; }
                   90705: 
                   90706: /* Page layout/boxes */
                   90707: 
                   90708: .info-box {}
                   90709: .info-box-title { margin: 1em 0em 0em 0em; padding: .25em; font-weight: normal; font-size: 14pt; border: 2px solid #999999; background-color: #CCCCFF }
                   90710: .info-box-body { border: 1px solid #999999; padding: .5em; }
                   90711: .nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; }
                   90712: 
                   90713: .oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
                   90714: .evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
                   90715: 
                   90716: .page-body { max-width: 800px; margin: auto; }
                   90717: .tree dl { margin: 0px }
                   90718: 
                   90719: /* Index formatting classes */
                   90720: 
                   90721: .index-item-body { margin-top: .5em; margin-bottom: .5em}
                   90722: .index-item-description { margin-top: .25em }
                   90723: .index-item-details { font-weight: normal; font-style: italic; font-size: 8pt }
                   90724: .index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em}
                   90725: .index-letter-title { font-size: 12pt; font-weight: bold }
                   90726: .index-letter-menu { text-align: center; margin: 1em }
                   90727: .index-letter { font-size: 12pt }
                   90728: 
                   90729: /* Docbook classes */
                   90730: 
                   90731: .description {}
                   90732: .short-description { font-weight: bold; color: #666666; }
                   90733: .tags {        padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; }
                   90734: .parameters {  padding-left: 0em; margin-left: 3em; font-style: italic; list-style-type: square; }
                   90735: .redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; }
                   90736: .package {  }
                   90737: .package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black }
                   90738: .package-details { font-size: 85%; }
                   90739: .sub-package { font-weight: bold; font-size: 120% }
                   90740: .tutorial { border-width: thin; border-color: #0066ff }
                   90741: .tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; }
                   90742: .nav-button-disabled { color: #999999; }
                   90743: .nav-button:active, 
                   90744: .nav-button:focus, 
                   90745: .nav-button:hover { background-color: #DDDDDD; outline: 1px solid #999999; text-decoration: none }
                   90746: .folder-title { font-style: italic }
                   90747: 
                   90748: /* Generic formatting */
                   90749: 
                   90750: .field { font-weight: bold; }
                   90751: .detail { font-size: 8pt; }
                   90752: .notes { font-style: italic; font-size: 8pt; }
                   90753: .separator { background-color: #999999; height: 2px; }
                   90754: .warning {  color: #FF6600; }
                   90755: .disabled { font-style: italic; color: #999999; }
                   90756: 
                   90757: /* Code elements */
                   90758: 
                   90759: .line-number {  }
                   90760: 
                   90761: .class-table { width: 100%; }
                   90762: .class-table-header { border-bottom: 1px dotted #666666; text-align: left}
                   90763: .class-name { color: #000000; font-weight: bold; }
                   90764: 
                   90765: .method-summary { padding-left: 1em; font-size: 8pt }
                   90766: .method-header { }
                   90767: .method-definition { margin-bottom: .3em }
                   90768: .method-title { font-weight: bold; }
                   90769: .method-name { font-weight: bold; }
                   90770: .method-signature { font-size: 85%; color: #666666; margin: .5em 0em }
                   90771: .method-result { font-style: italic; }
                   90772: 
                   90773: .var-summary { padding-left: 1em; font-size: 8pt; }
                   90774: .var-header { }
                   90775: .var-title { margin-bottom: .3em }
                   90776: .var-type { font-style: italic; }
                   90777: .var-name { font-weight: bold; }
                   90778: .var-default {}
                   90779: .var-description { font-weight: normal; color: #000000; }
                   90780: 
                   90781: .include-title {  }
                   90782: .include-type { font-style: italic; }
                   90783: .include-name { font-weight: bold; }
                   90784: 
                   90785: .const-title {  }
                   90786: .const-name { font-weight: bold; }
                   90787: 
                   90788: /* Syntax highlighting */
                   90789: 
                   90790: .src-code {  border: 1px solid #336699; padding: 1em; background-color: #EEEEEE; }
                   90791: 
                   90792: .src-comm { color: green; }
                   90793: .src-id {  }
                   90794: .src-inc { color: #0000FF; }
                   90795: .src-key { color: #0000FF; }
                   90796: .src-num { color: #CC0000; }
                   90797: .src-str { color: #66cccc; }
                   90798: .src-sym { font-weight: bold; }
                   90799: .src-var { }
                   90800: 
                   90801: .src-php { font-weight: bold; }
                   90802: 
                   90803: .src-doc { color: #009999 }
                   90804: .src-doc-close-template { color: #0000FF }
                   90805: .src-doc-coretag { color: #0099FF; font-weight: bold }
                   90806: .src-doc-inlinetag { color: #0099FF }
                   90807: .src-doc-internal { color: #6699cc }
                   90808: .src-doc-tag { color: #0080CC }
                   90809: .src-doc-template { color: #0000FF }
                   90810: .src-doc-type { font-style: italic }
                   90811: .src-doc-var { font-style: italic }
                   90812: 
                   90813: /* tutorial */
                   90814: 
                   90815: .authors {  }
                   90816: .author { font-style: italic; font-weight: bold }
                   90817: .author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal }
                   90818: .example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em }
                   90819: .listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap }
                   90820: .release-info { font-size: 85%; font-style: italic; margin: 1em 0em }
                   90821: .ref-title-box {  }
                   90822: .ref-title {  }
                   90823: .ref-purpose { font-style: italic; color: #666666 }
                   90824: .ref-synopsis {  }
                   90825: .title { font-weight: bold; margin: 1em 0em 0em 0em; padding: .25em; border: 2px solid #999999; background-color: #CCCCFF  }
                   90826: .cmd-synopsis { margin: 1em 0em }
                   90827: .cmd-title { font-weight: bold }
                   90828: .toc { margin-left: 2em; padding-left: 0em }
                   90829: 
                   90830: Structures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph.html0000644000076600000240000002127311461440275025701 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   90831: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   90832:   <html xmlns="http://www.w3.org/1999/xhtml">
                   90833:                <head>
                   90834:                        <!-- template designed by Marco Von Ballmoos -->
                   90835:                        <title>Docs For Class Structures_Graph</title>
                   90836:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   90837:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   90838:                </head>
                   90839:                <body>
                   90840:                        <div class="page-body">                 
                   90841: <h2 class="class-name">Class Structures_Graph</h2>
                   90842: 
                   90843: <a name="sec-description"></a>
                   90844: <div class="info-box">
                   90845:        <div class="info-box-title">Description</div>
                   90846:        <div class="nav-bar">
                   90847:                                        <span class="disabled">Description</span> |
                   90848:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   90849:                                                
                   90850:                        </div>
                   90851:        <div class="info-box-body">
                   90852:                <!-- ========== Info from phpDoc block ========= -->
                   90853: <p class="short-description">The Structures_Graph class represents a graph data structure.</p>
                   90854: <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>
                   90855:        <ul class="tags">
                   90856:                                <li><span class="field">copyright:</span> (c) 2004 by S閞gio Carvalho</li>
                   90857:                                <li><span class="field">author:</span> S閞gio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   90858:                        </ul>
                   90859:                <p class="notes">
                   90860:                        Located in <a class="field" href="_Structures_Graph_php.html">/Structures/Graph.php</a> (line <span class="field">56</span>)
                   90861:                </p>
                   90862:                
                   90863:                                
                   90864:                <pre></pre>
                   90865:        
                   90866:                        </div>
                   90867: </div>
                   90868: 
                   90869: 
                   90870: 
                   90871:        <a name="sec-method-summary"></a>
                   90872:        <div class="info-box">
                   90873:                <div class="info-box-title">Method Summary</span></div>
                   90874:                <div class="nav-bar">
                   90875:                        <a href="#sec-description">Description</a> |
                   90876:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   90877:                </div>
                   90878:                <div class="info-box-body">                     
                   90879:                        <div class="method-summary">
                   90880:                                                                
                   90881:                                <div class="method-definition">
                   90882:                                                                                        <span class="method-result">Structures_Graph</span>
                   90883:                                                                                <a href="#Structures_Graph" title="details" class="method-name">Structures_Graph</a>
                   90884:                                                                                        ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$directed</span> = <span class="var-default">true</span>])
                   90885:                                                                        </div>
                   90886:                                                                
                   90887:                                <div class="method-definition">
                   90888:                                                                                        <span class="method-result">void</span>
                   90889:                                                                                <a href="#addNode" title="details" class="method-name">addNode</a>
                   90890:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$newNode</span>)
                   90891:                                                                        </div>
                   90892:                                                                
                   90893:                                <div class="method-definition">
                   90894:                                                                                        <span class="method-result">array</span>
                   90895:                                                                                <a href="#getNodes" title="details" class="method-name">&amp;getNodes</a>
                   90896:                                                                                ()
                   90897:                                                                        </div>
                   90898:                                                                
                   90899:                                <div class="method-definition">
                   90900:                                                                                        <span class="method-result">boolean</span>
                   90901:                                                                                <a href="#isDirected" title="details" class="method-name">isDirected</a>
                   90902:                                                                                ()
                   90903:                                                                        </div>
                   90904:                                                                
                   90905:                                <div class="method-definition">
                   90906:                                                                                        <span class="method-result">void</span>
                   90907:                                                                                <a href="#removeNode" title="details" class="method-name">removeNode</a>
                   90908:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$node</span>)
                   90909:                                                                        </div>
                   90910:                                                        </div>
                   90911:                </div>
                   90912:        </div>          
                   90913: 
                   90914:        
                   90915:        <a name="sec-methods"></a>
                   90916:        <div class="info-box">
                   90917:                <div class="info-box-title">Methods</div>
                   90918:                <div class="nav-bar">
                   90919:                        <a href="#sec-description">Description</a> |
                   90920:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   90921:                                                
                   90922:                </div>
                   90923:                <div class="info-box-body">
                   90924:                        <A NAME='method_detail'></A>
                   90925: <a name="methodStructures_Graph" id="Structures_Graph"><!-- --></a>
                   90926: <div class="evenrow">
                   90927:        
                   90928:        <div class="method-header">
                   90929:                <span class="method-title">Constructor Structures_Graph</span> (line <span class="line-number">76</span>)
                   90930:        </div> 
                   90931:        
                   90932:        <!-- ========== Info from phpDoc block ========= -->
                   90933: <p class="short-description">Constructor</p>
                   90934:        <ul class="tags">
                   90935:                                <li><span class="field">access:</span> public</li>
                   90936:                        </ul>
                   90937:        
                   90938:        <div class="method-signature">
                   90939:                <span class="method-result">Structures_Graph</span>
                   90940:                <span class="method-name">
                   90941:                        Structures_Graph
                   90942:                </span>
                   90943:                                        ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$directed</span> = <span class="var-default">true</span>])
                   90944:                        </div>
                   90945:        
                   90946:                        <ul class="parameters">
                   90947:                                        <li>
                   90948:                                <span class="var-type">boolean</span>
                   90949:                                <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>
                   90950:                                </ul>
                   90951:                
                   90952:                
                   90953:        </div>
                   90954: <a name="methodaddNode" id="addNode"><!-- --></a>
                   90955: <div class="oddrow">
                   90956:        
                   90957:        <div class="method-header">
                   90958:                <span class="method-title">addNode</span> (line <span class="line-number">102</span>)
                   90959:        </div> 
                   90960:        
                   90961:        <!-- ========== Info from phpDoc block ========= -->
                   90962: <p class="short-description">Add a Node to the Graph</p>
                   90963:        <ul class="tags">
                   90964:                                <li><span class="field">access:</span> public</li>
                   90965:                        </ul>
                   90966:        
                   90967:        <div class="method-signature">
                   90968:                <span class="method-result">void</span>
                   90969:                <span class="method-name">
                   90970:                        addNode
                   90971:                </span>
                   90972:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$newNode</span>)
                   90973:                        </div>
                   90974:        
                   90975:                        <ul class="parameters">
                   90976:                                        <li>
                   90977:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>
                   90978:                                <span class="var-name">&$newNode</span><span class="var-description">: The node to be added.</span>                     </li>
                   90979:                                </ul>
                   90980:                
                   90981:                
                   90982:        </div>
                   90983: <a name="methodgetNodes" id="getNodes"><!-- --></a>
                   90984: <div class="evenrow">
                   90985:        
                   90986:        <div class="method-header">
                   90987:                <span class="method-title">getNodes</span> (line <span class="line-number">151</span>)
                   90988:        </div> 
                   90989:        
                   90990:        <!-- ========== Info from phpDoc block ========= -->
                   90991: <p class="short-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</p>
                   90992:        <ul class="tags">
                   90993:                                <li><span class="field">return:</span> The set of nodes in this graph</li>
                   90994:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li>
                   90995:                                <li><span class="field">access:</span> public</li>
                   90996:                        </ul>
                   90997:        
                   90998:        <div class="method-signature">
                   90999:                <span class="method-result">array</span>
                   91000:                <span class="method-name">
                   91001:                        &amp;getNodes
                   91002:                </span>
                   91003:                                ()
                   91004:                        </div>
                   91005:        
                   91006:                
                   91007:                
                   91008:        </div>
                   91009: <a name="methodisDirected" id="isDirected"><!-- --></a>
                   91010: <div class="oddrow">
                   91011:        
                   91012:        <div class="method-header">
                   91013:                <span class="method-title">isDirected</span> (line <span class="line-number">89</span>)
                   91014:        </div> 
                   91015:        
                   91016:        <!-- ========== Info from phpDoc block ========= -->
                   91017: <p class="short-description">Return true if a graph is directed</p>
                   91018:        <ul class="tags">
                   91019:                                <li><span class="field">return:</span> true if the graph is directed</li>
                   91020:                                <li><span class="field">access:</span> public</li>
                   91021:                        </ul>
                   91022:        
                   91023:        <div class="method-signature">
                   91024:                <span class="method-result">boolean</span>
                   91025:                <span class="method-name">
                   91026:                        isDirected
                   91027:                </span>
                   91028:                                ()
                   91029:                        </div>
                   91030:        
                   91031:                
                   91032:                
                   91033:        </div>
                   91034: <a name="methodremoveNode" id="removeNode"><!-- --></a>
                   91035: <div class="evenrow">
                   91036:        
                   91037:        <div class="method-header">
                   91038:                <span class="method-title">removeNode</span> (line <span class="line-number">138</span>)
                   91039:        </div> 
                   91040:        
                   91041:        <!-- ========== Info from phpDoc block ========= -->
                   91042: <p class="short-description">Remove a Node from the Graph</p>
                   91043:        <ul class="tags">
                   91044:                                <li><span class="field">access:</span> public</li>
                   91045:                                <li><span class="field">todo:</span> This is unimplemented</li>
                   91046:                        </ul>
                   91047:        
                   91048:        <div class="method-signature">
                   91049:                <span class="method-result">void</span>
                   91050:                <span class="method-name">
                   91051:                        removeNode
                   91052:                </span>
                   91053:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$node</span>)
                   91054:                        </div>
                   91055:        
                   91056:                        <ul class="parameters">
                   91057:                                        <li>
                   91058:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>
                   91059:                                <span class="var-name">&$node</span><span class="var-description">: The node to be removed from the graph</span>                        </li>
                   91060:                                </ul>
                   91061:                
                   91062:                
                   91063:        </div>
                   91064:                                                
                   91065:                </div>
                   91066:        </div>
                   91067:        
                   91068:        <p class="notes" id="credit">
                   91069:                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>
                   91070:        </p>
                   91071:        </div></body>
                   91072: </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"?>
                   91073: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   91074:   <html xmlns="http://www.w3.org/1999/xhtml">
                   91075:                <head>
                   91076:                        <!-- template designed by Marco Von Ballmoos -->
                   91077:                        <title>Docs For Class Structures_Graph_Manipulator_AcyclicTest</title>
                   91078:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   91079:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   91080:                </head>
                   91081:                <body>
                   91082:                        <div class="page-body">                 
                   91083: <h2 class="class-name">Class Structures_Graph_Manipulator_AcyclicTest</h2>
                   91084: 
                   91085: <a name="sec-description"></a>
                   91086: <div class="info-box">
                   91087:        <div class="info-box-title">Description</div>
                   91088:        <div class="nav-bar">
                   91089:                                        <span class="disabled">Description</span> |
                   91090:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   91091:                                                
                   91092:                        </div>
                   91093:        <div class="info-box-body">
                   91094:                <!-- ========== Info from phpDoc block ========= -->
                   91095: <p class="short-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</p>
                   91096: <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>
                   91097:        <ul class="tags">
                   91098:                                <li><span class="field">copyright:</span> (c) 2004 by S閞gio Carvalho</li>
                   91099:                                <li><span class="field">author:</span> S閞gio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   91100:                        </ul>
                   91101:                <p class="notes">
                   91102:                        Located in <a class="field" href="_Structures_Graph_Manipulator_AcyclicTest_php.html">/Structures/Graph/Manipulator/AcyclicTest.php</a> (line <span class="field">55</span>)
                   91103:                </p>
                   91104:                
                   91105:                                
                   91106:                <pre></pre>
                   91107:        
                   91108:                        </div>
                   91109: </div>
                   91110: 
                   91111: 
                   91112: 
                   91113:        <a name="sec-method-summary"></a>
                   91114:        <div class="info-box">
                   91115:                <div class="info-box-title">Method Summary</span></div>
                   91116:                <div class="nav-bar">
                   91117:                        <a href="#sec-description">Description</a> |
                   91118:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   91119:                </div>
                   91120:                <div class="info-box-body">                     
                   91121:                        <div class="method-summary">
                   91122:                                                                
                   91123:                                <div class="method-definition">
                   91124:                                                                                        <span class="method-result">boolean</span>
                   91125:                                                                                <a href="#isAcyclic" title="details" class="method-name">isAcyclic</a>
                   91126:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   91127:                                                                        </div>
                   91128:                                                        </div>
                   91129:                </div>
                   91130:        </div>          
                   91131: 
                   91132:        
                   91133:        <a name="sec-methods"></a>
                   91134:        <div class="info-box">
                   91135:                <div class="info-box-title">Methods</div>
                   91136:                <div class="nav-bar">
                   91137:                        <a href="#sec-description">Description</a> |
                   91138:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   91139:                                                
                   91140:                </div>
                   91141:                <div class="info-box-body">
                   91142:                        <A NAME='method_detail'></A>
                   91143: <a name="methodisAcyclic" id="isAcyclic"><!-- --></a>
                   91144: <div class="evenrow">
                   91145:        
                   91146:        <div class="method-header">
                   91147:                <span class="method-title">isAcyclic</span> (line <span class="line-number">126</span>)
                   91148:        </div> 
                   91149:        
                   91150:        <!-- ========== Info from phpDoc block ========= -->
                   91151: <p class="short-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</p>
                   91152:        <ul class="tags">
                   91153:                                <li><span class="field">return:</span> true iff graph is acyclic</li>
                   91154:                                <li><span class="field">access:</span> public</li>
                   91155:                        </ul>
                   91156:        
                   91157:        <div class="method-signature">
                   91158:                <span class="method-result">boolean</span>
                   91159:                <span class="method-name">
                   91160:                        isAcyclic
                   91161:                </span>
                   91162:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   91163:                        </div>
                   91164:        
                   91165:                
                   91166:                
                   91167:        </div>
                   91168:                                                
                   91169:                </div>
                   91170:        </div>
                   91171:        
                   91172:        <p class="notes" id="credit">
                   91173:                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>
                   91174:        </p>
                   91175:        </div></body>
                   91176: </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"?>
                   91177: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   91178:   <html xmlns="http://www.w3.org/1999/xhtml">
                   91179:                <head>
                   91180:                        <!-- template designed by Marco Von Ballmoos -->
                   91181:                        <title>Docs For Class Structures_Graph_Manipulator_TopologicalSorter</title>
                   91182:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   91183:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   91184:                </head>
                   91185:                <body>
                   91186:                        <div class="page-body">                 
                   91187: <h2 class="class-name">Class Structures_Graph_Manipulator_TopologicalSorter</h2>
                   91188: 
                   91189: <a name="sec-description"></a>
                   91190: <div class="info-box">
                   91191:        <div class="info-box-title">Description</div>
                   91192:        <div class="nav-bar">
                   91193:                                        <span class="disabled">Description</span> |
                   91194:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   91195:                                                
                   91196:                        </div>
                   91197:        <div class="info-box-body">
                   91198:                <!-- ========== Info from phpDoc block ========= -->
                   91199: <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>
                   91200: <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>
                   91201:        <ul class="tags">
                   91202:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li>
                   91203:                                <li><span class="field">copyright:</span> (c) 2004 by S閞gio Carvalho</li>
                   91204:                                <li><span class="field">author:</span> S閞gio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   91205:                        </ul>
                   91206:                <p class="notes">
                   91207:                        Located in <a class="field" href="_Structures_Graph_Manipulator_TopologicalSorter_php.html">/Structures/Graph/Manipulator/TopologicalSorter.php</a> (line <span class="field">58</span>)
                   91208:                </p>
                   91209:                
                   91210:                                
                   91211:                <pre></pre>
                   91212:        
                   91213:                        </div>
                   91214: </div>
                   91215: 
                   91216: 
                   91217: 
                   91218:        <a name="sec-method-summary"></a>
                   91219:        <div class="info-box">
                   91220:                <div class="info-box-title">Method Summary</span></div>
                   91221:                <div class="nav-bar">
                   91222:                        <a href="#sec-description">Description</a> |
                   91223:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   91224:                </div>
                   91225:                <div class="info-box-body">                     
                   91226:                        <div class="method-summary">
                   91227:                                                                
                   91228:                                <div class="method-definition">
                   91229:                                                                                        <span class="method-result">array</span>
                   91230:                                                                                <a href="#sort" title="details" class="method-name">sort</a>
                   91231:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   91232:                                                                        </div>
                   91233:                                                        </div>
                   91234:                </div>
                   91235:        </div>          
                   91236: 
                   91237:        
                   91238:        <a name="sec-methods"></a>
                   91239:        <div class="info-box">
                   91240:                <div class="info-box-title">Methods</div>
                   91241:                <div class="nav-bar">
                   91242:                        <a href="#sec-description">Description</a> |
                   91243:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   91244:                                                
                   91245:                </div>
                   91246:                <div class="info-box-body">
                   91247:                        <A NAME='method_detail'></A>
                   91248: <a name="methodsort" id="sort"><!-- --></a>
                   91249: <div class="evenrow">
                   91250:        
                   91251:        <div class="method-header">
                   91252:                <span class="method-title">sort</span> (line <span class="line-number">133</span>)
                   91253:        </div> 
                   91254:        
                   91255:        <!-- ========== Info from phpDoc block ========= -->
                   91256: <p class="short-description">sort returns the graph's nodes, sorted by topological order.</p>
                   91257: <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>
                   91258:        <ul class="tags">
                   91259:                                <li><span class="field">return:</span> The graph's nodes, sorted by topological order.</li>
                   91260:                                <li><span class="field">access:</span> public</li>
                   91261:                        </ul>
                   91262:        
                   91263:        <div class="method-signature">
                   91264:                <span class="method-result">array</span>
                   91265:                <span class="method-name">
                   91266:                        sort
                   91267:                </span>
                   91268:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   91269:                        </div>
                   91270:        
                   91271:                
                   91272:                
                   91273:        </div>
                   91274:                                                
                   91275:                </div>
                   91276:        </div>
                   91277:        
                   91278:        <p class="notes" id="credit">
                   91279:                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>
                   91280:        </p>
                   91281:        </div></body>
                   91282: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph_Node.html0000644000076600000240000005007111461440275026644 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   91283: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   91284:   <html xmlns="http://www.w3.org/1999/xhtml">
                   91285:                <head>
                   91286:                        <!-- template designed by Marco Von Ballmoos -->
                   91287:                        <title>Docs For Class Structures_Graph_Node</title>
                   91288:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   91289:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   91290:                </head>
                   91291:                <body>
                   91292:                        <div class="page-body">                 
                   91293: <h2 class="class-name">Class Structures_Graph_Node</h2>
                   91294: 
                   91295: <a name="sec-description"></a>
                   91296: <div class="info-box">
                   91297:        <div class="info-box-title">Description</div>
                   91298:        <div class="nav-bar">
                   91299:                                        <span class="disabled">Description</span> |
                   91300:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   91301:                                                
                   91302:                        </div>
                   91303:        <div class="info-box-body">
                   91304:                <!-- ========== Info from phpDoc block ========= -->
                   91305: <p class="short-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</p>
                   91306: <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>
                   91307:        <ul class="tags">
                   91308:                                <li><span class="field">copyright:</span> (c) 2004 by S閞gio Carvalho</li>
                   91309:                                <li><span class="field">author:</span> S閞gio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   91310:                        </ul>
                   91311:                <p class="notes">
                   91312:                        Located in <a class="field" href="_Structures_Graph_Node_php.html">/Structures/Graph/Node.php</a> (line <span class="field">57</span>)
                   91313:                </p>
                   91314:                
                   91315:                                
                   91316:                <pre></pre>
                   91317:        
                   91318:                        </div>
                   91319: </div>
                   91320: 
                   91321: 
                   91322: 
                   91323:        <a name="sec-method-summary"></a>
                   91324:        <div class="info-box">
                   91325:                <div class="info-box-title">Method Summary</span></div>
                   91326:                <div class="nav-bar">
                   91327:                        <a href="#sec-description">Description</a> |
                   91328:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   91329:                </div>
                   91330:                <div class="info-box-body">                     
                   91331:                        <div class="method-summary">
                   91332:                                                                
                   91333:                                <div class="method-definition">
                   91334:                                                                                        <span class="method-result">Structures_Graph_Node</span>
                   91335:                                                                                <a href="#Structures_Graph_Node" title="details" class="method-name">Structures_Graph_Node</a>
                   91336:                                                                                ()
                   91337:                                                                        </div>
                   91338:                                                                
                   91339:                                <div class="method-definition">
                   91340:                                                                                        <span class="method-result">boolean</span>
                   91341:                                                                                <a href="#connectsTo" title="details" class="method-name">connectsTo</a>
                   91342:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$target</span>)
                   91343:                                                                        </div>
                   91344:                                                                
                   91345:                                <div class="method-definition">
                   91346:                                                                                        <span class="method-result">void</span>
                   91347:                                                                                <a href="#connectTo" title="details" class="method-name">connectTo</a>
                   91348:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$destinationNode</span>)
                   91349:                                                                        </div>
                   91350:                                                                
                   91351:                                <div class="method-definition">
                   91352:                                                                                        <span class="method-result">mixed</span>
                   91353:                                                                                <a href="#getData" title="details" class="method-name">&amp;getData</a>
                   91354:                                                                                ()
                   91355:                                                                        </div>
                   91356:                                                                
                   91357:                                <div class="method-definition">
                   91358:                                                                                        <span class="method-result"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   91359:                                                                                <a href="#getGraph" title="details" class="method-name">&amp;getGraph</a>
                   91360:                                                                                ()
                   91361:                                                                        </div>
                   91362:                                                                
                   91363:                                <div class="method-definition">
                   91364:                                                                                        <span class="method-result">mixed</span>
                   91365:                                                                                <a href="#getMetadata" title="details" class="method-name">&amp;getMetadata</a>
                   91366:                                                                                        (<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>])
                   91367:                                                                        </div>
                   91368:                                                                
                   91369:                                <div class="method-definition">
                   91370:                                                                                        <span class="method-result">array</span>
                   91371:                                                                                <a href="#getNeighbours" title="details" class="method-name">getNeighbours</a>
                   91372:                                                                                ()
                   91373:                                                                        </div>
                   91374:                                                                
                   91375:                                <div class="method-definition">
                   91376:                                                                                        <span class="method-result">integer</span>
                   91377:                                                                                <a href="#inDegree" title="details" class="method-name">inDegree</a>
                   91378:                                                                                ()
                   91379:                                                                        </div>
                   91380:                                                                
                   91381:                                <div class="method-definition">
                   91382:                                                                                        <span class="method-result">boolean</span>
                   91383:                                                                                <a href="#metadataKeyExists" title="details" class="method-name">metadataKeyExists</a>
                   91384:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   91385:                                                                        </div>
                   91386:                                                                
                   91387:                                <div class="method-definition">
                   91388:                                                                                        <span class="method-result">integer</span>
                   91389:                                                                                <a href="#outDegree" title="details" class="method-name">outDegree</a>
                   91390:                                                                                ()
                   91391:                                                                        </div>
                   91392:                                                                
                   91393:                                <div class="method-definition">
                   91394:                                                                                        <span class="method-result">mixed</span>
                   91395:                                                                                <a href="#setData" title="details" class="method-name">setData</a>
                   91396:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   91397:                                                                        </div>
                   91398:                                                                
                   91399:                                <div class="method-definition">
                   91400:                                                                                        <span class="method-result">void</span>
                   91401:                                                                                <a href="#setGraph" title="details" class="method-name">setGraph</a>
                   91402:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$graph</span>)
                   91403:                                                                        </div>
                   91404:                                                                
                   91405:                                <div class="method-definition">
                   91406:                                                                                        <span class="method-result">void</span>
                   91407:                                                                                <a href="#setMetadata" title="details" class="method-name">setMetadata</a>
                   91408:                                                                                        (<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>)
                   91409:                                                                        </div>
                   91410:                                                                
                   91411:                                <div class="method-definition">
                   91412:                                                                                        <span class="method-result">void</span>
                   91413:                                                                                <a href="#unsetMetadata" title="details" class="method-name">unsetMetadata</a>
                   91414:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   91415:                                                                        </div>
                   91416:                                                        </div>
                   91417:                </div>
                   91418:        </div>          
                   91419: 
                   91420:        
                   91421:        <a name="sec-methods"></a>
                   91422:        <div class="info-box">
                   91423:                <div class="info-box-title">Methods</div>
                   91424:                <div class="nav-bar">
                   91425:                        <a href="#sec-description">Description</a> |
                   91426:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   91427:                                                
                   91428:                </div>
                   91429:                <div class="info-box-body">
                   91430:                        <A NAME='method_detail'></A>
                   91431: <a name="methodStructures_Graph_Node" id="Structures_Graph_Node"><!-- --></a>
                   91432: <div class="evenrow">
                   91433:        
                   91434:        <div class="method-header">
                   91435:                <span class="method-title">Constructor Structures_Graph_Node</span> (line <span class="line-number">78</span>)
                   91436:        </div> 
                   91437:        
                   91438:        <!-- ========== Info from phpDoc block ========= -->
                   91439: <p class="short-description">Constructor</p>
                   91440:        <ul class="tags">
                   91441:                                <li><span class="field">access:</span> public</li>
                   91442:                        </ul>
                   91443:        
                   91444:        <div class="method-signature">
                   91445:                <span class="method-result">Structures_Graph_Node</span>
                   91446:                <span class="method-name">
                   91447:                        Structures_Graph_Node
                   91448:                </span>
                   91449:                                ()
                   91450:                        </div>
                   91451:        
                   91452:                
                   91453:                
                   91454:        </div>
                   91455: <a name="methodconnectsTo" id="connectsTo"><!-- --></a>
                   91456: <div class="oddrow">
                   91457:        
                   91458:        <div class="method-header">
                   91459:                <span class="method-title">connectsTo</span> (line <span class="line-number">275</span>)
                   91460:        </div> 
                   91461:        
                   91462:        <!-- ========== Info from phpDoc block ========= -->
                   91463: <p class="short-description">Test wether this node has an arc to the target node</p>
                   91464:        <ul class="tags">
                   91465:                                <li><span class="field">return:</span> True if the two nodes are connected</li>
                   91466:                                <li><span class="field">access:</span> public</li>
                   91467:                        </ul>
                   91468:        
                   91469:        <div class="method-signature">
                   91470:                <span class="method-result">boolean</span>
                   91471:                <span class="method-name">
                   91472:                        connectsTo
                   91473:                </span>
                   91474:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$target</span>)
                   91475:                        </div>
                   91476:        
                   91477:                
                   91478:                
                   91479:        </div>
                   91480: <a name="methodconnectTo" id="connectTo"><!-- --></a>
                   91481: <div class="evenrow">
                   91482:        
                   91483:        <div class="method-header">
                   91484:                <span class="method-title">connectTo</span> (line <span class="line-number">236</span>)
                   91485:        </div> 
                   91486:        
                   91487:        <!-- ========== Info from phpDoc block ========= -->
                   91488: <p class="short-description">Connect this node to another one.</p>
                   91489: <p class="description"><p>If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.</p></p>
                   91490:        <ul class="tags">
                   91491:                                <li><span class="field">access:</span> public</li>
                   91492:                        </ul>
                   91493:        
                   91494:        <div class="method-signature">
                   91495:                <span class="method-result">void</span>
                   91496:                <span class="method-name">
                   91497:                        connectTo
                   91498:                </span>
                   91499:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$destinationNode</span>)
                   91500:                        </div>
                   91501:        
                   91502:                        <ul class="parameters">
                   91503:                                        <li>
                   91504:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   91505:                                <span class="var-name">&$destinationNode</span><span class="var-description">: Node to connect to</span>                        </li>
                   91506:                                </ul>
                   91507:                
                   91508:                
                   91509:        </div>
                   91510: <a name="methodgetData" id="getData"><!-- --></a>
                   91511: <div class="oddrow">
                   91512:        
                   91513:        <div class="method-header">
                   91514:                <span class="method-title">getData</span> (line <span class="line-number">119</span>)
                   91515:        </div> 
                   91516:        
                   91517:        <!-- ========== Info from phpDoc block ========= -->
                   91518: <p class="short-description">Node data getter.</p>
                   91519: <p class="description"><p>Each graph node can contain a reference to one variable. This is the getter for that reference.</p></p>
                   91520:        <ul class="tags">
                   91521:                                <li><span class="field">return:</span> Data stored in node</li>
                   91522:                                <li><span class="field">access:</span> public</li>
                   91523:                        </ul>
                   91524:        
                   91525:        <div class="method-signature">
                   91526:                <span class="method-result">mixed</span>
                   91527:                <span class="method-name">
                   91528:                        &amp;getData
                   91529:                </span>
                   91530:                                ()
                   91531:                        </div>
                   91532:        
                   91533:                
                   91534:                
                   91535:        </div>
                   91536: <a name="methodgetGraph" id="getGraph"><!-- --></a>
                   91537: <div class="evenrow">
                   91538:        
                   91539:        <div class="method-header">
                   91540:                <span class="method-title">getGraph</span> (line <span class="line-number">90</span>)
                   91541:        </div> 
                   91542:        
                   91543:        <!-- ========== Info from phpDoc block ========= -->
                   91544: <p class="short-description">Node graph getter</p>
                   91545:        <ul class="tags">
                   91546:                                <li><span class="field">return:</span> Graph where node is stored</li>
                   91547:                                <li><span class="field">access:</span> public</li>
                   91548:                        </ul>
                   91549:        
                   91550:        <div class="method-signature">
                   91551:                <span class="method-result"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   91552:                <span class="method-name">
                   91553:                        &amp;getGraph
                   91554:                </span>
                   91555:                                ()
                   91556:                        </div>
                   91557:        
                   91558:                
                   91559:                
                   91560:        </div>
                   91561: <a name="methodgetMetadata" id="getMetadata"><!-- --></a>
                   91562: <div class="oddrow">
                   91563:        
                   91564:        <div class="method-header">
                   91565:                <span class="method-title">getMetadata</span> (line <span class="line-number">171</span>)
                   91566:        </div> 
                   91567:        
                   91568:        <!-- ========== Info from phpDoc block ========= -->
                   91569: <p class="short-description">Node metadata getter</p>
                   91570: <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>
                   91571:        <ul class="tags">
                   91572:                                <li><span class="field">return:</span> Metadata Data stored in node under given key</li>
                   91573:                                <li><span class="field">access:</span> public</li>
                   91574:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a></li>
                   91575:                        </ul>
                   91576:        
                   91577:        <div class="method-signature">
                   91578:                <span class="method-result">mixed</span>
                   91579:                <span class="method-name">
                   91580:                        &amp;getMetadata
                   91581:                </span>
                   91582:                                        (<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>])
                   91583:                        </div>
                   91584:        
                   91585:                        <ul class="parameters">
                   91586:                                        <li>
                   91587:                                <span class="var-type">string</span>
                   91588:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   91589:                                        <li>
                   91590:                                <span class="var-type">boolean</span>
                   91591:                                <span class="var-name">$nullIfNonexistent</span><span class="var-description">: nullIfNonexistent (defaults to false).</span>                   </li>
                   91592:                                </ul>
                   91593:                
                   91594:                
                   91595:        </div>
                   91596: <a name="methodgetNeighbours" id="getNeighbours"><!-- --></a>
                   91597: <div class="evenrow">
                   91598:        
                   91599:        <div class="method-header">
                   91600:                <span class="method-title">getNeighbours</span> (line <span class="line-number">262</span>)
                   91601:        </div> 
                   91602:        
                   91603:        <!-- ========== Info from phpDoc block ========= -->
                   91604: <p class="short-description">Return nodes connected to this one.</p>
                   91605:        <ul class="tags">
                   91606:                                <li><span class="field">return:</span> Array of nodes</li>
                   91607:                                <li><span class="field">access:</span> public</li>
                   91608:                        </ul>
                   91609:        
                   91610:        <div class="method-signature">
                   91611:                <span class="method-result">array</span>
                   91612:                <span class="method-name">
                   91613:                        getNeighbours
                   91614:                </span>
                   91615:                                ()
                   91616:                        </div>
                   91617:        
                   91618:                
                   91619:                
                   91620:        </div>
                   91621: <a name="methodinDegree" id="inDegree"><!-- --></a>
                   91622: <div class="oddrow">
                   91623:        
                   91624:        <div class="method-header">
                   91625:                <span class="method-title">inDegree</span> (line <span class="line-number">309</span>)
                   91626:        </div> 
                   91627:        
                   91628:        <!-- ========== Info from phpDoc block ========= -->
                   91629: <p class="short-description">Calculate the in degree of the node.</p>
                   91630: <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>
                   91631:        <ul class="tags">
                   91632:                                <li><span class="field">return:</span> In degree of the node</li>
                   91633:                                <li><span class="field">access:</span> public</li>
                   91634:                        </ul>
                   91635:        
                   91636:        <div class="method-signature">
                   91637:                <span class="method-result">integer</span>
                   91638:                <span class="method-name">
                   91639:                        inDegree
                   91640:                </span>
                   91641:                                ()
                   91642:                        </div>
                   91643:        
                   91644:                
                   91645:                
                   91646:        </div>
                   91647: <a name="methodmetadataKeyExists" id="metadataKeyExists"><!-- --></a>
                   91648: <div class="evenrow">
                   91649:        
                   91650:        <div class="method-header">
                   91651:                <span class="method-title">metadataKeyExists</span> (line <span class="line-number">151</span>)
                   91652:        </div> 
                   91653:        
                   91654:        <!-- ========== Info from phpDoc block ========= -->
                   91655: <p class="short-description">Test for existence of metadata under a given key.</p>
                   91656: <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>
                   91657:        <ul class="tags">
                   91658:                                <li><span class="field">access:</span> public</li>
                   91659:                        </ul>
                   91660:        
                   91661:        <div class="method-signature">
                   91662:                <span class="method-result">boolean</span>
                   91663:                <span class="method-name">
                   91664:                        metadataKeyExists
                   91665:                </span>
                   91666:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   91667:                        </div>
                   91668:        
                   91669:                        <ul class="parameters">
                   91670:                                        <li>
                   91671:                                <span class="var-type">string</span>
                   91672:                                <span class="var-name">$key</span><span class="var-description">: Key to test</span>                    </li>
                   91673:                                </ul>
                   91674:                
                   91675:                
                   91676:        </div>
                   91677: <a name="methodoutDegree" id="outDegree"><!-- --></a>
                   91678: <div class="oddrow">
                   91679:        
                   91680:        <div class="method-header">
                   91681:                <span class="method-title">outDegree</span> (line <span class="line-number">333</span>)
                   91682:        </div> 
                   91683:        
                   91684:        <!-- ========== Info from phpDoc block ========= -->
                   91685: <p class="short-description">Calculate the out degree of the node.</p>
                   91686: <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>
                   91687:        <ul class="tags">
                   91688:                                <li><span class="field">return:</span> Out degree of the node</li>
                   91689:                                <li><span class="field">access:</span> public</li>
                   91690:                        </ul>
                   91691:        
                   91692:        <div class="method-signature">
                   91693:                <span class="method-result">integer</span>
                   91694:                <span class="method-name">
                   91695:                        outDegree
                   91696:                </span>
                   91697:                                ()
                   91698:                        </div>
                   91699:        
                   91700:                
                   91701:                
                   91702:        </div>
                   91703: <a name="methodsetData" id="setData"><!-- --></a>
                   91704: <div class="evenrow">
                   91705:        
                   91706:        <div class="method-header">
                   91707:                <span class="method-title">setData</span> (line <span class="line-number">134</span>)
                   91708:        </div> 
                   91709:        
                   91710:        <!-- ========== Info from phpDoc block ========= -->
                   91711: <p class="short-description">Node data setter</p>
                   91712: <p class="description"><p>Each graph node can contain a reference to one variable. This is the setter for that reference.</p></p>
                   91713:        <ul class="tags">
                   91714:                                <li><span class="field">return:</span> Data to store in node</li>
                   91715:                                <li><span class="field">access:</span> public</li>
                   91716:                        </ul>
                   91717:        
                   91718:        <div class="method-signature">
                   91719:                <span class="method-result">mixed</span>
                   91720:                <span class="method-name">
                   91721:                        setData
                   91722:                </span>
                   91723:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   91724:                        </div>
                   91725:        
                   91726:                
                   91727:                
                   91728:        </div>
                   91729: <a name="methodsetGraph" id="setGraph"><!-- --></a>
                   91730: <div class="oddrow">
                   91731:        
                   91732:        <div class="method-header">
                   91733:                <span class="method-title">setGraph</span> (line <span class="line-number">104</span>)
                   91734:        </div> 
                   91735:        
                   91736:        <!-- ========== Info from phpDoc block ========= -->
                   91737: <p class="short-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</p>
                   91738:        <ul class="tags">
                   91739:                                <li><span class="field">access:</span> public</li>
                   91740:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a></li>
                   91741:                        </ul>
                   91742:        
                   91743:        <div class="method-signature">
                   91744:                <span class="method-result">void</span>
                   91745:                <span class="method-name">
                   91746:                        setGraph
                   91747:                </span>
                   91748:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$graph</span>)
                   91749:                        </div>
                   91750:        
                   91751:                        <ul class="parameters">
                   91752:                                        <li>
                   91753:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   91754:                                <span class="var-name">&$graph</span><span class="var-description">: Set the graph for this node.</span>                        </li>
                   91755:                                </ul>
                   91756:                
                   91757:                
                   91758:        </div>
                   91759: <a name="methodsetMetadata" id="setMetadata"><!-- --></a>
                   91760: <div class="evenrow">
                   91761:        
                   91762:        <div class="method-header">
                   91763:                <span class="method-title">setMetadata</span> (line <span class="line-number">214</span>)
                   91764:        </div> 
                   91765:        
                   91766:        <!-- ========== Info from phpDoc block ========= -->
                   91767: <p class="short-description">Node metadata setter</p>
                   91768: <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>
                   91769:        <ul class="tags">
                   91770:                                <li><span class="field">access:</span> public</li>
                   91771:                        </ul>
                   91772:        
                   91773:        <div class="method-signature">
                   91774:                <span class="method-result">void</span>
                   91775:                <span class="method-name">
                   91776:                        setMetadata
                   91777:                </span>
                   91778:                                        (<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>)
                   91779:                        </div>
                   91780:        
                   91781:                        <ul class="parameters">
                   91782:                                        <li>
                   91783:                                <span class="var-type">string</span>
                   91784:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   91785:                                        <li>
                   91786:                                <span class="var-type">mixed</span>
                   91787:                                <span class="var-name">$data</span><span class="var-description">: Data</span>                  </li>
                   91788:                                </ul>
                   91789:                
                   91790:                
                   91791:        </div>
                   91792: <a name="methodunsetMetadata" id="unsetMetadata"><!-- --></a>
                   91793: <div class="oddrow">
                   91794:        
                   91795:        <div class="method-header">
                   91796:                <span class="method-title">unsetMetadata</span> (line <span class="line-number">196</span>)
                   91797:        </div> 
                   91798:        
                   91799:        <!-- ========== Info from phpDoc block ========= -->
                   91800: <p class="short-description">Delete metadata by key</p>
                   91801: <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>
                   91802:        <ul class="tags">
                   91803:                                <li><span class="field">access:</span> public</li>
                   91804:                        </ul>
                   91805:        
                   91806:        <div class="method-signature">
                   91807:                <span class="method-result">void</span>
                   91808:                <span class="method-name">
                   91809:                        unsetMetadata
                   91810:                </span>
                   91811:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   91812:                        </div>
                   91813:        
                   91814:                        <ul class="parameters">
                   91815:                                        <li>
                   91816:                                <span class="var-type">string</span>
                   91817:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   91818:                                </ul>
                   91819:                
                   91820:                
                   91821:        </div>
                   91822:                                                
                   91823:                </div>
                   91824:        </div>
                   91825:        
                   91826:        <p class="notes" id="credit">
                   91827:                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>
                   91828:        </p>
                   91829:        </div></body>
                   91830: </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"?>
                   91831: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   91832:   <html xmlns="http://www.w3.org/1999/xhtml">
                   91833:                <head>
                   91834:                        <!-- template designed by Marco Von Ballmoos -->
                   91835:                        <title>Structures_Graph Tutorial</title>
                   91836:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   91837:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   91838:                </head>
                   91839:                <body>
                   91840:                        <div class="page-body">                 
                   91841: 
                   91842: <div><a name="package.database.structures_graph.tutorial"></a><div class="ref-title-box"><h1 class="ref-title">Structures_Graph Tutorial</h1>
                   91843:   <h2 class="ref-purpose">A first tour of graph datastructure manipulation</h2></div>
                   91844:  <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>
                   91845:   <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>
                   91846:  <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:
                   91847:    <pre class="listing"><pre>
                   91848: require_once 'Structures/Graph.php';
                   91849: 
                   91850: $directedGraph =&amp; new Structures_Graph(true);
                   91851: $nonDirectedGraph =&amp; new Structures_Graph(false);
                   91852:     </pre></pre>
                   91853:    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>
                   91854:   <p>To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
                   91855:    <pre class="listing"><pre>
                   91856: require_once 'Structures/Graph/Node.php';
                   91857: 
                   91858: $nodeOne =&amp; new Structures_Graph_Node();
                   91859: $nodeTwo =&amp; new Structures_Graph_Node();
                   91860: $nodeThree =&amp; new Structures_Graph_Node();
                   91861: 
                   91862: $directedGraph-&gt;addNode(&amp;$nodeOne);
                   91863: $directedGraph-&gt;addNode(&amp;$nodeTwo);
                   91864: $directedGraph-&gt;addNode(&amp;$nodeThree);
                   91865:     </pre></pre>
                   91866:    and then setup the arcs:
                   91867:    <pre class="listing"><pre>
                   91868: $nodeOne-&gt;connectTo($nodeTwo);
                   91869: $nodeOne-&gt;connectTo($nodeThree);
                   91870:     </pre></pre>
                   91871:    Note that arcs can only be created after the nodes have been inserted into the graph.</p></span>
                   91872:  <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.
                   91873:    <pre class="listing"><pre>
                   91874: $nodeOne-&gt;setData(&quot;Node One's Data is a String&quot;);
                   91875: $nodeTwo-&gt;setData(1976);
                   91876: $nodeThree-&gt;setData('Some other string');
                   91877: 
                   91878: print(&quot;NodeTwo's Data is an integer: &quot; . $nodeTwo-&gt;getData());
                   91879:     </pre></pre></p>
                   91880:   <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:
                   91881:    <pre class="listing"><pre>
                   91882: $nodeOne-&gt;setMetadata('example key', &quot;Node One's Sample Metadata&quot;);
                   91883: print(&quot;Metadata stored under key 'example key' in node one: &quot; . $nodeOne-&gt;getMetadata('example key'));
                   91884: $nodeOne-&gt;unsetMetadata('example key');
                   91885:     </pre></pre></p></span>
                   91886:  <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:
                   91887:    <pre class="listing"><pre>
                   91888: // Nodes are able to calculate their indegree and outdegree
                   91889: print(&quot;NodeOne's inDegree: &quot; . $nodeOne-&gt;inDegree());
                   91890: print(&quot;NodeOne's outDegree: &quot; . $nodeOne-&gt;outDegree());
                   91891: 
                   91892: // and naturally, nodes can report on their arcs
                   91893: $arcs = $nodeOne-&gt;getNeighbours();
                   91894: for ($i=0;$i&lt;sizeof($arcs);$i++) {
                   91895:     print(&quot;NodeOne has an arc to &quot; . $arcs[$i]-&gt;getData());
                   91896: }
                   91897:     </pre></pre></p></span></div>
                   91898: 
                   91899: 
                   91900:        <p class="notes" id="credit">
                   91901:                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>
                   91902:        </p>
                   91903:        </div></body>
                   91904: </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"?>
                   91905: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   91906:   <html xmlns="http://www.w3.org/1999/xhtml">
                   91907:                <head>
                   91908:                        <!-- template designed by Marco Von Ballmoos -->
                   91909:                        <title>Docs for page AcyclicTest.php</title>
                   91910:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   91911:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   91912:                </head>
                   91913:                <body>
                   91914:                        <div class="page-body">                 
                   91915: <h2 class="file-name">/Structures/Graph/Manipulator/AcyclicTest.php</h2>
                   91916: 
                   91917: <a name="sec-description"></a>
                   91918: <div class="info-box">
                   91919:        <div class="info-box-title">Description</div>
                   91920:        <div class="nav-bar">
                   91921:                                        <span class="disabled">Description</span> |
                   91922:                                                        <a href="#sec-classes">Classes</a>
                   91923:                        |                                                       <a href="#sec-includes">Includes</a>
                   91924:                                                                                                </div>
                   91925:        <div class="info-box-body">     
                   91926:                <!-- ========== Info from phpDoc block ========= -->
                   91927: <p class="short-description">This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.</p>
                   91928:        <ul class="tags">
                   91929:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li>
                   91930:                        </ul>
                   91931:                
                   91932:                        </div>
                   91933: </div>
                   91934:                
                   91935:        <a name="sec-classes"></a>      
                   91936:        <div class="info-box">
                   91937:                <div class="info-box-title">Classes</div>
                   91938:                <div class="nav-bar">
                   91939:                        <a href="#sec-description">Description</a> |
                   91940:                        <span class="disabled">Classes</span>
                   91941:                        |                                                       <a href="#sec-includes">Includes</a>
                   91942:                                                                                                                                                </div>
                   91943:                <div class="info-box-body">     
                   91944:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   91945:                                <tr>
                   91946:                                        <th class="class-table-header">Class</th>
                   91947:                                        <th class="class-table-header">Description</th>
                   91948:                                </tr>
                   91949:                                                                <tr>
                   91950:                                        <td style="padding-right: 2em; vertical-align: top">
                   91951:                                                <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a>
                   91952:                                        </td>
                   91953:                                        <td>
                   91954:                                                                                        The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.
                   91955:                                                                                </td>
                   91956:                                </tr>
                   91957:                                                        </table>
                   91958:                </div>
                   91959:        </div>
                   91960: 
                   91961:        <a name="sec-includes"></a>     
                   91962:        <div class="info-box">
                   91963:                <div class="info-box-title">Includes</div>
                   91964:                <div class="nav-bar">
                   91965:                        <a href="#sec-description">Description</a> |
                   91966:                                                        <a href="#sec-classes">Classes</a>
                   91967:                                |                                               <span class="disabled">Includes</span>
                   91968:                                                                                                                </div>
                   91969:                <div class="info-box-body">     
                   91970:                        <a name="_PEAR_php"><!-- --></a>
                   91971: <div class="oddrow">
                   91972:        
                   91973:        <div>
                   91974:                <span class="include-title">
                   91975:                        <span class="include-type">require_once</span>
                   91976:                        (<span class="include-name">'PEAR.php'</span>)
                   91977:                        (line <span class="line-number">35</span>)
                   91978:                </span>
                   91979:        </div>
                   91980: 
                   91981:        <!-- ========== Info from phpDoc block ========= -->
                   91982:        
                   91983: </div>
                   91984: <a name="_Structures/Graph_php"><!-- --></a>
                   91985: <div class="evenrow">
                   91986:        
                   91987:        <div>
                   91988:                <span class="include-title">
                   91989:                        <span class="include-type">require_once</span>
                   91990:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   91991:                        (line <span class="line-number">37</span>)
                   91992:                </span>
                   91993:        </div>
                   91994: 
                   91995:        <!-- ========== Info from phpDoc block ========= -->
                   91996:        
                   91997: </div>
                   91998: <a name="_Structures/Graph/Node_php"><!-- --></a>
                   91999: <div class="oddrow">
                   92000:        
                   92001:        <div>
                   92002:                <span class="include-title">
                   92003:                        <span class="include-type">require_once</span>
                   92004:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   92005:                        (line <span class="line-number">39</span>)
                   92006:                </span>
                   92007:        </div>
                   92008: 
                   92009:        <!-- ========== Info from phpDoc block ========= -->
                   92010:        
                   92011: </div>
                   92012:                </div>
                   92013:        </div>
                   92014:        
                   92015:        
                   92016:        
                   92017:        
                   92018:        <p class="notes" id="credit">
                   92019:                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>
                   92020:        </p>
                   92021:        </div></body>
                   92022: </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"?>
                   92023: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92024:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92025:                <head>
                   92026:                        <!-- template designed by Marco Von Ballmoos -->
                   92027:                        <title>Docs for page TopologicalSorter.php</title>
                   92028:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   92029:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92030:                </head>
                   92031:                <body>
                   92032:                        <div class="page-body">                 
                   92033: <h2 class="file-name">/Structures/Graph/Manipulator/TopologicalSorter.php</h2>
                   92034: 
                   92035: <a name="sec-description"></a>
                   92036: <div class="info-box">
                   92037:        <div class="info-box-title">Description</div>
                   92038:        <div class="nav-bar">
                   92039:                                        <span class="disabled">Description</span> |
                   92040:                                                        <a href="#sec-classes">Classes</a>
                   92041:                        |                                                       <a href="#sec-includes">Includes</a>
                   92042:                                                                                                </div>
                   92043:        <div class="info-box-body">     
                   92044:                <!-- ========== Info from phpDoc block ========= -->
                   92045: <p class="short-description">This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.</p>
                   92046:        <ul class="tags">
                   92047:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li>
                   92048:                        </ul>
                   92049:                
                   92050:                        </div>
                   92051: </div>
                   92052:                
                   92053:        <a name="sec-classes"></a>      
                   92054:        <div class="info-box">
                   92055:                <div class="info-box-title">Classes</div>
                   92056:                <div class="nav-bar">
                   92057:                        <a href="#sec-description">Description</a> |
                   92058:                        <span class="disabled">Classes</span>
                   92059:                        |                                                       <a href="#sec-includes">Includes</a>
                   92060:                                                                                                                                                </div>
                   92061:                <div class="info-box-body">     
                   92062:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   92063:                                <tr>
                   92064:                                        <th class="class-table-header">Class</th>
                   92065:                                        <th class="class-table-header">Description</th>
                   92066:                                </tr>
                   92067:                                                                <tr>
                   92068:                                        <td style="padding-right: 2em; vertical-align: top">
                   92069:                                                <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a>
                   92070:                                        </td>
                   92071:                                        <td>
                   92072:                                                                                        The Structures_Graph_Manipulator_TopologicalSorter is a manipulator  which is able to return the set of nodes in a graph, sorted by topological  order.
                   92073:                                                                                </td>
                   92074:                                </tr>
                   92075:                                                        </table>
                   92076:                </div>
                   92077:        </div>
                   92078: 
                   92079:        <a name="sec-includes"></a>     
                   92080:        <div class="info-box">
                   92081:                <div class="info-box-title">Includes</div>
                   92082:                <div class="nav-bar">
                   92083:                        <a href="#sec-description">Description</a> |
                   92084:                                                        <a href="#sec-classes">Classes</a>
                   92085:                                |                                               <span class="disabled">Includes</span>
                   92086:                                                                                                                </div>
                   92087:                <div class="info-box-body">     
                   92088:                        <a name="_PEAR_php"><!-- --></a>
                   92089: <div class="oddrow">
                   92090:        
                   92091:        <div>
                   92092:                <span class="include-title">
                   92093:                        <span class="include-type">require_once</span>
                   92094:                        (<span class="include-name">'PEAR.php'</span>)
                   92095:                        (line <span class="line-number">35</span>)
                   92096:                </span>
                   92097:        </div>
                   92098: 
                   92099:        <!-- ========== Info from phpDoc block ========= -->
                   92100:        
                   92101: </div>
                   92102: <a name="_Structures/Graph_php"><!-- --></a>
                   92103: <div class="evenrow">
                   92104:        
                   92105:        <div>
                   92106:                <span class="include-title">
                   92107:                        <span class="include-type">require_once</span>
                   92108:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   92109:                        (line <span class="line-number">37</span>)
                   92110:                </span>
                   92111:        </div>
                   92112: 
                   92113:        <!-- ========== Info from phpDoc block ========= -->
                   92114:        
                   92115: </div>
                   92116: <a name="_Structures/Graph/Node_php"><!-- --></a>
                   92117: <div class="oddrow">
                   92118:        
                   92119:        <div>
                   92120:                <span class="include-title">
                   92121:                        <span class="include-type">require_once</span>
                   92122:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   92123:                        (line <span class="line-number">39</span>)
                   92124:                </span>
                   92125:        </div>
                   92126: 
                   92127:        <!-- ========== Info from phpDoc block ========= -->
                   92128:        
                   92129: </div>
                   92130: <a name="_Structures/Graph/Manipulator/AcyclicTest_php"><!-- --></a>
                   92131: <div class="evenrow">
                   92132:        
                   92133:        <div>
                   92134:                <span class="include-title">
                   92135:                        <span class="include-type">require_once</span>
                   92136:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">'Structures/Graph/Manipulator/AcyclicTest.php'</a></span>)
                   92137:                        (line <span class="line-number">41</span>)
                   92138:                </span>
                   92139:        </div>
                   92140: 
                   92141:        <!-- ========== Info from phpDoc block ========= -->
                   92142:        
                   92143: </div>
                   92144:                </div>
                   92145:        </div>
                   92146:        
                   92147:        
                   92148:        
                   92149:        
                   92150:        <p class="notes" id="credit">
                   92151:                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>
                   92152:        </p>
                   92153:        </div></body>
                   92154: </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"?>
                   92155: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92156:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92157:                <head>
                   92158:                        <!-- template designed by Marco Von Ballmoos -->
                   92159:                        <title>Docs for page Node.php</title>
                   92160:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   92161:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92162:                </head>
                   92163:                <body>
                   92164:                        <div class="page-body">                 
                   92165: <h2 class="file-name">/Structures/Graph/Node.php</h2>
                   92166: 
                   92167: <a name="sec-description"></a>
                   92168: <div class="info-box">
                   92169:        <div class="info-box-title">Description</div>
                   92170:        <div class="nav-bar">
                   92171:                                        <span class="disabled">Description</span> |
                   92172:                                                        <a href="#sec-classes">Classes</a>
                   92173:                        |                                                       <a href="#sec-includes">Includes</a>
                   92174:                                                                                                </div>
                   92175:        <div class="info-box-body">     
                   92176:                <!-- ========== Info from phpDoc block ========= -->
                   92177: <p class="short-description">This file contains the definition of the Structures_Graph_Node class</p>
                   92178:        <ul class="tags">
                   92179:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></li>
                   92180:                        </ul>
                   92181:                
                   92182:                        </div>
                   92183: </div>
                   92184:                
                   92185:        <a name="sec-classes"></a>      
                   92186:        <div class="info-box">
                   92187:                <div class="info-box-title">Classes</div>
                   92188:                <div class="nav-bar">
                   92189:                        <a href="#sec-description">Description</a> |
                   92190:                        <span class="disabled">Classes</span>
                   92191:                        |                                                       <a href="#sec-includes">Includes</a>
                   92192:                                                                                                                                                </div>
                   92193:                <div class="info-box-body">     
                   92194:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   92195:                                <tr>
                   92196:                                        <th class="class-table-header">Class</th>
                   92197:                                        <th class="class-table-header">Description</th>
                   92198:                                </tr>
                   92199:                                                                <tr>
                   92200:                                        <td style="padding-right: 2em; vertical-align: top">
                   92201:                                                <a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a>
                   92202:                                        </td>
                   92203:                                        <td>
                   92204:                                                                                        The Structures_Graph_Node class represents a Node that can be member of a  graph node set.
                   92205:                                                                                </td>
                   92206:                                </tr>
                   92207:                                                        </table>
                   92208:                </div>
                   92209:        </div>
                   92210: 
                   92211:        <a name="sec-includes"></a>     
                   92212:        <div class="info-box">
                   92213:                <div class="info-box-title">Includes</div>
                   92214:                <div class="nav-bar">
                   92215:                        <a href="#sec-description">Description</a> |
                   92216:                                                        <a href="#sec-classes">Classes</a>
                   92217:                                |                                               <span class="disabled">Includes</span>
                   92218:                                                                                                                </div>
                   92219:                <div class="info-box-body">     
                   92220:                        <a name="_PEAR_php"><!-- --></a>
                   92221: <div class="evenrow">
                   92222:        
                   92223:        <div>
                   92224:                <span class="include-title">
                   92225:                        <span class="include-type">require_once</span>
                   92226:                        (<span class="include-name">'PEAR.php'</span>)
                   92227:                        (line <span class="line-number">35</span>)
                   92228:                </span>
                   92229:        </div>
                   92230: 
                   92231:        <!-- ========== Info from phpDoc block ========= -->
                   92232:        
                   92233: </div>
                   92234: <a name="_Structures/Graph_php"><!-- --></a>
                   92235: <div class="oddrow">
                   92236:        
                   92237:        <div>
                   92238:                <span class="include-title">
                   92239:                        <span class="include-type">require_once</span>
                   92240:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   92241:                        (line <span class="line-number">37</span>)
                   92242:                </span>
                   92243:        </div>
                   92244: 
                   92245:        <!-- ========== Info from phpDoc block ========= -->
                   92246:        
                   92247: </div>
                   92248:                </div>
                   92249:        </div>
                   92250:        
                   92251:        
                   92252:        
                   92253:        
                   92254:        <p class="notes" id="credit">
                   92255:                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>
                   92256:        </p>
                   92257:        </div></body>
                   92258: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_php.html0000644000076600000240000001020711461440275026702 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   92259: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92260:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92261:                <head>
                   92262:                        <!-- template designed by Marco Von Ballmoos -->
                   92263:                        <title>Docs for page Graph.php</title>
                   92264:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   92265:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92266:                </head>
                   92267:                <body>
                   92268:                        <div class="page-body">                 
                   92269: <h2 class="file-name">/Structures/Graph.php</h2>
                   92270: 
                   92271: <a name="sec-description"></a>
                   92272: <div class="info-box">
                   92273:        <div class="info-box-title">Description</div>
                   92274:        <div class="nav-bar">
                   92275:                                        <span class="disabled">Description</span> |
                   92276:                                                        <a href="#sec-classes">Classes</a>
                   92277:                        |                                                       <a href="#sec-includes">Includes</a>
                   92278:                        |                                                       <a href="#sec-constants">Constants</a>
                   92279:                                                                                </div>
                   92280:        <div class="info-box-body">     
                   92281:                <!-- ========== Info from phpDoc block ========= -->
                   92282: <p class="short-description">The Graph.php file contains the definition of the Structures_Graph class</p>
                   92283:        <ul class="tags">
                   92284:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></li>
                   92285:                        </ul>
                   92286:                
                   92287:                        </div>
                   92288: </div>
                   92289:                
                   92290:        <a name="sec-classes"></a>      
                   92291:        <div class="info-box">
                   92292:                <div class="info-box-title">Classes</div>
                   92293:                <div class="nav-bar">
                   92294:                        <a href="#sec-description">Description</a> |
                   92295:                        <span class="disabled">Classes</span>
                   92296:                        |                                                       <a href="#sec-includes">Includes</a>
                   92297:                                |                                                                               <a href="#sec-constants">Constants</a>
                   92298:                                                                                                                        </div>
                   92299:                <div class="info-box-body">     
                   92300:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   92301:                                <tr>
                   92302:                                        <th class="class-table-header">Class</th>
                   92303:                                        <th class="class-table-header">Description</th>
                   92304:                                </tr>
                   92305:                                                                <tr>
                   92306:                                        <td style="padding-right: 2em; vertical-align: top">
                   92307:                                                <a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a>
                   92308:                                        </td>
                   92309:                                        <td>
                   92310:                                                                                        The Structures_Graph class represents a graph data structure.
                   92311:                                                                                </td>
                   92312:                                </tr>
                   92313:                                                        </table>
                   92314:                </div>
                   92315:        </div>
                   92316: 
                   92317:        <a name="sec-includes"></a>     
                   92318:        <div class="info-box">
                   92319:                <div class="info-box-title">Includes</div>
                   92320:                <div class="nav-bar">
                   92321:                        <a href="#sec-description">Description</a> |
                   92322:                                                        <a href="#sec-classes">Classes</a>
                   92323:                                |                                               <span class="disabled">Includes</span>
                   92324:                        |                                                       <a href="#sec-constants">Constants</a>
                   92325:                                                                                                                        </div>
                   92326:                <div class="info-box-body">     
                   92327:                        <a name="_Structures/Graph/Node_php"><!-- --></a>
                   92328: <div class="oddrow">
                   92329:        
                   92330:        <div>
                   92331:                <span class="include-title">
                   92332:                        <span class="include-type">require_once</span>
                   92333:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   92334:                        (line <span class="line-number">37</span>)
                   92335:                </span>
                   92336:        </div>
                   92337: 
                   92338:        <!-- ========== Info from phpDoc block ========= -->
                   92339: <p class="short-description">Graph Node</p>
                   92340:        
                   92341: </div>
                   92342: <a name="_PEAR_php"><!-- --></a>
                   92343: <div class="evenrow">
                   92344:        
                   92345:        <div>
                   92346:                <span class="include-title">
                   92347:                        <span class="include-type">require_once</span>
                   92348:                        (<span class="include-name">'PEAR.php'</span>)
                   92349:                        (line <span class="line-number">35</span>)
                   92350:                </span>
                   92351:        </div>
                   92352: 
                   92353:        <!-- ========== Info from phpDoc block ========= -->
                   92354: <p class="short-description">PEAR base classes</p>
                   92355:        
                   92356: </div>
                   92357:                </div>
                   92358:        </div>
                   92359:        
                   92360:        <a name="sec-constants"></a>    
                   92361:        <div class="info-box">
                   92362:                <div class="info-box-title">Constants</div>
                   92363:                <div class="nav-bar">
                   92364:                        <a href="#sec-description">Description</a> |
                   92365:                                                        <a href="#sec-classes">Classes</a>
                   92366:                                |                                                                               <a href="#sec-includes">Includes</a>
                   92367:                                |                                               <span class="disabled">Constants</span>
                   92368:                                                                                        </div>
                   92369:                <div class="info-box-body">     
                   92370:                        <a name="defineSTRUCTURES_GRAPH_ERROR_GENERIC"><!-- --></a>
                   92371: <div class="oddrow">
                   92372:        
                   92373:        <div>
                   92374:                <span class="const-title">
                   92375:                        <span class="const-name">STRUCTURES_GRAPH_ERROR_GENERIC</span> = 100
                   92376:                        (line <span class="line-number">40</span>)
                   92377:                </span>
                   92378:        </div>
                   92379:        
                   92380:        <!-- ========== Info from phpDoc block ========= -->
                   92381:        
                   92382:                
                   92383: </div>
                   92384:                </div>
                   92385:        </div>
                   92386:        
                   92387:        
                   92388:        
                   92389:        <p class="notes" id="credit">
                   92390:                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>
                   92391:        </p>
                   92392:        </div></body>
                   92393: </html>Structures_Graph-1.0.4/docs/html/classtrees_Structures_Graph.html0000644000076600000240000000253011461440275024620 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   92394: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92395:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92396:                <head>
                   92397:                        <!-- template designed by Marco Von Ballmoos -->
                   92398:                        <title></title>
                   92399:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   92400:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92401:                </head>
                   92402:                <body>
                   92403:                                                
                   92404: <!-- Start of Class Data -->
                   92405: <H2>
                   92406:        
                   92407: </H2>
                   92408: <h2>Root class Structures_Graph</h2>
                   92409: <ul>
                   92410: <li><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a></li></ul>
                   92411: 
                   92412: <h2>Root class Structures_Graph_Manipulator_AcyclicTest</h2>
                   92413: <ul>
                   92414: <li><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li></ul>
                   92415: 
                   92416: <h2>Root class Structures_Graph_Manipulator_TopologicalSorter</h2>
                   92417: <ul>
                   92418: <li><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li></ul>
                   92419: 
                   92420: <h2>Root class Structures_Graph_Node</h2>
                   92421: <ul>
                   92422: <li><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></li></ul>
                   92423: 
                   92424:        <p class="notes" id="credit">
                   92425:                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>
                   92426:        </p>
                   92427:        </body>
                   92428: </html>Structures_Graph-1.0.4/docs/html/elementindex.html0000644000076600000240000003640711461440275021557 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   92429: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92430:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92431:                <head>
                   92432:                        <!-- template designed by Marco Von Ballmoos -->
                   92433:                        <title></title>
                   92434:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   92435:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92436:                </head>
                   92437:                <body>
                   92438:                                                <a name="top"></a>
                   92439: <h2>Full index</h2>
                   92440: <h3>Package indexes</h3>
                   92441: <ul>
                   92442:        <li><a href="elementindex_Structures_Graph.html">Structures_Graph</a></li>
                   92443: </ul>
                   92444: <br />
                   92445: <div class="index-letter-menu">
                   92446:        <a class="index-letter" href="elementindex.html#a">a</a>
                   92447:        <a class="index-letter" href="elementindex.html#c">c</a>
                   92448:        <a class="index-letter" href="elementindex.html#g">g</a>
                   92449:        <a class="index-letter" href="elementindex.html#i">i</a>
                   92450:        <a class="index-letter" href="elementindex.html#m">m</a>
                   92451:        <a class="index-letter" href="elementindex.html#n">n</a>
                   92452:        <a class="index-letter" href="elementindex.html#o">o</a>
                   92453:        <a class="index-letter" href="elementindex.html#r">r</a>
                   92454:        <a class="index-letter" href="elementindex.html#s">s</a>
                   92455:        <a class="index-letter" href="elementindex.html#t">t</a>
                   92456:        <a class="index-letter" href="elementindex.html#u">u</a>
                   92457: </div>
                   92458: 
                   92459:        <a name="a"></a>
                   92460:        <div class="index-letter-section">
                   92461:                <div style="float: left" class="index-letter-title">a</div>
                   92462:                <div style="float: right"><a href="#top">top</a></div>
                   92463:                <div style="clear: both"></div>
                   92464:        </div>
                   92465:        <dl>
                   92466:                        <dt class="field">
                   92467:                                                <span class="method-title">addNode</span>
                   92468:                                        </dt>
                   92469:                <dd class="index-item-body">
                   92470:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a> in Graph.php</div>
                   92471:                                                        <div class="index-item-description">Add a Node to the Graph</div>
                   92472:                                        </dd>
                   92473:                        <dt class="field">
                   92474:                                                <span class="include-title">AcyclicTest.php</span>
                   92475:                                        </dt>
                   92476:                <dd class="index-item-body">
                   92477:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">AcyclicTest.php</a> in AcyclicTest.php</div>
                   92478:                                        </dd>
                   92479:                </dl>
                   92480:        <a name="c"></a>
                   92481:        <div class="index-letter-section">
                   92482:                <div style="float: left" class="index-letter-title">c</div>
                   92483:                <div style="float: right"><a href="#top">top</a></div>
                   92484:                <div style="clear: both"></div>
                   92485:        </div>
                   92486:        <dl>
                   92487:                        <dt class="field">
                   92488:                                                <span class="method-title">connectsTo</span>
                   92489:                                        </dt>
                   92490:                <dd class="index-item-body">
                   92491:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectsTo">Structures_Graph_Node::connectsTo()</a> in Node.php</div>
                   92492:                                                        <div class="index-item-description">Test wether this node has an arc to the target node</div>
                   92493:                                        </dd>
                   92494:                        <dt class="field">
                   92495:                                                <span class="method-title">connectTo</span>
                   92496:                                        </dt>
                   92497:                <dd class="index-item-body">
                   92498:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectTo">Structures_Graph_Node::connectTo()</a> in Node.php</div>
                   92499:                                                        <div class="index-item-description">Connect this node to another one.</div>
                   92500:                                        </dd>
                   92501:                </dl>
                   92502:        <a name="g"></a>
                   92503:        <div class="index-letter-section">
                   92504:                <div style="float: left" class="index-letter-title">g</div>
                   92505:                <div style="float: right"><a href="#top">top</a></div>
                   92506:                <div style="clear: both"></div>
                   92507:        </div>
                   92508:        <dl>
                   92509:                        <dt class="field">
                   92510:                                                <span class="method-title">getData</span>
                   92511:                                        </dt>
                   92512:                <dd class="index-item-body">
                   92513:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetData">Structures_Graph_Node::getData()</a> in Node.php</div>
                   92514:                                                        <div class="index-item-description">Node data getter.</div>
                   92515:                                        </dd>
                   92516:                        <dt class="field">
                   92517:                                                <span class="method-title">getGraph</span>
                   92518:                                        </dt>
                   92519:                <dd class="index-item-body">
                   92520:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetGraph">Structures_Graph_Node::getGraph()</a> in Node.php</div>
                   92521:                                                        <div class="index-item-description">Node graph getter</div>
                   92522:                                        </dd>
                   92523:                        <dt class="field">
                   92524:                                                <span class="method-title">getMetadata</span>
                   92525:                                        </dt>
                   92526:                <dd class="index-item-body">
                   92527:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetMetadata">Structures_Graph_Node::getMetadata()</a> in Node.php</div>
                   92528:                                                        <div class="index-item-description">Node metadata getter</div>
                   92529:                                        </dd>
                   92530:                        <dt class="field">
                   92531:                                                <span class="method-title">getNeighbours</span>
                   92532:                                        </dt>
                   92533:                <dd class="index-item-body">
                   92534:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetNeighbours">Structures_Graph_Node::getNeighbours()</a> in Node.php</div>
                   92535:                                                        <div class="index-item-description">Return nodes connected to this one.</div>
                   92536:                                        </dd>
                   92537:                        <dt class="field">
                   92538:                                                <span class="method-title">getNodes</span>
                   92539:                                        </dt>
                   92540:                <dd class="index-item-body">
                   92541:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodgetNodes">Structures_Graph::getNodes()</a> in Graph.php</div>
                   92542:                                                        <div class="index-item-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</div>
                   92543:                                        </dd>
                   92544:                        <dt class="field">
                   92545:                                                <span class="include-title">Graph.php</span>
                   92546:                                        </dt>
                   92547:                <dd class="index-item-body">
                   92548:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html">Graph.php</a> in Graph.php</div>
                   92549:                                        </dd>
                   92550:                </dl>
                   92551:        <a name="i"></a>
                   92552:        <div class="index-letter-section">
                   92553:                <div style="float: left" class="index-letter-title">i</div>
                   92554:                <div style="float: right"><a href="#top">top</a></div>
                   92555:                <div style="clear: both"></div>
                   92556:        </div>
                   92557:        <dl>
                   92558:                        <dt class="field">
                   92559:                                                <span class="method-title">inDegree</span>
                   92560:                                        </dt>
                   92561:                <dd class="index-item-body">
                   92562:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodinDegree">Structures_Graph_Node::inDegree()</a> in Node.php</div>
                   92563:                                                        <div class="index-item-description">Calculate the in degree of the node.</div>
                   92564:                                        </dd>
                   92565:                        <dt class="field">
                   92566:                                                <span class="method-title">isAcyclic</span>
                   92567:                                        </dt>
                   92568:                <dd class="index-item-body">
                   92569:                        <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>
                   92570:                                                        <div class="index-item-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</div>
                   92571:                                        </dd>
                   92572:                        <dt class="field">
                   92573:                                                <span class="method-title">isDirected</span>
                   92574:                                        </dt>
                   92575:                <dd class="index-item-body">
                   92576:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodisDirected">Structures_Graph::isDirected()</a> in Graph.php</div>
                   92577:                                                        <div class="index-item-description">Return true if a graph is directed</div>
                   92578:                                        </dd>
                   92579:                </dl>
                   92580:        <a name="m"></a>
                   92581:        <div class="index-letter-section">
                   92582:                <div style="float: left" class="index-letter-title">m</div>
                   92583:                <div style="float: right"><a href="#top">top</a></div>
                   92584:                <div style="clear: both"></div>
                   92585:        </div>
                   92586:        <dl>
                   92587:                        <dt class="field">
                   92588:                                                <span class="method-title">metadataKeyExists</span>
                   92589:                                        </dt>
                   92590:                <dd class="index-item-body">
                   92591:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a> in Node.php</div>
                   92592:                                                        <div class="index-item-description">Test for existence of metadata under a given key.</div>
                   92593:                                        </dd>
                   92594:                </dl>
                   92595:        <a name="n"></a>
                   92596:        <div class="index-letter-section">
                   92597:                <div style="float: left" class="index-letter-title">n</div>
                   92598:                <div style="float: right"><a href="#top">top</a></div>
                   92599:                <div style="clear: both"></div>
                   92600:        </div>
                   92601:        <dl>
                   92602:                        <dt class="field">
                   92603:                                                <span class="include-title">Node.php</span>
                   92604:                                        </dt>
                   92605:                <dd class="index-item-body">
                   92606:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Node_php.html">Node.php</a> in Node.php</div>
                   92607:                                        </dd>
                   92608:                </dl>
                   92609:        <a name="o"></a>
                   92610:        <div class="index-letter-section">
                   92611:                <div style="float: left" class="index-letter-title">o</div>
                   92612:                <div style="float: right"><a href="#top">top</a></div>
                   92613:                <div style="clear: both"></div>
                   92614:        </div>
                   92615:        <dl>
                   92616:                        <dt class="field">
                   92617:                                                <span class="method-title">outDegree</span>
                   92618:                                        </dt>
                   92619:                <dd class="index-item-body">
                   92620:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodoutDegree">Structures_Graph_Node::outDegree()</a> in Node.php</div>
                   92621:                                                        <div class="index-item-description">Calculate the out degree of the node.</div>
                   92622:                                        </dd>
                   92623:                </dl>
                   92624:        <a name="r"></a>
                   92625:        <div class="index-letter-section">
                   92626:                <div style="float: left" class="index-letter-title">r</div>
                   92627:                <div style="float: right"><a href="#top">top</a></div>
                   92628:                <div style="clear: both"></div>
                   92629:        </div>
                   92630:        <dl>
                   92631:                        <dt class="field">
                   92632:                                                <span class="method-title">removeNode</span>
                   92633:                                        </dt>
                   92634:                <dd class="index-item-body">
                   92635:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a> in Graph.php</div>
                   92636:                                                        <div class="index-item-description">Remove a Node from the Graph</div>
                   92637:                                        </dd>
                   92638:                </dl>
                   92639:        <a name="s"></a>
                   92640:        <div class="index-letter-section">
                   92641:                <div style="float: left" class="index-letter-title">s</div>
                   92642:                <div style="float: right"><a href="#top">top</a></div>
                   92643:                <div style="clear: both"></div>
                   92644:        </div>
                   92645:        <dl>
                   92646:                        <dt class="field">
                   92647:                                                <span class="method-title">setData</span>
                   92648:                                        </dt>
                   92649:                <dd class="index-item-body">
                   92650:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetData">Structures_Graph_Node::setData()</a> in Node.php</div>
                   92651:                                                        <div class="index-item-description">Node data setter</div>
                   92652:                                        </dd>
                   92653:                        <dt class="field">
                   92654:                                                <span class="method-title">setGraph</span>
                   92655:                                        </dt>
                   92656:                <dd class="index-item-body">
                   92657:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetGraph">Structures_Graph_Node::setGraph()</a> in Node.php</div>
                   92658:                                                        <div class="index-item-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</div>
                   92659:                                        </dd>
                   92660:                        <dt class="field">
                   92661:                                                <span class="method-title">setMetadata</span>
                   92662:                                        </dt>
                   92663:                <dd class="index-item-body">
                   92664:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetMetadata">Structures_Graph_Node::setMetadata()</a> in Node.php</div>
                   92665:                                                        <div class="index-item-description">Node metadata setter</div>
                   92666:                                        </dd>
                   92667:                        <dt class="field">
                   92668:                                                <span class="method-title">sort</span>
                   92669:                                        </dt>
                   92670:                <dd class="index-item-body">
                   92671:                        <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>
                   92672:                                                        <div class="index-item-description">sort returns the graph's nodes, sorted by topological order.</div>
                   92673:                                        </dd>
                   92674:                        <dt class="field">
                   92675:                                                Structures_Graph
                   92676:                                        </dt>
                   92677:                <dd class="index-item-body">
                   92678:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a> in Graph.php</div>
                   92679:                                                        <div class="index-item-description">The Structures_Graph class represents a graph data structure.</div>
                   92680:                                        </dd>
                   92681:                        <dt class="field">
                   92682:                                                <span class="method-title">Structures_Graph</span>
                   92683:                                        </dt>
                   92684:                <dd class="index-item-body">
                   92685:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodStructures_Graph">Structures_Graph::Structures_Graph()</a> in Graph.php</div>
                   92686:                                                        <div class="index-item-description">Constructor</div>
                   92687:                                        </dd>
                   92688:                        <dt class="field">
                   92689:                                                <span class="const-title">STRUCTURES_GRAPH_ERROR_GENERIC</span>
                   92690:                                        </dt>
                   92691:                <dd class="index-item-body">
                   92692:                        <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>
                   92693:                                        </dd>
                   92694:                        <dt class="field">
                   92695:                                                Structures_Graph_Manipulator_AcyclicTest
                   92696:                                        </dt>
                   92697:                <dd class="index-item-body">
                   92698:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a> in AcyclicTest.php</div>
                   92699:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</div>
                   92700:                                        </dd>
                   92701:                        <dt class="field">
                   92702:                                                Structures_Graph_Manipulator_TopologicalSorter
                   92703:                                        </dt>
                   92704:                <dd class="index-item-body">
                   92705:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a> in TopologicalSorter.php</div>
                   92706:                                                        <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>
                   92707:                                        </dd>
                   92708:                        <dt class="field">
                   92709:                                                <span class="method-title">Structures_Graph_Node</span>
                   92710:                                        </dt>
                   92711:                <dd class="index-item-body">
                   92712:                        <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>
                   92713:                                                        <div class="index-item-description">Constructor</div>
                   92714:                                        </dd>
                   92715:                        <dt class="field">
                   92716:                                                Structures_Graph_Node
                   92717:                                        </dt>
                   92718:                <dd class="index-item-body">
                   92719:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a> in Node.php</div>
                   92720:                                                        <div class="index-item-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</div>
                   92721:                                        </dd>
                   92722:                </dl>
                   92723:        <a name="t"></a>
                   92724:        <div class="index-letter-section">
                   92725:                <div style="float: left" class="index-letter-title">t</div>
                   92726:                <div style="float: right"><a href="#top">top</a></div>
                   92727:                <div style="clear: both"></div>
                   92728:        </div>
                   92729:        <dl>
                   92730:                        <dt class="field">
                   92731:                                                <span class="include-title">TopologicalSorter.php</span>
                   92732:                                        </dt>
                   92733:                <dd class="index-item-body">
                   92734:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html">TopologicalSorter.php</a> in TopologicalSorter.php</div>
                   92735:                                        </dd>
                   92736:                </dl>
                   92737:        <a name="u"></a>
                   92738:        <div class="index-letter-section">
                   92739:                <div style="float: left" class="index-letter-title">u</div>
                   92740:                <div style="float: right"><a href="#top">top</a></div>
                   92741:                <div style="clear: both"></div>
                   92742:        </div>
                   92743:        <dl>
                   92744:                        <dt class="field">
                   92745:                                                <span class="method-title">unsetMetadata</span>
                   92746:                                        </dt>
                   92747:                <dd class="index-item-body">
                   92748:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodunsetMetadata">Structures_Graph_Node::unsetMetadata()</a> in Node.php</div>
                   92749:                                                        <div class="index-item-description">Delete metadata by key</div>
                   92750:                                        </dd>
                   92751:                </dl>
                   92752: 
                   92753: <div class="index-letter-menu">
                   92754:        <a class="index-letter" href="elementindex.html#a">a</a>
                   92755:        <a class="index-letter" href="elementindex.html#c">c</a>
                   92756:        <a class="index-letter" href="elementindex.html#g">g</a>
                   92757:        <a class="index-letter" href="elementindex.html#i">i</a>
                   92758:        <a class="index-letter" href="elementindex.html#m">m</a>
                   92759:        <a class="index-letter" href="elementindex.html#n">n</a>
                   92760:        <a class="index-letter" href="elementindex.html#o">o</a>
                   92761:        <a class="index-letter" href="elementindex.html#r">r</a>
                   92762:        <a class="index-letter" href="elementindex.html#s">s</a>
                   92763:        <a class="index-letter" href="elementindex.html#t">t</a>
                   92764:        <a class="index-letter" href="elementindex.html#u">u</a>
                   92765: </div> </body>
                   92766: </html>Structures_Graph-1.0.4/docs/html/elementindex_Structures_Graph.html0000644000076600000240000003712011461440275025134 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   92767: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   92768:   <html xmlns="http://www.w3.org/1999/xhtml">
                   92769:                <head>
                   92770:                        <!-- template designed by Marco Von Ballmoos -->
                   92771:                        <title></title>
                   92772:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   92773:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   92774:                </head>
                   92775:                <body>
                   92776:                                                <a name="top"></a>
                   92777: <h2>[Structures_Graph] element index</h2>
                   92778: <a href="elementindex.html">All elements</a>
                   92779: <br />
                   92780: <div class="index-letter-menu">
                   92781:        <a class="index-letter" href="elementindex_Structures_Graph.html#a">a</a>
                   92782:        <a class="index-letter" href="elementindex_Structures_Graph.html#c">c</a>
                   92783:        <a class="index-letter" href="elementindex_Structures_Graph.html#g">g</a>
                   92784:        <a class="index-letter" href="elementindex_Structures_Graph.html#i">i</a>
                   92785:        <a class="index-letter" href="elementindex_Structures_Graph.html#m">m</a>
                   92786:        <a class="index-letter" href="elementindex_Structures_Graph.html#n">n</a>
                   92787:        <a class="index-letter" href="elementindex_Structures_Graph.html#o">o</a>
                   92788:        <a class="index-letter" href="elementindex_Structures_Graph.html#r">r</a>
                   92789:        <a class="index-letter" href="elementindex_Structures_Graph.html#s">s</a>
                   92790:        <a class="index-letter" href="elementindex_Structures_Graph.html#t">t</a>
                   92791:        <a class="index-letter" href="elementindex_Structures_Graph.html#u">u</a>
                   92792: </div>
                   92793: 
                   92794:        <a name="a"></a>
                   92795:        <div class="index-letter-section">
                   92796:                <div style="float: left" class="index-letter-title">a</div>
                   92797:                <div style="float: right"><a href="#top">top</a></div>
                   92798:                <div style="clear: both"></div>
                   92799:        </div>
                   92800:        <dl>
                   92801:                        <dt class="field">
                   92802:                                                <span class="method-title">addNode</span>
                   92803:                                        </dt>
                   92804:                <dd class="index-item-body">
                   92805:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a> in Graph.php</div>
                   92806:                                                        <div class="index-item-description">Add a Node to the Graph</div>
                   92807:                                        </dd>
                   92808:                        <dt class="field">
                   92809:                                                <span class="include-title">AcyclicTest.php</span>
                   92810:                                        </dt>
                   92811:                <dd class="index-item-body">
                   92812:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">AcyclicTest.php</a> in AcyclicTest.php</div>
                   92813:                                        </dd>
                   92814:                </dl>
                   92815:        <a name="c"></a>
                   92816:        <div class="index-letter-section">
                   92817:                <div style="float: left" class="index-letter-title">c</div>
                   92818:                <div style="float: right"><a href="#top">top</a></div>
                   92819:                <div style="clear: both"></div>
                   92820:        </div>
                   92821:        <dl>
                   92822:                        <dt class="field">
                   92823:                                                <span class="method-title">connectsTo</span>
                   92824:                                        </dt>
                   92825:                <dd class="index-item-body">
                   92826:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectsTo">Structures_Graph_Node::connectsTo()</a> in Node.php</div>
                   92827:                                                        <div class="index-item-description">Test wether this node has an arc to the target node</div>
                   92828:                                        </dd>
                   92829:                        <dt class="field">
                   92830:                                                <span class="method-title">connectTo</span>
                   92831:                                        </dt>
                   92832:                <dd class="index-item-body">
                   92833:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectTo">Structures_Graph_Node::connectTo()</a> in Node.php</div>
                   92834:                                                        <div class="index-item-description">Connect this node to another one.</div>
                   92835:                                        </dd>
                   92836:                </dl>
                   92837:        <a name="g"></a>
                   92838:        <div class="index-letter-section">
                   92839:                <div style="float: left" class="index-letter-title">g</div>
                   92840:                <div style="float: right"><a href="#top">top</a></div>
                   92841:                <div style="clear: both"></div>
                   92842:        </div>
                   92843:        <dl>
                   92844:                        <dt class="field">
                   92845:                                                <span class="method-title">getData</span>
                   92846:                                        </dt>
                   92847:                <dd class="index-item-body">
                   92848:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetData">Structures_Graph_Node::getData()</a> in Node.php</div>
                   92849:                                                        <div class="index-item-description">Node data getter.</div>
                   92850:                                        </dd>
                   92851:                        <dt class="field">
                   92852:                                                <span class="method-title">getGraph</span>
                   92853:                                        </dt>
                   92854:                <dd class="index-item-body">
                   92855:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetGraph">Structures_Graph_Node::getGraph()</a> in Node.php</div>
                   92856:                                                        <div class="index-item-description">Node graph getter</div>
                   92857:                                        </dd>
                   92858:                        <dt class="field">
                   92859:                                                <span class="method-title">getMetadata</span>
                   92860:                                        </dt>
                   92861:                <dd class="index-item-body">
                   92862:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetMetadata">Structures_Graph_Node::getMetadata()</a> in Node.php</div>
                   92863:                                                        <div class="index-item-description">Node metadata getter</div>
                   92864:                                        </dd>
                   92865:                        <dt class="field">
                   92866:                                                <span class="method-title">getNeighbours</span>
                   92867:                                        </dt>
                   92868:                <dd class="index-item-body">
                   92869:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetNeighbours">Structures_Graph_Node::getNeighbours()</a> in Node.php</div>
                   92870:                                                        <div class="index-item-description">Return nodes connected to this one.</div>
                   92871:                                        </dd>
                   92872:                        <dt class="field">
                   92873:                                                <span class="method-title">getNodes</span>
                   92874:                                        </dt>
                   92875:                <dd class="index-item-body">
                   92876:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodgetNodes">Structures_Graph::getNodes()</a> in Graph.php</div>
                   92877:                                                        <div class="index-item-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</div>
                   92878:                                        </dd>
                   92879:                        <dt class="field">
                   92880:                                                <span class="include-title">Graph.php</span>
                   92881:                                        </dt>
                   92882:                <dd class="index-item-body">
                   92883:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html">Graph.php</a> in Graph.php</div>
                   92884:                                        </dd>
                   92885:                </dl>
                   92886:        <a name="i"></a>
                   92887:        <div class="index-letter-section">
                   92888:                <div style="float: left" class="index-letter-title">i</div>
                   92889:                <div style="float: right"><a href="#top">top</a></div>
                   92890:                <div style="clear: both"></div>
                   92891:        </div>
                   92892:        <dl>
                   92893:                        <dt class="field">
                   92894:                                                <span class="method-title">inDegree</span>
                   92895:                                        </dt>
                   92896:                <dd class="index-item-body">
                   92897:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodinDegree">Structures_Graph_Node::inDegree()</a> in Node.php</div>
                   92898:                                                        <div class="index-item-description">Calculate the in degree of the node.</div>
                   92899:                                        </dd>
                   92900:                        <dt class="field">
                   92901:                                                <span class="method-title">isAcyclic</span>
                   92902:                                        </dt>
                   92903:                <dd class="index-item-body">
                   92904:                        <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>
                   92905:                                                        <div class="index-item-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</div>
                   92906:                                        </dd>
                   92907:                        <dt class="field">
                   92908:                                                <span class="method-title">isDirected</span>
                   92909:                                        </dt>
                   92910:                <dd class="index-item-body">
                   92911:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodisDirected">Structures_Graph::isDirected()</a> in Graph.php</div>
                   92912:                                                        <div class="index-item-description">Return true if a graph is directed</div>
                   92913:                                        </dd>
                   92914:                </dl>
                   92915:        <a name="m"></a>
                   92916:        <div class="index-letter-section">
                   92917:                <div style="float: left" class="index-letter-title">m</div>
                   92918:                <div style="float: right"><a href="#top">top</a></div>
                   92919:                <div style="clear: both"></div>
                   92920:        </div>
                   92921:        <dl>
                   92922:                        <dt class="field">
                   92923:                                                <span class="method-title">metadataKeyExists</span>
                   92924:                                        </dt>
                   92925:                <dd class="index-item-body">
                   92926:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a> in Node.php</div>
                   92927:                                                        <div class="index-item-description">Test for existence of metadata under a given key.</div>
                   92928:                                        </dd>
                   92929:                </dl>
                   92930:        <a name="n"></a>
                   92931:        <div class="index-letter-section">
                   92932:                <div style="float: left" class="index-letter-title">n</div>
                   92933:                <div style="float: right"><a href="#top">top</a></div>
                   92934:                <div style="clear: both"></div>
                   92935:        </div>
                   92936:        <dl>
                   92937:                        <dt class="field">
                   92938:                                                <span class="include-title">Node.php</span>
                   92939:                                        </dt>
                   92940:                <dd class="index-item-body">
                   92941:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Node_php.html">Node.php</a> in Node.php</div>
                   92942:                                        </dd>
                   92943:                </dl>
                   92944:        <a name="o"></a>
                   92945:        <div class="index-letter-section">
                   92946:                <div style="float: left" class="index-letter-title">o</div>
                   92947:                <div style="float: right"><a href="#top">top</a></div>
                   92948:                <div style="clear: both"></div>
                   92949:        </div>
                   92950:        <dl>
                   92951:                        <dt class="field">
                   92952:                                                <span class="method-title">outDegree</span>
                   92953:                                        </dt>
                   92954:                <dd class="index-item-body">
                   92955:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodoutDegree">Structures_Graph_Node::outDegree()</a> in Node.php</div>
                   92956:                                                        <div class="index-item-description">Calculate the out degree of the node.</div>
                   92957:                                        </dd>
                   92958:                </dl>
                   92959:        <a name="r"></a>
                   92960:        <div class="index-letter-section">
                   92961:                <div style="float: left" class="index-letter-title">r</div>
                   92962:                <div style="float: right"><a href="#top">top</a></div>
                   92963:                <div style="clear: both"></div>
                   92964:        </div>
                   92965:        <dl>
                   92966:                        <dt class="field">
                   92967:                                                <span class="method-title">removeNode</span>
                   92968:                                        </dt>
                   92969:                <dd class="index-item-body">
                   92970:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a> in Graph.php</div>
                   92971:                                                        <div class="index-item-description">Remove a Node from the Graph</div>
                   92972:                                        </dd>
                   92973:                </dl>
                   92974:        <a name="s"></a>
                   92975:        <div class="index-letter-section">
                   92976:                <div style="float: left" class="index-letter-title">s</div>
                   92977:                <div style="float: right"><a href="#top">top</a></div>
                   92978:                <div style="clear: both"></div>
                   92979:        </div>
                   92980:        <dl>
                   92981:                        <dt class="field">
                   92982:                                                <span class="method-title">setData</span>
                   92983:                                        </dt>
                   92984:                <dd class="index-item-body">
                   92985:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetData">Structures_Graph_Node::setData()</a> in Node.php</div>
                   92986:                                                        <div class="index-item-description">Node data setter</div>
                   92987:                                        </dd>
                   92988:                        <dt class="field">
                   92989:                                                <span class="method-title">setGraph</span>
                   92990:                                        </dt>
                   92991:                <dd class="index-item-body">
                   92992:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetGraph">Structures_Graph_Node::setGraph()</a> in Node.php</div>
                   92993:                                                        <div class="index-item-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</div>
                   92994:                                        </dd>
                   92995:                        <dt class="field">
                   92996:                                                <span class="method-title">setMetadata</span>
                   92997:                                        </dt>
                   92998:                <dd class="index-item-body">
                   92999:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetMetadata">Structures_Graph_Node::setMetadata()</a> in Node.php</div>
                   93000:                                                        <div class="index-item-description">Node metadata setter</div>
                   93001:                                        </dd>
                   93002:                        <dt class="field">
                   93003:                                                <span class="method-title">sort</span>
                   93004:                                        </dt>
                   93005:                <dd class="index-item-body">
                   93006:                        <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>
                   93007:                                                        <div class="index-item-description">sort returns the graph's nodes, sorted by topological order.</div>
                   93008:                                        </dd>
                   93009:                        <dt class="field">
                   93010:                                                Structures_Graph
                   93011:                                        </dt>
                   93012:                <dd class="index-item-body">
                   93013:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a> in Graph.php</div>
                   93014:                                                        <div class="index-item-description">The Structures_Graph class represents a graph data structure.</div>
                   93015:                                        </dd>
                   93016:                        <dt class="field">
                   93017:                                                <span class="method-title">Structures_Graph</span>
                   93018:                                        </dt>
                   93019:                <dd class="index-item-body">
                   93020:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodStructures_Graph">Structures_Graph::Structures_Graph()</a> in Graph.php</div>
                   93021:                                                        <div class="index-item-description">Constructor</div>
                   93022:                                        </dd>
                   93023:                        <dt class="field">
                   93024:                                                <span class="const-title">STRUCTURES_GRAPH_ERROR_GENERIC</span>
                   93025:                                        </dt>
                   93026:                <dd class="index-item-body">
                   93027:                        <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>
                   93028:                                        </dd>
                   93029:                        <dt class="field">
                   93030:                                                Structures_Graph_Manipulator_AcyclicTest
                   93031:                                        </dt>
                   93032:                <dd class="index-item-body">
                   93033:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a> in AcyclicTest.php</div>
                   93034:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</div>
                   93035:                                        </dd>
                   93036:                        <dt class="field">
                   93037:                                                Structures_Graph_Manipulator_TopologicalSorter
                   93038:                                        </dt>
                   93039:                <dd class="index-item-body">
                   93040:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a> in TopologicalSorter.php</div>
                   93041:                                                        <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>
                   93042:                                        </dd>
                   93043:                        <dt class="field">
                   93044:                                                <span class="method-title">Structures_Graph_Node</span>
                   93045:                                        </dt>
                   93046:                <dd class="index-item-body">
                   93047:                        <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>
                   93048:                                                        <div class="index-item-description">Constructor</div>
                   93049:                                        </dd>
                   93050:                        <dt class="field">
                   93051:                                                Structures_Graph_Node
                   93052:                                        </dt>
                   93053:                <dd class="index-item-body">
                   93054:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a> in Node.php</div>
                   93055:                                                        <div class="index-item-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</div>
                   93056:                                        </dd>
                   93057:                </dl>
                   93058:        <a name="t"></a>
                   93059:        <div class="index-letter-section">
                   93060:                <div style="float: left" class="index-letter-title">t</div>
                   93061:                <div style="float: right"><a href="#top">top</a></div>
                   93062:                <div style="clear: both"></div>
                   93063:        </div>
                   93064:        <dl>
                   93065:                        <dt class="field">
                   93066:                                                <span class="include-title">TopologicalSorter.php</span>
                   93067:                                        </dt>
                   93068:                <dd class="index-item-body">
                   93069:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html">TopologicalSorter.php</a> in TopologicalSorter.php</div>
                   93070:                                        </dd>
                   93071:                </dl>
                   93072:        <a name="u"></a>
                   93073:        <div class="index-letter-section">
                   93074:                <div style="float: left" class="index-letter-title">u</div>
                   93075:                <div style="float: right"><a href="#top">top</a></div>
                   93076:                <div style="clear: both"></div>
                   93077:        </div>
                   93078:        <dl>
                   93079:                        <dt class="field">
                   93080:                                                <span class="method-title">unsetMetadata</span>
                   93081:                                        </dt>
                   93082:                <dd class="index-item-body">
                   93083:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodunsetMetadata">Structures_Graph_Node::unsetMetadata()</a> in Node.php</div>
                   93084:                                                        <div class="index-item-description">Delete metadata by key</div>
                   93085:                                        </dd>
                   93086:                </dl>
                   93087: 
                   93088: <div class="index-letter-menu">
                   93089:        <a class="index-letter" href="elementindex_Structures_Graph.html#a">a</a>
                   93090:        <a class="index-letter" href="elementindex_Structures_Graph.html#c">c</a>
                   93091:        <a class="index-letter" href="elementindex_Structures_Graph.html#g">g</a>
                   93092:        <a class="index-letter" href="elementindex_Structures_Graph.html#i">i</a>
                   93093:        <a class="index-letter" href="elementindex_Structures_Graph.html#m">m</a>
                   93094:        <a class="index-letter" href="elementindex_Structures_Graph.html#n">n</a>
                   93095:        <a class="index-letter" href="elementindex_Structures_Graph.html#o">o</a>
                   93096:        <a class="index-letter" href="elementindex_Structures_Graph.html#r">r</a>
                   93097:        <a class="index-letter" href="elementindex_Structures_Graph.html#s">s</a>
                   93098:        <a class="index-letter" href="elementindex_Structures_Graph.html#t">t</a>
                   93099:        <a class="index-letter" href="elementindex_Structures_Graph.html#u">u</a>
                   93100: </div> </body>
                   93101: </html>Structures_Graph-1.0.4/docs/html/errors.html0000644000076600000240000000132511461440275020401 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   93102: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   93103:   <html xmlns="http://www.w3.org/1999/xhtml">
                   93104:                <head>
                   93105:                        <!-- template designed by Marco Von Ballmoos -->
                   93106:                        <title>phpDocumentor Parser Errors and Warnings</title>
                   93107:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   93108:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   93109:                </head>
                   93110:                <body>
                   93111:                                                <a href="#Post-parsing">Post-parsing</a><br>
                   93112:        <p class="notes" id="credit">
                   93113:                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>
                   93114:        </p>
                   93115:        </body>
                   93116: </html>Structures_Graph-1.0.4/docs/html/index.html0000644000076600000240000000176111461440275020200 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   93117: <!DOCTYPE html 
                   93118:      PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//FR"
                   93119:      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
                   93120:    <html xmlns="http://www.w3.org/1999/xhtml">
                   93121: <head>
                   93122:        <!-- Generated by phpDocumentor on Fri, 30 Jan 2004 16:37:28 +0000  -->
                   93123:   <title>Structures_Graph Documentation</title>
                   93124:   <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   93125: </head>
                   93126: 
                   93127: <FRAMESET rows='100,*'>
                   93128:        <FRAME src='packages.html' name='left_top' frameborder="1" bordercolor="#999999">
                   93129:        <FRAMESET cols='25%,*'>
                   93130:                <FRAME src='li_Structures_Graph.html' name='left_bottom' frameborder="1" bordercolor="#999999">
                   93131:                <FRAME src='Structures_Graph/tutorial_Structures_Graph.pkg.html' name='right' frameborder="1" bordercolor="#999999">
                   93132:        </FRAMESET>
                   93133:        <NOFRAMES>
                   93134:                <H2>Frame Alert</H2>
                   93135:                <P>This document is designed to be viewed using the frames feature.
                   93136:                If you see this message, you are using a non-frame-capable web client.</P>
                   93137:        </NOFRAMES>
                   93138: </FRAMESET>
                   93139: </HTML>Structures_Graph-1.0.4/docs/html/li_Structures_Graph.html0000644000076600000240000000476011461440275023063 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   93140: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   93141:   <html xmlns="http://www.w3.org/1999/xhtml">
                   93142:                <head>
                   93143:                        <!-- template designed by Marco Von Ballmoos -->
                   93144:                        <title></title>
                   93145:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   93146:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   93147:                </head>
                   93148:                <body>
                   93149:                                                <div class="package-title">Structures_Graph</div>
                   93150: <div class="package-details">
                   93151: 
                   93152:        <dl class="tree">
                   93153:                
                   93154:                <dt class="folder-title">Description</dt>
                   93155:                <dd>
                   93156:                        <a href='classtrees_Structures_Graph.html' target='right'>Class trees</a><br />
                   93157:                        <a href='elementindex_Structures_Graph.html' target='right'>Index of elements</a><br />
                   93158:                                                        <a href="todolist.html" target="right">Todo List</a><br />
                   93159:                                        </dd>
                   93160:        
                   93161:                                                        
                   93162:                                                        
                   93163:                                                                        <dt class="folder-title">Tutorials/Manuals</dt>
                   93164:                                        <dd>
                   93165:                                                                                        <dl class="tree">
                   93166:                                                <dt class="folder-title">Package-level</dt>
                   93167:                                                <dd>
                   93168:                                                                                                        <div><a href="Structures_Graph/tutorial_Structures_Graph.pkg.html" target="right">Structures_Graph Tutorial</a></div>
                   93169: 
                   93170:                                                                                                </dd>
                   93171:                                                </dl>
                   93172:                                                                                
                   93173:                                                                                
                   93174:                                                                                </dd>
                   93175:                                                                                                        <dt class="folder-title">Classes</dt>
                   93176:                                                                                        <dd><a href='Structures_Graph/Structures_Graph.html' target='right'>Structures_Graph</a></dd>
                   93177:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html' target='right'>Structures_Graph_Manipulator_AcyclicTest</a></dd>
                   93178:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html' target='right'>Structures_Graph_Manipulator_TopologicalSorter</a></dd>
                   93179:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Node.html' target='right'>Structures_Graph_Node</a></dd>
                   93180:                                                                                                                                                                                <dt class="folder-title">Files</dt>
                   93181:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html' target='right'>AcyclicTest.php</a></dd>
                   93182:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_php.html' target='right'>Graph.php</a></dd>
                   93183:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Node_php.html' target='right'>Node.php</a></dd>
                   93184:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html' target='right'>TopologicalSorter.php</a></dd>
                   93185:                                                                                                                                        
                   93186:                                                
                   93187:                        </dl>
                   93188: </div>
                   93189: <p class="notes"><a href="http://www.phpdoc.org" target="_blank">phpDocumentor v <span class="field">1.2.3</span></a></p>
                   93190: </BODY>
                   93191: </HTML>Structures_Graph-1.0.4/docs/html/packages.html0000644000076600000240000000164111461440275020644 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   93192: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   93193:   <html xmlns="http://www.w3.org/1999/xhtml">
                   93194:                <head>
                   93195:                        <!-- template designed by Marco Von Ballmoos -->
                   93196:                        <title></title>
                   93197:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   93198:                        <link rel="stylesheet" href="media/banner.css" />
                   93199:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   93200:                </head>
                   93201:                <body>
                   93202:                        <div class="banner">
                   93203:                                <div class="banner-title">Structures_Graph</div>
                   93204:                                <div class="banner-menu">
                   93205:                <table cellpadding="0" cellspacing="0" style="width: 100%">
                   93206:                  <tr>
                   93207:               <td>
                   93208:                                                                              </td>
                   93209:               <td style="width: 2em">&nbsp;</td>
                   93210:               <td style="text-align: right">
                   93211:                                                                              </td>
                   93212:                                                </tr>
                   93213:           </table>
                   93214:                                </div>
                   93215:                        </div>
                   93216:                </body>
                   93217:        </html>Structures_Graph-1.0.4/docs/html/todolist.html0000644000076600000240000000155411461440275020732 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   93218: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   93219:   <html xmlns="http://www.w3.org/1999/xhtml">
                   93220:                <head>
                   93221:                        <!-- template designed by Marco Von Ballmoos -->
                   93222:                        <title>Todo List</title>
                   93223:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   93224:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   93225:                </head>
                   93226:                <body>
                   93227:                                                <div align="center"><h1>Todo List</h1></div>
                   93228: <h2>Structures_Graph</h2>
                   93229: <h3><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a></h3>
                   93230: <ul>
                   93231:     <li>This is unimplemented</li>
                   93232: </ul>
                   93233:        <p class="notes" id="credit">
                   93234:                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>
                   93235:        </p>
                   93236:        </body>
                   93237: </html>Structures_Graph-1.0.4/docs/tutorials/Structures_Graph/Structures_Graph.pkg0000644000076600000240000000771411461440275026604 0ustar  bbieberstaff<refentry id="{@id package.database.structures_graph.tutorial}">
                   93238:  <refnamediv>
                   93239:   <refname><classname>Structures_Graph</classname> Tutorial</refname>
                   93240:   <refpurpose>A first tour of graph datastructure manipulation</refpurpose>
                   93241:  </refnamediv>
                   93242:  <refsect1 id="{@id package.database.structures_graph.tutorial.intro}">
                   93243:   <title>Introduction</title>
                   93244:   <para>
                   93245:   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.
                   93246:   </para>
                   93247:   <para>
                   93248:   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.
                   93249:   </para>
                   93250:  </refsect1>
                   93251:  <refsect1 id="{@id package.database.structures_graph.tutorial.creation}">
                   93252:   <title>Creating a Graph</title>
                   93253:   <para>
                   93254:    Creating a graph is done using the simple constructor:
                   93255:    <programlisting>
                   93256:     <![CDATA[
                   93257: require_once 'Structures/Graph.php';
                   93258: 
                   93259: $directedGraph =& new Structures_Graph(true);
                   93260: $nonDirectedGraph =& new Structures_Graph(false);
                   93261:     ]]>
                   93262:    </programlisting>
                   93263:    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.
                   93264:   </para>
                   93265:   <para>
                   93266:   To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
                   93267:    <programlisting>
                   93268:     <![CDATA[
                   93269: require_once 'Structures/Graph/Node.php';
                   93270: 
                   93271: $nodeOne =& new Structures_Graph_Node();
                   93272: $nodeTwo =& new Structures_Graph_Node();
                   93273: $nodeThree =& new Structures_Graph_Node();
                   93274: 
                   93275: $directedGraph->addNode(&$nodeOne);
                   93276: $directedGraph->addNode(&$nodeTwo);
                   93277: $directedGraph->addNode(&$nodeThree);
                   93278:     ]]>
                   93279:    </programlisting>
                   93280:    and then setup the arcs:
                   93281:    <programlisting>
                   93282:     <![CDATA[
                   93283: $nodeOne->connectTo($nodeTwo);
                   93284: $nodeOne->connectTo($nodeThree);
                   93285:     ]]>
                   93286:    </programlisting>
                   93287:    Note that arcs can only be created after the nodes have been inserted into the graph. 
                   93288:   </para>
                   93289:  </refsect1>
                   93290:  <refsect1 id="{@id package.database.structures_graph.tutorial.nodesanddata}">
                   93291:   <title>Associating Data</title>
                   93292:   <para>
                   93293:   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.
                   93294:    <programlisting>
                   93295:     <![CDATA[
                   93296: $nodeOne->setData("Node One's Data is a String");
                   93297: $nodeTwo->setData(1976);
                   93298: $nodeThree->setData('Some other string');
                   93299: 
                   93300: print("NodeTwo's Data is an integer: " . $nodeTwo->getData());
                   93301:     ]]>
                   93302:    </programlisting>
                   93303:   </para>
                   93304:   <para>
                   93305:   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:
                   93306:    <programlisting>
                   93307:     <![CDATA[
                   93308: $nodeOne->setMetadata('example key', "Node One's Sample Metadata");
                   93309: print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key'));
                   93310: $nodeOne->unsetMetadata('example key');
                   93311:     ]]>
                   93312:    </programlisting>
                   93313:   </para>
                   93314:  </refsect1>
                   93315:  <refsect1 id="{@id package.database.structures_graph.tutorial.querying}">
                   93316:   <title>Querying a Graph</title>
                   93317:   <para>
                   93318:   Structures_Graph provides for basic querying of the graph:
                   93319:    <programlisting>
                   93320:     <![CDATA[
                   93321: // Nodes are able to calculate their indegree and outdegree
                   93322: print("NodeOne's inDegree: " . $nodeOne->inDegree());
                   93323: print("NodeOne's outDegree: " . $nodeOne->outDegree());
                   93324: 
                   93325: // and naturally, nodes can report on their arcs
                   93326: $arcs = $nodeOne->getNeighbours();
                   93327: for ($i=0;$i<sizeof($arcs);$i++) {
                   93328:     print("NodeOne has an arc to " . $arcs[$i]->getData());
                   93329: }
                   93330:     ]]>
                   93331:    </programlisting>
                   93332:   </para>
                   93333:  </refsect1>
                   93334: </refentry>
                   93335: Structures_Graph-1.0.4/docs/generate.sh0000755000076600000240000000055511461440275017370 0ustar  bbieberstaff#!/bin/sh
                   93336: (cd ..; tar czf docs/arch.tgz "{arch}")
                   93337: rm -Rf "../{arch}"
                   93338: rm -Rf ./html
                   93339: mkdir -p ./html
                   93340: phpdoc --directory ../Structures,./tutorials --target ./html --title "Structures_Graph Documentation" --output "HTML:frames" --defaultpackagename structures_graph --defaultcategoryname structures --pear 
                   93341: (cd ..; tar --absolute-names -xzf docs/arch.tgz)
                   93342: #rm arch.tgz
                   93343: Structures_Graph-1.0.4/Structures/Graph/Manipulator/AcyclicTest.php0000644000076600000240000001316011461440275024742 0ustar  bbieberstaff<?php
                   93344: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   93345: // +-----------------------------------------------------------------------------+
                   93346: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   93347: // +-----------------------------------------------------------------------------+
                   93348: // | This file is part of Structures_Graph.                                      |
                   93349: // |                                                                             |
                   93350: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   93351: // | it under the terms of the GNU Lesser General Public License as published by |
                   93352: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   93353: // | (at your option) any later version.                                         |
                   93354: // |                                                                             |
                   93355: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   93356: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   93357: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   93358: // | GNU Lesser General Public License for more details.                         |
                   93359: // |                                                                             |
                   93360: // | You should have received a copy of the GNU Lesser General Public License    |
                   93361: // | along with Structures_Graph; if not, write to the Free Software             |
                   93362: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   93363: // | 02111-1307 USA                                                              |
                   93364: // +-----------------------------------------------------------------------------+
                   93365: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   93366: // +-----------------------------------------------------------------------------+
                   93367: //
                   93368: /**
                   93369:  * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
                   93370:  * 
                   93371:  * @see Structures_Graph_Manipulator_AcyclicTest
                   93372:  * @package Structures_Graph
                   93373:  */
                   93374: 
                   93375: /* dependencies {{{ */
                   93376: /** */
                   93377: require_once 'PEAR.php';
                   93378: /** */
                   93379: require_once 'Structures/Graph.php';
                   93380: /** */
                   93381: require_once 'Structures/Graph/Node.php';
                   93382: /* }}} */
                   93383: 
                   93384: /* class Structures_Graph_Manipulator_AcyclicTest {{{ */
                   93385: /**
                   93386:  * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
                   93387:  * which tests whether a graph contains a cycle. 
                   93388:  * 
                   93389:  * The definition of an acyclic graph used in this manipulator is that of a 
                   93390:  * DAG. The graph must be directed, or else it is considered cyclic, even when 
                   93391:  * there are no arcs.
                   93392:  *
                   93393:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   93394:  * @copyright  (c) 2004 by S閞gio Carvalho
                   93395:  * @package Structures_Graph
                   93396:  */
                   93397: class Structures_Graph_Manipulator_AcyclicTest {
                   93398:     /* _nonVisitedInDegree {{{ */
                   93399:     /**
                   93400:     *
                   93401:     * This is a variant of Structures_Graph::inDegree which does 
                   93402:     * not count nodes marked as visited.
                   93403:     *
                   93404:     * @access   private
                   93405:     * @return  integer  Number of non-visited nodes that link to this one
                   93406:     */
                   93407:     function _nonVisitedInDegree(&$node) {
                   93408:         $result = 0;
                   93409:         $graphNodes =& $node->_graph->getNodes();
                   93410:         foreach (array_keys($graphNodes) as $key) {
                   93411:             if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   93412:         }
                   93413:         return $result;
                   93414:         
                   93415:     }
                   93416:     /* }}} */
                   93417: 
                   93418:     /* _isAcyclic {{{ */
                   93419:     /**
                   93420:     * @access   private
                   93421:     */
                   93422:     function _isAcyclic(&$graph) {
                   93423:         // Mark every node as not visited
                   93424:         $nodes =& $graph->getNodes();
                   93425:         $nodeKeys = array_keys($nodes);
                   93426:         $refGenerator = array();
                   93427:         foreach($nodeKeys as $key) {
                   93428:             $refGenerator[] = false;
                   93429:             $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   93430:         }
                   93431: 
                   93432:         // Iteratively peel off leaf nodes
                   93433:         do {
                   93434:             // Find out which nodes are leafs (excluding visited nodes)
                   93435:             $leafNodes = array();
                   93436:             foreach($nodeKeys as $key) {
                   93437:                 if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
                   93438:                     $leafNodes[] =& $nodes[$key];
                   93439:                 }
                   93440:             }
                   93441:             // Mark leafs as visited
                   93442:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   93443:                 $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
                   93444:                 $visited = true;
                   93445:                 $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
                   93446:             }
                   93447:         } while (sizeof($leafNodes) > 0);
                   93448: 
                   93449:         // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
                   93450:         $result = true;
                   93451:         foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
                   93452:         
                   93453:         // Cleanup visited marks
                   93454:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
                   93455: 
                   93456:         return $result;
                   93457:     }
                   93458:     /* }}} */
                   93459: 
                   93460:     /* isAcyclic {{{ */
                   93461:     /**
                   93462:     *
                   93463:     * isAcyclic returns true if a graph contains no cycles, false otherwise.
                   93464:     *
                   93465:     * @return  boolean  true iff graph is acyclic
                   93466:     * @access  public
                   93467:     */
                   93468:     function isAcyclic(&$graph) {
                   93469:         // We only test graphs
                   93470:         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);
                   93471:         if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
                   93472: 
                   93473:         return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
                   93474:     }
                   93475:     /* }}} */
                   93476: }
                   93477: /* }}} */
                   93478: ?>
                   93479: Structures_Graph-1.0.4/Structures/Graph/Manipulator/TopologicalSorter.php0000644000076600000240000001504611461440275026213 0ustar  bbieberstaff<?php
                   93480: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   93481: // +-----------------------------------------------------------------------------+
                   93482: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   93483: // +-----------------------------------------------------------------------------+
                   93484: // | This file is part of Structures_Graph.                                      |
                   93485: // |                                                                             |
                   93486: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   93487: // | it under the terms of the GNU Lesser General Public License as published by |
                   93488: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   93489: // | (at your option) any later version.                                         |
                   93490: // |                                                                             |
                   93491: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   93492: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   93493: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   93494: // | GNU Lesser General Public License for more details.                         |
                   93495: // |                                                                             |
                   93496: // | You should have received a copy of the GNU Lesser General Public License    |
                   93497: // | along with Structures_Graph; if not, write to the Free Software             |
                   93498: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   93499: // | 02111-1307 USA                                                              |
                   93500: // +-----------------------------------------------------------------------------+
                   93501: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   93502: // +-----------------------------------------------------------------------------+
                   93503: //
                   93504: /**
                   93505:  * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
                   93506:  * 
                   93507:  * @see Structures_Graph_Manipulator_TopologicalSorter
                   93508:  * @package Structures_Graph
                   93509:  */
                   93510: 
                   93511: /* dependencies {{{ */
                   93512: /** */
                   93513: require_once 'PEAR.php';
                   93514: /** */
                   93515: require_once 'Structures/Graph.php';
                   93516: /** */
                   93517: require_once 'Structures/Graph/Node.php';
                   93518: /** */
                   93519: require_once 'Structures/Graph/Manipulator/AcyclicTest.php';
                   93520: /* }}} */
                   93521: 
                   93522: /* class Structures_Graph_Manipulator_TopologicalSorter {{{ */
                   93523: /**
                   93524:  * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator 
                   93525:  * which is able to return the set of nodes in a graph, sorted by topological 
                   93526:  * order.
                   93527:  *
                   93528:  * A graph may only be sorted topologically iff it's a DAG. You can test it
                   93529:  * with the Structures_Graph_Manipulator_AcyclicTest.
                   93530:  * 
                   93531:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   93532:  * @copyright  (c) 2004 by S閞gio Carvalho
                   93533:  * @see     Structures_Graph_Manipulator_AcyclicTest
                   93534:  * @package Structures_Graph
                   93535:  */
                   93536: class Structures_Graph_Manipulator_TopologicalSorter {
                   93537:     /* _nonVisitedInDegree {{{ */
                   93538:     /**
                   93539:     *
                   93540:     * This is a variant of Structures_Graph::inDegree which does 
                   93541:     * not count nodes marked as visited.
                   93542:     *
                   93543:     * @access   private
                   93544:     * @return  integer  Number of non-visited nodes that link to this one
                   93545:     */
                   93546:     function _nonVisitedInDegree(&$node) {
                   93547:         $result = 0;
                   93548:         $graphNodes =& $node->_graph->getNodes();
                   93549:         foreach (array_keys($graphNodes) as $key) {
                   93550:             if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   93551:         }
                   93552:         return $result;
                   93553:         
                   93554:     }
                   93555:     /* }}} */
                   93556: 
                   93557:     /* _sort {{{ */
                   93558:     /**
                   93559:     * @access   private
                   93560:     */
                   93561:     function _sort(&$graph) {
                   93562:         // Mark every node as not visited
                   93563:         $nodes =& $graph->getNodes();
                   93564:         $nodeKeys = array_keys($nodes);
                   93565:         $refGenerator = array();
                   93566:         foreach($nodeKeys as $key) {
                   93567:             $refGenerator[] = false;
                   93568:             $nodes[$key]->setMetadata('topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   93569:         }
                   93570: 
                   93571:         // Iteratively peel off leaf nodes
                   93572:         $topologicalLevel = 0;
                   93573:         do {
                   93574:             // Find out which nodes are leafs (excluding visited nodes)
                   93575:             $leafNodes = array();
                   93576:             foreach($nodeKeys as $key) {
                   93577:                 if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && Structures_Graph_Manipulator_TopologicalSorter::_nonVisitedInDegree($nodes[$key]) == 0) {
                   93578:                     $leafNodes[] =& $nodes[$key];
                   93579:                 }
                   93580:             }
                   93581:             // Mark leafs as visited
                   93582:             $refGenerator[] = $topologicalLevel;
                   93583:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   93584:                 $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
                   93585:                 $visited = true;
                   93586:                 $leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
                   93587:                 $leafNodes[$i]->setMetadata('topological-sort-level', $refGenerator[sizeof($refGenerator) - 1]);
                   93588:             }
                   93589:             $topologicalLevel++;
                   93590:         } while (sizeof($leafNodes) > 0);
                   93591: 
                   93592:         // Cleanup visited marks
                   93593:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('topological-sort-visited');
                   93594:     }
                   93595:     /* }}} */
                   93596: 
                   93597:     /* sort {{{ */
                   93598:     /**
                   93599:     *
                   93600:     * sort returns the graph's nodes, sorted by topological order. 
                   93601:     * 
                   93602:     * The result is an array with 
                   93603:     * as many entries as topological levels. Each entry in this array is an array of nodes within
                   93604:     * the given topological level.
                   93605:     *
                   93606:     * @return  array    The graph's nodes, sorted by topological order.
                   93607:     * @access  public
                   93608:     */
                   93609:     function sort(&$graph) {
                   93610:         // We only sort graphs
                   93611:         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);
                   93612:         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);
                   93613: 
                   93614:         Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
                   93615:         $result = array();
                   93616: 
                   93617:         // Fill out result array
                   93618:         $nodes =& $graph->getNodes();
                   93619:         $nodeKeys = array_keys($nodes);
                   93620:         foreach($nodeKeys as $key) {
                   93621:             if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) $result[$nodes[$key]->getMetadata('topological-sort-level')] = array();
                   93622:             $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key];
                   93623:             $nodes[$key]->unsetMetadata('topological-sort-level');
                   93624:         }
                   93625: 
                   93626:         return $result;
                   93627:     }
                   93628:     /* }}} */
                   93629: }
                   93630: /* }}} */
                   93631: ?>
                   93632: Structures_Graph-1.0.4/Structures/Graph/Node.php0000644000076600000240000002545011461440275021132 0ustar  bbieberstaff<?php
                   93633: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   93634: // +-----------------------------------------------------------------------------+
                   93635: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   93636: // +-----------------------------------------------------------------------------+
                   93637: // | This file is part of Structures_Graph.                                      |
                   93638: // |                                                                             |
                   93639: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   93640: // | it under the terms of the GNU Lesser General Public License as published by |
                   93641: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   93642: // | (at your option) any later version.                                         |
                   93643: // |                                                                             |
                   93644: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   93645: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   93646: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   93647: // | GNU Lesser General Public License for more details.                         |
                   93648: // |                                                                             |
                   93649: // | You should have received a copy of the GNU Lesser General Public License    |
                   93650: // | along with Structures_Graph; if not, write to the Free Software             |
                   93651: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   93652: // | 02111-1307 USA                                                              |
                   93653: // +-----------------------------------------------------------------------------+
                   93654: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   93655: // +-----------------------------------------------------------------------------+
                   93656: //
                   93657: /**
                   93658:  * This file contains the definition of the Structures_Graph_Node class
                   93659:  * 
                   93660:  * @see Structures_Graph_Node
                   93661:  * @package Structures_Graph
                   93662:  */
                   93663: 
                   93664: /* dependencies {{{ */
                   93665: /** */
                   93666: require_once 'PEAR.php';
                   93667: /** */
                   93668: require_once 'Structures/Graph.php';
                   93669: /* }}} */
                   93670: 
                   93671: /* class Structures_Graph_Node {{{ */
                   93672: /**
                   93673:  * The Structures_Graph_Node class represents a Node that can be member of a 
                   93674:  * graph node set.
                   93675:  *
                   93676:  * A graph node can contain data. Under this API, the node contains default data, 
                   93677:  * and key index data. It behaves, thus, both as a regular data node, and as a 
                   93678:  * dictionary (or associative array) node.
                   93679:  * 
                   93680:  * Regular data is accessed via getData and setData. Key indexed data is accessed
                   93681:  * via getMetadata and setMetadata.
                   93682:  *
                   93683:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   93684:  * @copyright  (c) 2004 by S閞gio Carvalho
                   93685:  * @package Structures_Graph
                   93686:  */
                   93687: /* }}} */
                   93688: class Structures_Graph_Node {
                   93689:     /* fields {{{ */
                   93690:     /** 
                   93691:      * @access private 
                   93692:      */
                   93693:     var $_data = null;
                   93694:     /** @access private */
                   93695:     var $_metadata = array();
                   93696:     /** @access private */
                   93697:     var $_arcs = array();
                   93698:     /** @access private */
                   93699:     var $_graph = null;
                   93700:     /* }}} */
                   93701: 
                   93702:     /* Constructor {{{ */
                   93703:     /**
                   93704:     *
                   93705:     * Constructor
                   93706:     *
                   93707:     * @access  public
                   93708:     */
                   93709:     function Structures_Graph_Node() {
                   93710:     }
                   93711:     /* }}} */
                   93712: 
                   93713:     /* getGraph {{{ */
                   93714:     /**
                   93715:     *
                   93716:     * Node graph getter
                   93717:     *
                   93718:     * @return  Structures_Graph        Graph where node is stored
                   93719:     * @access  public
                   93720:     */
                   93721:     function &getGraph() {
                   93722:         return $this->_graph;
                   93723:     }
                   93724:     /* }}} */
                   93725: 
                   93726:     /* setGraph {{{ */
                   93727:     /**
                   93728:     *
                   93729:     * Node graph setter. This method should not be called directly. Use Graph::addNode instead.
                   93730:     *
                   93731:     * @param    Structures_Graph   Set the graph for this node. 
                   93732:     * @see      Structures_Graph::addNode()
                   93733:     * @access  public
                   93734:     */
                   93735:     function setGraph(&$graph) {
                   93736:         $this->_graph =& $graph;
                   93737:     }
                   93738:     /* }}} */
                   93739: 
                   93740:     /* getData {{{ */
                   93741:     /**
                   93742:     *
                   93743:     * Node data getter.
                   93744:     * 
                   93745:     * Each graph node can contain a reference to one variable. This is the getter for that reference.
                   93746:     *
                   93747:     * @return  mixed   Data stored in node
                   93748:     * @access  public
                   93749:     */
                   93750:     function &getData() {
                   93751:         return $this->_data;
                   93752:     }
                   93753:     /* }}} */
                   93754: 
                   93755:     /* setData {{{ */
                   93756:     /**
                   93757:     *
                   93758:     * Node data setter
                   93759:     *
                   93760:     * Each graph node can contain a reference to one variable. This is the setter for that reference.
                   93761:     *
                   93762:     * @return  mixed   Data to store in node
                   93763:     * @access  public
                   93764:     */
                   93765:     function setData($data) {
                   93766:         $this->_data =& $data;
                   93767:     }
                   93768:     /* }}} */
                   93769: 
                   93770:     /* metadataKeyExists {{{ */
                   93771:     /**
                   93772:     *
                   93773:     * Test for existence of metadata under a given key.
                   93774:     *
                   93775:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   93776:     * associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
                   93777:     *
                   93778:     * @param    string    Key to test
                   93779:     * @return  boolean  
                   93780:     * @access  public
                   93781:     */
                   93782:     function metadataKeyExists($key) {
                   93783:         return array_key_exists($key, $this->_metadata);
                   93784:     }
                   93785:     /* }}} */
                   93786: 
                   93787:     /* getMetadata {{{ */
                   93788:     /**
                   93789:     *
                   93790:     * Node metadata getter
                   93791:     *
                   93792:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   93793:     * associative array or in a dictionary. This method gets the data under the given key. If the key does
                   93794:     * not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
                   93795:     *
                   93796:     * @param    string  Key
                   93797:     * @param    boolean nullIfNonexistent (defaults to false).
                   93798:     * @return  mixed   Metadata Data stored in node under given key
                   93799:     * @see      metadataKeyExists
                   93800:     * @access  public
                   93801:     */
                   93802:     function &getMetadata($key, $nullIfNonexistent = false) {
                   93803:         if (array_key_exists($key, $this->_metadata)) {
                   93804:             return $this->_metadata[$key];
                   93805:         } else {
                   93806:             if ($nullIfNonexistent) {
                   93807:                 $a = null;
                   93808:                 return $a;
                   93809:             } else {
                   93810:                 $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
                   93811:                 return $a;
                   93812:             }
                   93813:         }
                   93814:     }
                   93815:     /* }}} */
                   93816: 
                   93817:     /* unsetMetadata {{{ */
                   93818:     /**
                   93819:     *
                   93820:     * Delete metadata by key
                   93821:     *
                   93822:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   93823:     * associative array or in a dictionary. This method removes any data that might be stored under the provided key.
                   93824:     * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
                   93825:     *
                   93826:     * @param    string  Key
                   93827:     * @access  public
                   93828:     */
                   93829:     function unsetMetadata($key) {
                   93830:         if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
                   93831:     }
                   93832:     /* }}} */
                   93833: 
                   93834:     /* setMetadata {{{ */
                   93835:     /**
                   93836:     *
                   93837:     * Node metadata setter
                   93838:     *
                   93839:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   93840:     * associative array or in a dictionary. This method stores data under the given key. If the key already exists,
                   93841:     * previously stored data is discarded.
                   93842:     *
                   93843:     * @param    string  Key
                   93844:     * @param    mixed   Data 
                   93845:     * @access  public
                   93846:     */
                   93847:     function setMetadata($key, $data) {
                   93848:         $this->_metadata[$key] =& $data;
                   93849:     }
                   93850:     /* }}} */
                   93851: 
                   93852:     /* _connectTo {{{ */
                   93853:     /** @access private */
                   93854:     function _connectTo(&$destinationNode) {
                   93855:         $this->_arcs[] =& $destinationNode;
                   93856:     }
                   93857:     /* }}} */
                   93858: 
                   93859:     /* connectTo {{{ */
                   93860:     /**
                   93861:     *
                   93862:     * Connect this node to another one.
                   93863:     * 
                   93864:     * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
                   93865:     *
                   93866:     * @param    Structures_Graph_Node Node to connect to
                   93867:     * @access  public
                   93868:     */
                   93869:     function connectTo(&$destinationNode) {
                   93870:         // We only connect to nodes
                   93871:         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);
                   93872:         // Nodes must already be in graphs to be connected
                   93873:         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);
                   93874:         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);
                   93875:         // Connect here
                   93876:         $this->_connectTo($destinationNode);
                   93877:         // If graph is undirected, connect back
                   93878:         if (!$this->_graph->isDirected()) {
                   93879:             $destinationNode->_connectTo($this);
                   93880:         }
                   93881:     }
                   93882:     /* }}} */
                   93883: 
                   93884:     /* getNeighbours {{{ */
                   93885:     /**
                   93886:     *
                   93887:     * Return nodes connected to this one.
                   93888:     * 
                   93889:     * @return   array   Array of nodes
                   93890:     * @access  public
                   93891:     */
                   93892:     function getNeighbours() {
                   93893:         return $this->_arcs;
                   93894:     }
                   93895:     /* }}} */
                   93896: 
                   93897:     /* connectsTo {{{ */
                   93898:     /**
                   93899:     *
                   93900:     * Test wether this node has an arc to the target node
                   93901:     *
                   93902:     * @return  boolean   True if the two nodes are connected
                   93903:     * @access  public
                   93904:     */
                   93905:     function connectsTo(&$target) {
                   93906:         if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
                   93907:             return in_array($target, $this->getNeighbours(), true);
                   93908:         }
                   93909: 
                   93910:         $copy = $target;
                   93911:         $arcKeys = array_keys($this->_arcs);
                   93912:         foreach($arcKeys as $key) {
                   93913:             /* ZE1 chokes on this expression:
                   93914:                 if ($target === $arc) return true;
                   93915:               so, we'll use more convoluted stuff
                   93916:             */
                   93917:             $arc =& $this->_arcs[$key];
                   93918:             $target = true;
                   93919:             if ($arc === true) {
                   93920:                 $target = false;
                   93921:                 if ($arc === false) {
                   93922:                     $target = $copy;
                   93923:                     return true;
                   93924:                 }
                   93925:             }
                   93926:         }
                   93927:         $target = $copy;
                   93928:         return false;
                   93929:     }
                   93930:     /* }}} */
                   93931: 
                   93932:     /* inDegree {{{ */
                   93933:     /**
                   93934:     *
                   93935:     * Calculate the in degree of the node.
                   93936:     * 
                   93937:     * The indegree for a node is the number of arcs entering the node. For non directed graphs, 
                   93938:     * the indegree is equal to the outdegree.
                   93939:     *
                   93940:     * @return  integer  In degree of the node
                   93941:     * @access  public
                   93942:     */
                   93943:     function inDegree() {
                   93944:         if ($this->_graph == null) return 0;
                   93945:         if (!$this->_graph->isDirected()) return $this->outDegree();
                   93946:         $result = 0;
                   93947:         $graphNodes =& $this->_graph->getNodes();
                   93948:         foreach (array_keys($graphNodes) as $key) {
                   93949:             if ($graphNodes[$key]->connectsTo($this)) $result++;
                   93950:         }
                   93951:         return $result;
                   93952:         
                   93953:     }
                   93954:     /* }}} */
                   93955: 
                   93956:     /* outDegree {{{ */
                   93957:     /**
                   93958:     *
                   93959:     * Calculate the out degree of the node.
                   93960:     *
                   93961:     * The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
                   93962:     * the outdegree is always equal to the indegree.
                   93963:     * 
                   93964:     * @return  integer  Out degree of the node
                   93965:     * @access  public
                   93966:     */
                   93967:     function outDegree() {
                   93968:         if ($this->_graph == null) return 0;
                   93969:         return sizeof($this->_arcs);
                   93970:     }
                   93971:     /* }}} */
                   93972: }
                   93973: ?>
                   93974: Structures_Graph-1.0.4/Structures/Graph.php0000644000076600000240000001316311461440275020243 0ustar  bbieberstaff<?php
                   93975: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   93976: // +-----------------------------------------------------------------------------+
                   93977: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   93978: // +-----------------------------------------------------------------------------+
                   93979: // | This file is part of Structures_Graph.                                      |
                   93980: // |                                                                             |
                   93981: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   93982: // | it under the terms of the GNU Lesser General Public License as published by |
                   93983: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   93984: // | (at your option) any later version.                                         |
                   93985: // |                                                                             |
                   93986: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   93987: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   93988: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   93989: // | GNU Lesser General Public License for more details.                         |
                   93990: // |                                                                             |
                   93991: // | You should have received a copy of the GNU Lesser General Public License    |
                   93992: // | along with Structures_Graph; if not, write to the Free Software             |
                   93993: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   93994: // | 02111-1307 USA                                                              |
                   93995: // +-----------------------------------------------------------------------------+
                   93996: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   93997: // +-----------------------------------------------------------------------------+
                   93998: //
                   93999: /**
                   94000:  * The Graph.php file contains the definition of the Structures_Graph class 
                   94001:  *
                   94002:  * @see Structures_Graph
                   94003:  * @package Structures_Graph
                   94004:  */
                   94005: 
                   94006: /* dependencies {{{ */
                   94007: /** PEAR base classes */
                   94008: require_once 'PEAR.php';
                   94009: /** Graph Node */
                   94010: require_once 'Structures/Graph/Node.php';
                   94011: /* }}} */
                   94012: 
                   94013: define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
                   94014: 
                   94015: /* class Structures_Graph {{{ */
                   94016: /**
                   94017:  * The Structures_Graph class represents a graph data structure. 
                   94018:  *
                   94019:  * A Graph is a data structure composed by a set of nodes, connected by arcs.
                   94020:  * Graphs may either be directed or undirected. In a directed graph, arcs are 
                   94021:  * directional, and can be traveled only one way. In an undirected graph, arcs
                   94022:  * are bidirectional, and can be traveled both ways.
                   94023:  *
                   94024:  * @author             S閞gio Carvalho <sergio.carvalho@portugalmail.com> 
                   94025:  * @copyright  (c) 2004 by S閞gio Carvalho
                   94026:  * @package Structures_Graph
                   94027:  */
                   94028: /* }}} */
                   94029: class Structures_Graph {
                   94030:     /* fields {{{ */
                   94031:     /**
                   94032:      * @access private
                   94033:      */
                   94034:     var $_nodes = array();
                   94035:     /**
                   94036:      * @access private
                   94037:      */
                   94038:     var $_directed = false;
                   94039:     /* }}} */
                   94040: 
                   94041:     /* Constructor {{{ */
                   94042:     /**
                   94043:     *
                   94044:     * Constructor
                   94045:     *
                   94046:     * @param    boolean    Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)
                   94047:     * @access  public
                   94048:     */
                   94049:     function Structures_Graph($directed = true) {
                   94050:         $this->_directed = $directed;
                   94051:     }
                   94052:     /* }}} */
                   94053: 
                   94054:     /* isDirected {{{ */
                   94055:     /**
                   94056:     *
                   94057:     * Return true if a graph is directed
                   94058:     *
                   94059:     * @return  boolean  true if the graph is directed
                   94060:     * @access  public
                   94061:     */
                   94062:     function isDirected() {
                   94063:         return (boolean) $this->_directed;
                   94064:     }
                   94065:     /* }}} */
                   94066: 
                   94067:     /* addNode {{{ */
                   94068:     /**
                   94069:     *
                   94070:     * Add a Node to the Graph
                   94071:     *
                   94072:     * @param    Structures_Graph_Node   The node to be added.
                   94073:     * @access  public
                   94074:     */
                   94075:     function addNode(&$newNode) {
                   94076:         // We only add nodes
                   94077:         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);
                   94078:         // Graphs are node *sets*, so duplicates are forbidden. We allow nodes that are exactly equal, but disallow equal references.
                   94079:         foreach($this->_nodes as $key => $node) {
                   94080:             /*
                   94081:              ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object.
                   94082:              So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in 
                   94083:              $node)
                   94084:             */
                   94085:             $savedData = $this->_nodes[$key];
                   94086:             $referenceIsEqualFlag = false;
                   94087:             $this->_nodes[$key] = true;
                   94088:             if ($node === true) {
                   94089:                 $this->_nodes[$key] = false;
                   94090:                 if ($node === false) $referenceIsEqualFlag = true;
                   94091:             }
                   94092:             $this->_nodes[$key] = $savedData;
                   94093:             if ($referenceIsEqualFlag) return Pear::raiseError('Structures_Graph::addNode received an object that is a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC);
                   94094:         }
                   94095:         $this->_nodes[] =& $newNode;
                   94096:         $newNode->setGraph($this);
                   94097:     }
                   94098:     /* }}} */
                   94099: 
                   94100:     /* removeNode (unimplemented) {{{ */
                   94101:     /**
                   94102:     *
                   94103:     * Remove a Node from the Graph
                   94104:     *
                   94105:     * @todo     This is unimplemented
                   94106:     * @param    Structures_Graph_Node   The node to be removed from the graph
                   94107:     * @access  public
                   94108:     */
                   94109:     function removeNode(&$node) {
                   94110:     }
                   94111:     /* }}} */
                   94112: 
                   94113:     /* getNodes {{{ */
                   94114:     /**
                   94115:     *
                   94116:     * Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
                   94117:     *
                   94118:     * @access   public
                   94119:     * @see      Structures_Graph_Manipulator_TopologicalSorter
                   94120:     * @return   array The set of nodes in this graph
                   94121:     */
                   94122:     function &getNodes() {
                   94123:         return $this->_nodes;
                   94124:     }
                   94125:     /* }}} */
                   94126: }
                   94127: ?>
                   94128: Structures_Graph-1.0.4/tests/testCase/BasicGraph.php0000644000076600000240000002161111461440275021734 0ustar  bbieberstaff<?php
                   94129: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   94130: // +-----------------------------------------------------------------------------+
                   94131: // | Copyright (c) 2003 S閞gio Gon鏰lves Carvalho                                |
                   94132: // +-----------------------------------------------------------------------------+
                   94133: // | This file is part of Structures_Graph.                                      |
                   94134: // |                                                                             |
                   94135: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   94136: // | it under the terms of the GNU Lesser General Public License as published by |
                   94137: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   94138: // | (at your option) any later version.                                         |
                   94139: // |                                                                             |
                   94140: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   94141: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   94142: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   94143: // | GNU Lesser General Public License for more details.                         |
                   94144: // |                                                                             |
                   94145: // | You should have received a copy of the GNU Lesser General Public License    |
                   94146: // | along with Structures_Graph; if not, write to the Free Software             |
                   94147: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   94148: // | 02111-1307 USA                                                              |
                   94149: // +-----------------------------------------------------------------------------+
                   94150: // | Author: S閞gio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   94151: // +-----------------------------------------------------------------------------+
                   94152: //
                   94153: 
                   94154: require_once 'Structures/Graph.php';
                   94155: require_once 'PHPUnit/Framework.php';
                   94156: 
                   94157: /**
                   94158:  * @access private
                   94159:  */
                   94160: class BasicGraph extends PHPUnit_Framework_TestCase
                   94161: {
                   94162:     var $_graph = null;
                   94163: 
                   94164:     function test_create_graph() {
                   94165:         $this->_graph = new Structures_Graph();
                   94166:         $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); 
                   94167:     }
                   94168: 
                   94169:     function test_add_node() {
                   94170:         $this->_graph = new Structures_Graph();
                   94171:         $data = 1;
                   94172:         $node = new Structures_Graph_Node($data);
                   94173:         $this->_graph->addNode($node);
                   94174:         $node = new Structures_Graph_Node($data);
                   94175:         $this->_graph->addNode($node);
                   94176:         $node = new Structures_Graph_Node($data);
                   94177:         $this->_graph->addNode($node);
                   94178:     }
                   94179: 
                   94180:     function test_connect_node() {
                   94181:         $this->_graph = new Structures_Graph();
                   94182:         $data = 1;
                   94183:         $node1 = new Structures_Graph_Node($data);
                   94184:         $node2 = new Structures_Graph_Node($data);
                   94185:         $this->_graph->addNode($node1);
                   94186:         $this->_graph->addNode($node2);
                   94187:         $node1->connectTo($node2);
                   94188: 
                   94189:         $node =& $this->_graph->getNodes();
                   94190:         $node =& $node[0];
                   94191:         $node = $node->getNeighbours();
                   94192:         $node =& $node[0];
                   94193:         /* 
                   94194:          ZE1 == and === operators fail on $node,$node2 because of the recursion introduced
                   94195:          by the _graph field in the Node object. So, we'll use the stupid method for reference
                   94196:          testing
                   94197:         */
                   94198:         $node = true;
                   94199:         $this->assertTrue($node2);
                   94200:         $node = false;
                   94201:         $this->assertFalse($node2);
                   94202:     }
                   94203: 
                   94204:     function test_data_references() {
                   94205:         $this->_graph = new Structures_Graph();
                   94206:         $data = 1;
                   94207:         $node = new Structures_Graph_Node();
                   94208:         $node->setData(&$data);
                   94209:         $this->_graph->addNode($node);
                   94210:         $data = 2;
                   94211:         $dataInNode =& $this->_graph->getNodes();
                   94212:         $dataInNode =& $dataInNode[0];
                   94213:         $dataInNode =& $dataInNode->getData();
                   94214:         $this->assertTrue($data === $dataInNode);
                   94215:     }
                   94216: 
                   94217:     function test_metadata_references() {
                   94218:         $this->_graph = new Structures_Graph();
                   94219:         $data = 1;
                   94220:         $node = new Structures_Graph_Node();
                   94221:         $node->setMetadata('5', &$data);
                   94222:         $data = 2;
                   94223:         $dataInNode =& $node->getMetadata('5');
                   94224:         $this->assertTrue($data === $dataInNode);
                   94225:     }
                   94226:    
                   94227:     function test_metadata_key_exists() {
                   94228:         $this->_graph = new Structures_Graph();
                   94229:         $data = 1;
                   94230:         $node = new Structures_Graph_Node();
                   94231:         $node->setMetadata('5', $data);
                   94232:         $this->assertTrue($node->metadataKeyExists('5'));
                   94233:         $this->assertFalse($node->metadataKeyExists('1'));
                   94234:     }
                   94235: 
                   94236:     function test_directed_degree() {
                   94237:         $this->_graph = new Structures_Graph(true);
                   94238:         $node = array();
                   94239:         $node[] = new Structures_Graph_Node();
                   94240:         $node[] = new Structures_Graph_Node();
                   94241:         $node[] = new Structures_Graph_Node();
                   94242:         $this->_graph->addNode($node[0]);
                   94243:         $this->_graph->addNode($node[1]);
                   94244:         $this->_graph->addNode($node[2]);
                   94245:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
                   94246:         $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
                   94247:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
                   94248:         $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
                   94249:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
                   94250:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
                   94251:         $node[0]->connectTo($node[1]);
                   94252:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
                   94253:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
                   94254:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
                   94255:         $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
                   94256:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
                   94257:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
                   94258:         $node[0]->connectTo($node[2]);
                   94259:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
                   94260:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
                   94261:         $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
                   94262:         $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
                   94263:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
                   94264:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
                   94265:     }
                   94266: 
                   94267:     function test_undirected_degree() {
                   94268:         $this->_graph = new Structures_Graph(false);
                   94269:         $node = array();
                   94270:         $node[] = new Structures_Graph_Node();
                   94271:         $node[] = new Structures_Graph_Node();
                   94272:         $node[] = new Structures_Graph_Node();
                   94273:         $this->_graph->addNode($node[0]);
                   94274:         $this->_graph->addNode($node[1]);
                   94275:         $this->_graph->addNode($node[2]);
                   94276:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
                   94277:         $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
                   94278:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
                   94279:         $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
                   94280:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
                   94281:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
                   94282:         $node[0]->connectTo($node[1]);
                   94283:         $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
                   94284:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
                   94285:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
                   94286:         $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
                   94287:         $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
                   94288:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
                   94289:         $node[0]->connectTo($node[2]);
                   94290:         $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
                   94291:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
                   94292:         $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
                   94293:         $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
                   94294:         $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
                   94295:         $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
                   94296:     }
                   94297: }
                   94298: ?>
                   94299: Structures_Graph-1.0.4/tests/AllTests.php0000644000076600000240000000641411461440275017715 0ustar  bbieberstaff<?php
                   94300: 
                   94301: /**
                   94302:  * Master Unit Test Suite file for Structures_Graph
                   94303:  * 
                   94304:  * This top-level test suite file organizes 
                   94305:  * all class test suite files, 
                   94306:  * so that the full suite can be run 
                   94307:  * by PhpUnit or via "pear run-tests -u". 
                   94308:  *
                   94309:  * PHP version 5
                   94310:  *
                   94311:  * @category   XML
                   94312:  * @package    XML_Util
                   94313:  * @subpackage UnitTesting
                   94314:  * @author     Chuck Burgess <ashnazg@php.net>
                   94315:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   94316:  * @version    CVS: $Id$
                   94317:  * @link       http://pear.php.net/package/XML_Util
                   94318:  * @since      1.2.0a1
                   94319:  */
                   94320: 
                   94321: 
                   94322: /**
                   94323:  * Check PHP version... PhpUnit v3+ requires at least PHP v5.1.4
                   94324:  */
                   94325: if (version_compare(PHP_VERSION, "5.1.4") < 0) {
                   94326:     // Cannnot run test suites
                   94327:     echo 'Cannot run test suite via PhpUnit... requires at least PHP v5.1.4.' . PHP_EOL;
                   94328:     echo 'Use "pear run-tests -p xml_util" to run the PHPT tests directly.' . PHP_EOL;
                   94329:     exit(1);
                   94330: }
                   94331: 
                   94332: 
                   94333: /**
                   94334:  * Derive the "main" method name
                   94335:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   94336:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   94337:  */
                   94338: if (!defined('PHPUnit_MAIN_METHOD')) {
                   94339:     define('PHPUnit_MAIN_METHOD', 'Structures_Graph_AllTests::main');
                   94340: }
                   94341: 
                   94342: 
                   94343: /*
                   94344:  * Files needed by PhpUnit
                   94345:  */
                   94346: require_once 'PHPUnit/Framework.php';
                   94347: require_once 'PHPUnit/TextUI/TestRunner.php';
                   94348: require_once 'PHPUnit/Extensions/PhptTestSuite.php';
                   94349: 
                   94350: /*
                   94351:  * You must add each additional class-level test suite file here
                   94352:  */
                   94353: require_once dirname(__FILE__).'/testCase/BasicGraph.php';
                   94354: 
                   94355: 
                   94356: /**
                   94357:  * Master Unit Test Suite class for Structures_Graph
                   94358:  * 
                   94359:  * This top-level test suite class organizes 
                   94360:  * all class test suite files, 
                   94361:  * so that the full suite can be run 
                   94362:  * by PhpUnit or via "pear run-tests -up Structures_Graph". 
                   94363:  *
                   94364:  * @category   Structures
                   94365:  * @package    Structures_Graph
                   94366:  * @subpackage UnitTesting
                   94367:  * @author     Chuck Burgess <ashnazg@php.net>
                   94368:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   94369:  * @version    Release: @package_version@
                   94370:  * @link       http://pear.php.net/package/XML_Util
                   94371:  * @since      1.2.0a1
                   94372:  */
                   94373: class Structures_Graph_AllTests
                   94374: {
                   94375: 
                   94376:     /**
                   94377:      * Launches the TextUI test runner
                   94378:      *
                   94379:      * @return void
                   94380:      * @uses PHPUnit_TextUI_TestRunner
                   94381:      */
                   94382:     public static function main()
                   94383:     {
                   94384:         PHPUnit_TextUI_TestRunner::run(self::suite());
                   94385:     }
                   94386: 
                   94387: 
                   94388:     /**
                   94389:      * Adds all class test suites into the master suite
                   94390:      *
                   94391:      * @return PHPUnit_Framework_TestSuite a master test suite
                   94392:      *                                     containing all class test suites
                   94393:      * @uses PHPUnit_Framework_TestSuite
                   94394:      */ 
                   94395:     public static function suite()
                   94396:     {
                   94397:         $suite = new PHPUnit_Framework_TestSuite(
                   94398:             'Structures_Graph Full Suite of Unit Tests');
                   94399: 
                   94400:         /*
                   94401:          * You must add each additional class-level test suite name here
                   94402:          */
                   94403:         $suite->addTestSuite('BasicGraph');
                   94404: 
                   94405:         return $suite;
                   94406:     }
                   94407: }
                   94408: 
                   94409: /**
                   94410:  * Call the main method if this file is executed directly
                   94411:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   94412:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   94413:  */
                   94414: if (PHPUnit_MAIN_METHOD == 'Structures_Graph_AllTests::main') {
                   94415:     Structures_Graph_AllTests::main();
                   94416: }
                   94417: 
                   94418: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   94419: ?>
                   94420: Structures_Graph-1.0.4/LICENSE0000644000076600000240000006347611461440275015327 0ustar  bbieberstaff             GNU LESSER GENERAL PUBLIC LICENSE
                   94421:                       Version 2.1, February 1999
                   94422: 
                   94423:  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
                   94424:      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                   94425:  Everyone is permitted to copy and distribute verbatim copies
                   94426:  of this license document, but changing it is not allowed.
                   94427: 
                   94428: [This is the first released version of the Lesser GPL.  It also counts
                   94429:  as the successor of the GNU Library Public License, version 2, hence
                   94430:  the version number 2.1.]
                   94431: 
                   94432:                            Preamble
                   94433: 
                   94434:   The licenses for most software are designed to take away your
                   94435: freedom to share and change it.  By contrast, the GNU General Public
                   94436: Licenses are intended to guarantee your freedom to share and change
                   94437: free software--to make sure the software is free for all its users.
                   94438: 
                   94439:   This license, the Lesser General Public License, applies to some
                   94440: specially designated software packages--typically libraries--of the
                   94441: Free Software Foundation and other authors who decide to use it.  You
                   94442: can use it too, but we suggest you first think carefully about whether
                   94443: this license or the ordinary General Public License is the better
                   94444: strategy to use in any particular case, based on the explanations below.
                   94445: 
                   94446:   When we speak of free software, we are referring to freedom of use,
                   94447: not price.  Our General Public Licenses are designed to make sure that
                   94448: you have the freedom to distribute copies of free software (and charge
                   94449: for this service if you wish); that you receive source code or can get
                   94450: it if you want it; that you can change the software and use pieces of
                   94451: it in new free programs; and that you are informed that you can do
                   94452: these things.
                   94453: 
                   94454:   To protect your rights, we need to make restrictions that forbid
                   94455: distributors to deny you these rights or to ask you to surrender these
                   94456: rights.  These restrictions translate to certain responsibilities for
                   94457: you if you distribute copies of the library or if you modify it.
                   94458: 
                   94459:   For example, if you distribute copies of the library, whether gratis
                   94460: or for a fee, you must give the recipients all the rights that we gave
                   94461: you.  You must make sure that they, too, receive or can get the source
                   94462: code.  If you link other code with the library, you must provide
                   94463: complete object files to the recipients, so that they can relink them
                   94464: with the library after making changes to the library and recompiling
                   94465: it.  And you must show them these terms so they know their rights.
                   94466: 
                   94467:   We protect your rights with a two-step method: (1) we copyright the
                   94468: library, and (2) we offer you this license, which gives you legal
                   94469: permission to copy, distribute and/or modify the library.
                   94470: 
                   94471:   To protect each distributor, we want to make it very clear that
                   94472: there is no warranty for the free library.  Also, if the library is
                   94473: modified by someone else and passed on, the recipients should know
                   94474: that what they have is not the original version, so that the original
                   94475: author's reputation will not be affected by problems that might be
                   94476: introduced by others.
                   94477: 
                   94478:   Finally, software patents pose a constant threat to the existence of
                   94479: any free program.  We wish to make sure that a company cannot
                   94480: effectively restrict the users of a free program by obtaining a
                   94481: restrictive license from a patent holder.  Therefore, we insist that
                   94482: any patent license obtained for a version of the library must be
                   94483: consistent with the full freedom of use specified in this license.
                   94484: 
                   94485:   Most GNU software, including some libraries, is covered by the
                   94486: ordinary GNU General Public License.  This license, the GNU Lesser
                   94487: General Public License, applies to certain designated libraries, and
                   94488: is quite different from the ordinary General Public License.  We use
                   94489: this license for certain libraries in order to permit linking those
                   94490: libraries into non-free programs.
                   94491: 
                   94492:   When a program is linked with a library, whether statically or using
                   94493: a shared library, the combination of the two is legally speaking a
                   94494: combined work, a derivative of the original library.  The ordinary
                   94495: General Public License therefore permits such linking only if the
                   94496: entire combination fits its criteria of freedom.  The Lesser General
                   94497: Public License permits more lax criteria for linking other code with
                   94498: the library.
                   94499: 
                   94500:   We call this license the "Lesser" General Public License because it
                   94501: does Less to protect the user's freedom than the ordinary General
                   94502: Public License.  It also provides other free software developers Less
                   94503: of an advantage over competing non-free programs.  These disadvantages
                   94504: are the reason we use the ordinary General Public License for many
                   94505: libraries.  However, the Lesser license provides advantages in certain
                   94506: special circumstances.
                   94507: 
                   94508:   For example, on rare occasions, there may be a special need to
                   94509: encourage the widest possible use of a certain library, so that it becomes
                   94510: a de-facto standard.  To achieve this, non-free programs must be
                   94511: allowed to use the library.  A more frequent case is that a free
                   94512: library does the same job as widely used non-free libraries.  In this
                   94513: case, there is little to gain by limiting the free library to free
                   94514: software only, so we use the Lesser General Public License.
                   94515: 
                   94516:   In other cases, permission to use a particular library in non-free
                   94517: programs enables a greater number of people to use a large body of
                   94518: free software.  For example, permission to use the GNU C Library in
                   94519: non-free programs enables many more people to use the whole GNU
                   94520: operating system, as well as its variant, the GNU/Linux operating
                   94521: system.
                   94522: 
                   94523:   Although the Lesser General Public License is Less protective of the
                   94524: users' freedom, it does ensure that the user of a program that is
                   94525: linked with the Library has the freedom and the wherewithal to run
                   94526: that program using a modified version of the Library.
                   94527: 
                   94528:   The precise terms and conditions for copying, distribution and
                   94529: modification follow.  Pay close attention to the difference between a
                   94530: "work based on the library" and a "work that uses the library".  The
                   94531: former contains code derived from the library, whereas the latter must
                   94532: be combined with the library in order to run.
                   94533: 
                   94534:                  GNU LESSER GENERAL PUBLIC LICENSE
                   94535:    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
                   94536: 
                   94537:   0. This License Agreement applies to any software library or other
                   94538: program which contains a notice placed by the copyright holder or
                   94539: other authorized party saying it may be distributed under the terms of
                   94540: this Lesser General Public License (also called "this License").
                   94541: Each licensee is addressed as "you".
                   94542: 
                   94543:   A "library" means a collection of software functions and/or data
                   94544: prepared so as to be conveniently linked with application programs
                   94545: (which use some of those functions and data) to form executables.
                   94546: 
                   94547:   The "Library", below, refers to any such software library or work
                   94548: which has been distributed under these terms.  A "work based on the
                   94549: Library" means either the Library or any derivative work under
                   94550: copyright law: that is to say, a work containing the Library or a
                   94551: portion of it, either verbatim or with modifications and/or translated
                   94552: straightforwardly into another language.  (Hereinafter, translation is
                   94553: included without limitation in the term "modification".)
                   94554: 
                   94555:   "Source code" for a work means the preferred form of the work for
                   94556: making modifications to it.  For a library, complete source code means
                   94557: all the source code for all modules it contains, plus any associated
                   94558: interface definition files, plus the scripts used to control compilation
                   94559: and installation of the library.
                   94560: 
                   94561:   Activities other than copying, distribution and modification are not
                   94562: covered by this License; they are outside its scope.  The act of
                   94563: running a program using the Library is not restricted, and output from
                   94564: such a program is covered only if its contents constitute a work based
                   94565: on the Library (independent of the use of the Library in a tool for
                   94566: writing it).  Whether that is true depends on what the Library does
                   94567: and what the program that uses the Library does.
                   94568:   
                   94569:   1. You may copy and distribute verbatim copies of the Library's
                   94570: complete source code as you receive it, in any medium, provided that
                   94571: you conspicuously and appropriately publish on each copy an
                   94572: appropriate copyright notice and disclaimer of warranty; keep intact
                   94573: all the notices that refer to this License and to the absence of any
                   94574: warranty; and distribute a copy of this License along with the
                   94575: Library.
                   94576: 
                   94577:   You may charge a fee for the physical act of transferring a copy,
                   94578: and you may at your option offer warranty protection in exchange for a
                   94579: fee.
                   94580: 
                   94581:   2. You may modify your copy or copies of the Library or any portion
                   94582: of it, thus forming a work based on the Library, and copy and
                   94583: distribute such modifications or work under the terms of Section 1
                   94584: above, provided that you also meet all of these conditions:
                   94585: 
                   94586:     a) The modified work must itself be a software library.
                   94587: 
                   94588:     b) You must cause the files modified to carry prominent notices
                   94589:     stating that you changed the files and the date of any change.
                   94590: 
                   94591:     c) You must cause the whole of the work to be licensed at no
                   94592:     charge to all third parties under the terms of this License.
                   94593: 
                   94594:     d) If a facility in the modified Library refers to a function or a
                   94595:     table of data to be supplied by an application program that uses
                   94596:     the facility, other than as an argument passed when the facility
                   94597:     is invoked, then you must make a good faith effort to ensure that,
                   94598:     in the event an application does not supply such function or
                   94599:     table, the facility still operates, and performs whatever part of
                   94600:     its purpose remains meaningful.
                   94601: 
                   94602:     (For example, a function in a library to compute square roots has
                   94603:     a purpose that is entirely well-defined independent of the
                   94604:     application.  Therefore, Subsection 2d requires that any
                   94605:     application-supplied function or table used by this function must
                   94606:     be optional: if the application does not supply it, the square
                   94607:     root function must still compute square roots.)
                   94608: 
                   94609: These requirements apply to the modified work as a whole.  If
                   94610: identifiable sections of that work are not derived from the Library,
                   94611: and can be reasonably considered independent and separate works in
                   94612: themselves, then this License, and its terms, do not apply to those
                   94613: sections when you distribute them as separate works.  But when you
                   94614: distribute the same sections as part of a whole which is a work based
                   94615: on the Library, the distribution of the whole must be on the terms of
                   94616: this License, whose permissions for other licensees extend to the
                   94617: entire whole, and thus to each and every part regardless of who wrote
                   94618: it.
                   94619: 
                   94620: Thus, it is not the intent of this section to claim rights or contest
                   94621: your rights to work written entirely by you; rather, the intent is to
                   94622: exercise the right to control the distribution of derivative or
                   94623: collective works based on the Library.
                   94624: 
                   94625: In addition, mere aggregation of another work not based on the Library
                   94626: with the Library (or with a work based on the Library) on a volume of
                   94627: a storage or distribution medium does not bring the other work under
                   94628: the scope of this License.
                   94629: 
                   94630:   3. You may opt to apply the terms of the ordinary GNU General Public
                   94631: License instead of this License to a given copy of the Library.  To do
                   94632: this, you must alter all the notices that refer to this License, so
                   94633: that they refer to the ordinary GNU General Public License, version 2,
                   94634: instead of to this License.  (If a newer version than version 2 of the
                   94635: ordinary GNU General Public License has appeared, then you can specify
                   94636: that version instead if you wish.)  Do not make any other change in
                   94637: these notices.
                   94638: 
                   94639:   Once this change is made in a given copy, it is irreversible for
                   94640: that copy, so the ordinary GNU General Public License applies to all
                   94641: subsequent copies and derivative works made from that copy.
                   94642: 
                   94643:   This option is useful when you wish to copy part of the code of
                   94644: the Library into a program that is not a library.
                   94645: 
                   94646:   4. You may copy and distribute the Library (or a portion or
                   94647: derivative of it, under Section 2) in object code or executable form
                   94648: under the terms of Sections 1 and 2 above provided that you accompany
                   94649: it with the complete corresponding machine-readable source code, which
                   94650: must be distributed under the terms of Sections 1 and 2 above on a
                   94651: medium customarily used for software interchange.
                   94652: 
                   94653:   If distribution of object code is made by offering access to copy
                   94654: from a designated place, then offering equivalent access to copy the
                   94655: source code from the same place satisfies the requirement to
                   94656: distribute the source code, even though third parties are not
                   94657: compelled to copy the source along with the object code.
                   94658: 
                   94659:   5. A program that contains no derivative of any portion of the
                   94660: Library, but is designed to work with the Library by being compiled or
                   94661: linked with it, is called a "work that uses the Library".  Such a
                   94662: work, in isolation, is not a derivative work of the Library, and
                   94663: therefore falls outside the scope of this License.
                   94664: 
                   94665:   However, linking a "work that uses the Library" with the Library
                   94666: creates an executable that is a derivative of the Library (because it
                   94667: contains portions of the Library), rather than a "work that uses the
                   94668: library".  The executable is therefore covered by this License.
                   94669: Section 6 states terms for distribution of such executables.
                   94670: 
                   94671:   When a "work that uses the Library" uses material from a header file
                   94672: that is part of the Library, the object code for the work may be a
                   94673: derivative work of the Library even though the source code is not.
                   94674: Whether this is true is especially significant if the work can be
                   94675: linked without the Library, or if the work is itself a library.  The
                   94676: threshold for this to be true is not precisely defined by law.
                   94677: 
                   94678:   If such an object file uses only numerical parameters, data
                   94679: structure layouts and accessors, and small macros and small inline
                   94680: functions (ten lines or less in length), then the use of the object
                   94681: file is unrestricted, regardless of whether it is legally a derivative
                   94682: work.  (Executables containing this object code plus portions of the
                   94683: Library will still fall under Section 6.)
                   94684: 
                   94685:   Otherwise, if the work is a derivative of the Library, you may
                   94686: distribute the object code for the work under the terms of Section 6.
                   94687: Any executables containing that work also fall under Section 6,
                   94688: whether or not they are linked directly with the Library itself.
                   94689: 
                   94690:   6. As an exception to the Sections above, you may also combine or
                   94691: link a "work that uses the Library" with the Library to produce a
                   94692: work containing portions of the Library, and distribute that work
                   94693: under terms of your choice, provided that the terms permit
                   94694: modification of the work for the customer's own use and reverse
                   94695: engineering for debugging such modifications.
                   94696: 
                   94697:   You must give prominent notice with each copy of the work that the
                   94698: Library is used in it and that the Library and its use are covered by
                   94699: this License.  You must supply a copy of this License.  If the work
                   94700: during execution displays copyright notices, you must include the
                   94701: copyright notice for the Library among them, as well as a reference
                   94702: directing the user to the copy of this License.  Also, you must do one
                   94703: of these things:
                   94704: 
                   94705:     a) Accompany the work with the complete corresponding
                   94706:     machine-readable source code for the Library including whatever
                   94707:     changes were used in the work (which must be distributed under
                   94708:     Sections 1 and 2 above); and, if the work is an executable linked
                   94709:     with the Library, with the complete machine-readable "work that
                   94710:     uses the Library", as object code and/or source code, so that the
                   94711:     user can modify the Library and then relink to produce a modified
                   94712:     executable containing the modified Library.  (It is understood
                   94713:     that the user who changes the contents of definitions files in the
                   94714:     Library will not necessarily be able to recompile the application
                   94715:     to use the modified definitions.)
                   94716: 
                   94717:     b) Use a suitable shared library mechanism for linking with the
                   94718:     Library.  A suitable mechanism is one that (1) uses at run time a
                   94719:     copy of the library already present on the user's computer system,
                   94720:     rather than copying library functions into the executable, and (2)
                   94721:     will operate properly with a modified version of the library, if
                   94722:     the user installs one, as long as the modified version is
                   94723:     interface-compatible with the version that the work was made with.
                   94724: 
                   94725:     c) Accompany the work with a written offer, valid for at
                   94726:     least three years, to give the same user the materials
                   94727:     specified in Subsection 6a, above, for a charge no more
                   94728:     than the cost of performing this distribution.
                   94729: 
                   94730:     d) If distribution of the work is made by offering access to copy
                   94731:     from a designated place, offer equivalent access to copy the above
                   94732:     specified materials from the same place.
                   94733: 
                   94734:     e) Verify that the user has already received a copy of these
                   94735:     materials or that you have already sent this user a copy.
                   94736: 
                   94737:   For an executable, the required form of the "work that uses the
                   94738: Library" must include any data and utility programs needed for
                   94739: reproducing the executable from it.  However, as a special exception,
                   94740: the materials to be distributed need not include anything that is
                   94741: normally distributed (in either source or binary form) with the major
                   94742: components (compiler, kernel, and so on) of the operating system on
                   94743: which the executable runs, unless that component itself accompanies
                   94744: the executable.
                   94745: 
                   94746:   It may happen that this requirement contradicts the license
                   94747: restrictions of other proprietary libraries that do not normally
                   94748: accompany the operating system.  Such a contradiction means you cannot
                   94749: use both them and the Library together in an executable that you
                   94750: distribute.
                   94751: 
                   94752:   7. You may place library facilities that are a work based on the
                   94753: Library side-by-side in a single library together with other library
                   94754: facilities not covered by this License, and distribute such a combined
                   94755: library, provided that the separate distribution of the work based on
                   94756: the Library and of the other library facilities is otherwise
                   94757: permitted, and provided that you do these two things:
                   94758: 
                   94759:     a) Accompany the combined library with a copy of the same work
                   94760:     based on the Library, uncombined with any other library
                   94761:     facilities.  This must be distributed under the terms of the
                   94762:     Sections above.
                   94763: 
                   94764:     b) Give prominent notice with the combined library of the fact
                   94765:     that part of it is a work based on the Library, and explaining
                   94766:     where to find the accompanying uncombined form of the same work.
                   94767: 
                   94768:   8. You may not copy, modify, sublicense, link with, or distribute
                   94769: the Library except as expressly provided under this License.  Any
                   94770: attempt otherwise to copy, modify, sublicense, link with, or
                   94771: distribute the Library is void, and will automatically terminate your
                   94772: rights under this License.  However, parties who have received copies,
                   94773: or rights, from you under this License will not have their licenses
                   94774: terminated so long as such parties remain in full compliance.
                   94775: 
                   94776:   9. You are not required to accept this License, since you have not
                   94777: signed it.  However, nothing else grants you permission to modify or
                   94778: distribute the Library or its derivative works.  These actions are
                   94779: prohibited by law if you do not accept this License.  Therefore, by
                   94780: modifying or distributing the Library (or any work based on the
                   94781: Library), you indicate your acceptance of this License to do so, and
                   94782: all its terms and conditions for copying, distributing or modifying
                   94783: the Library or works based on it.
                   94784: 
                   94785:   10. Each time you redistribute the Library (or any work based on the
                   94786: Library), the recipient automatically receives a license from the
                   94787: original licensor to copy, distribute, link with or modify the Library
                   94788: subject to these terms and conditions.  You may not impose any further
                   94789: restrictions on the recipients' exercise of the rights granted herein.
                   94790: You are not responsible for enforcing compliance by third parties with
                   94791: this License.
                   94792: 
                   94793:   11. If, as a consequence of a court judgment or allegation of patent
                   94794: infringement or for any other reason (not limited to patent issues),
                   94795: conditions are imposed on you (whether by court order, agreement or
                   94796: otherwise) that contradict the conditions of this License, they do not
                   94797: excuse you from the conditions of this License.  If you cannot
                   94798: distribute so as to satisfy simultaneously your obligations under this
                   94799: License and any other pertinent obligations, then as a consequence you
                   94800: may not distribute the Library at all.  For example, if a patent
                   94801: license would not permit royalty-free redistribution of the Library by
                   94802: all those who receive copies directly or indirectly through you, then
                   94803: the only way you could satisfy both it and this License would be to
                   94804: refrain entirely from distribution of the Library.
                   94805: 
                   94806: If any portion of this section is held invalid or unenforceable under any
                   94807: particular circumstance, the balance of the section is intended to apply,
                   94808: and the section as a whole is intended to apply in other circumstances.
                   94809: 
                   94810: It is not the purpose of this section to induce you to infringe any
                   94811: patents or other property right claims or to contest validity of any
                   94812: such claims; this section has the sole purpose of protecting the
                   94813: integrity of the free software distribution system which is
                   94814: implemented by public license practices.  Many people have made
                   94815: generous contributions to the wide range of software distributed
                   94816: through that system in reliance on consistent application of that
                   94817: system; it is up to the author/donor to decide if he or she is willing
                   94818: to distribute software through any other system and a licensee cannot
                   94819: impose that choice.
                   94820: 
                   94821: This section is intended to make thoroughly clear what is believed to
                   94822: be a consequence of the rest of this License.
                   94823: 
                   94824:   12. If the distribution and/or use of the Library is restricted in
                   94825: certain countries either by patents or by copyrighted interfaces, the
                   94826: original copyright holder who places the Library under this License may add
                   94827: an explicit geographical distribution limitation excluding those countries,
                   94828: so that distribution is permitted only in or among countries not thus
                   94829: excluded.  In such case, this License incorporates the limitation as if
                   94830: written in the body of this License.
                   94831: 
                   94832:   13. The Free Software Foundation may publish revised and/or new
                   94833: versions of the Lesser General Public License from time to time.
                   94834: Such new versions will be similar in spirit to the present version,
                   94835: but may differ in detail to address new problems or concerns.
                   94836: 
                   94837: Each version is given a distinguishing version number.  If the Library
                   94838: specifies a version number of this License which applies to it and
                   94839: "any later version", you have the option of following the terms and
                   94840: conditions either of that version or of any later version published by
                   94841: the Free Software Foundation.  If the Library does not specify a
                   94842: license version number, you may choose any version ever published by
                   94843: the Free Software Foundation.
                   94844: 
                   94845:   14. If you wish to incorporate parts of the Library into other free
                   94846: programs whose distribution conditions are incompatible with these,
                   94847: write to the author to ask for permission.  For software which is
                   94848: copyrighted by the Free Software Foundation, write to the Free
                   94849: Software Foundation; we sometimes make exceptions for this.  Our
                   94850: decision will be guided by the two goals of preserving the free status
                   94851: of all derivatives of our free software and of promoting the sharing
                   94852: and reuse of software generally.
                   94853: 
                   94854:                            NO WARRANTY
                   94855: 
                   94856:   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
                   94857: WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
                   94858: EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
                   94859: OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
                   94860: KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
                   94861: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   94862: PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
                   94863: LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
                   94864: THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
                   94865: 
                   94866:   16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
                   94867: WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
                   94868: AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
                   94869: FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
                   94870: CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
                   94871: LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
                   94872: RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
                   94873: FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
                   94874: SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
                   94875: DAMAGES.
                   94876: 
                   94877:                     END OF TERMS AND CONDITIONS
                   94878: 
                   94879:            How to Apply These Terms to Your New Libraries
                   94880: 
                   94881:   If you develop a new library, and you want it to be of the greatest
                   94882: possible use to the public, we recommend making it free software that
                   94883: everyone can redistribute and change.  You can do so by permitting
                   94884: redistribution under these terms (or, alternatively, under the terms of the
                   94885: ordinary General Public License).
                   94886: 
                   94887:   To apply these terms, attach the following notices to the library.  It is
                   94888: safest to attach them to the start of each source file to most effectively
                   94889: convey the exclusion of warranty; and each file should have at least the
                   94890: "copyright" line and a pointer to where the full notice is found.
                   94891: 
                   94892:     <one line to give the library's name and a brief idea of what it does.>
                   94893:     Copyright (C) <year>  <name of author>
                   94894: 
                   94895:     This library is free software; you can redistribute it and/or
                   94896:     modify it under the terms of the GNU Lesser General Public
                   94897:     License as published by the Free Software Foundation; either
                   94898:     version 2.1 of the License, or (at your option) any later version.
                   94899: 
                   94900:     This library is distributed in the hope that it will be useful,
                   94901:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                   94902:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                   94903:     Lesser General Public License for more details.
                   94904: 
                   94905:     You should have received a copy of the GNU Lesser General Public
                   94906:     License along with this library; if not, write to the Free Software
                   94907:     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                   94908: 
                   94909: Also add information on how to contact you by electronic and paper mail.
                   94910: 
                   94911: You should also get your employer (if you work as a programmer) or your
                   94912: school, if any, to sign a "copyright disclaimer" for the library, if
                   94913: necessary.  Here is a sample; alter the names:
                   94914: 
                   94915:   Yoyodyne, Inc., hereby disclaims all copyright interest in the
                   94916:   library `Frob' (a library for tweaking knobs) written by James Random Hacker.
                   94917: 
                   94918:   <signature of Ty Coon>, 1 April 1990
                   94919:   Ty Coon, President of Vice
                   94920: 
                   94921: That's all there is to it!
                   94922: 
                   94923: 
                   94924: <?php
                   94925: /**
                   94926:  * File/Directory manipulation
                   94927:  *
                   94928:  * PHP versions 4 and 5
                   94929:  *
                   94930:  * @category   pear
                   94931:  * @package    System
                   94932:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   94933:  * @copyright  1997-2009 The Authors
                   94934:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   94935:  * @version    CVS: $Id: System.php 312944 2011-07-05 18:31:18Z dufuz $
                   94936:  * @link       http://pear.php.net/package/PEAR
                   94937:  * @since      File available since Release 0.1
                   94938:  */
                   94939: 
                   94940: /**
                   94941:  * base class
                   94942:  */
                   94943: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   94944: require_once 'phar://install-pear-nozlib.phar/' . 'Console/Getopt.php';
                   94945: 
                   94946: $GLOBALS['_System_temp_files'] = array();
                   94947: 
                   94948: /**
                   94949: * System offers cross plattform compatible system functions
                   94950: *
                   94951: * Static functions for different operations. Should work under
                   94952: * Unix and Windows. The names and usage has been taken from its respectively
                   94953: * GNU commands. The functions will return (bool) false on error and will
                   94954: * trigger the error with the PHP trigger_error() function (you can silence
                   94955: * the error by prefixing a '@' sign after the function call, but this
                   94956: * is not recommended practice.  Instead use an error handler with
                   94957: * {@link set_error_handler()}).
                   94958: *
                   94959: * Documentation on this class you can find in:
                   94960: * http://pear.php.net/manual/
                   94961: *
                   94962: * Example usage:
                   94963: * if (!@System::rm('-r file1 dir1')) {
                   94964: *    print "could not delete file1 or dir1";
                   94965: * }
                   94966: *
                   94967: * In case you need to to pass file names with spaces,
                   94968: * pass the params as an array:
                   94969: *
                   94970: * System::rm(array('-r', $file1, $dir1));
                   94971: *
                   94972: * @category   pear
                   94973: * @package    System
                   94974: * @author     Tomas V.V. Cox <cox@idecnet.com>
                   94975: * @copyright  1997-2006 The PHP Group
                   94976: * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   94977: * @version    Release: 1.10.0beta1
                   94978: * @link       http://pear.php.net/package/PEAR
                   94979: * @since      Class available since Release 0.1
                   94980: * @static
                   94981: */
                   94982: class System
                   94983: {
                   94984:     /**
                   94985:      * returns the commandline arguments of a function
                   94986:      *
                   94987:      * @param    string  $argv           the commandline
                   94988:      * @param    string  $short_options  the allowed option short-tags
                   94989:      * @param    string  $long_options   the allowed option long-tags
                   94990:      * @return   array   the given options and there values
                   94991:      * @static
                   94992:      * @access private
                   94993:      */
                   94994:     function _parseArgs($argv, $short_options, $long_options = null)
                   94995:     {
                   94996:         if (!is_array($argv) && $argv !== null) {
                   94997:             /*
                   94998:             // Quote all items that are a short option
                   94999:             $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
                   95000:             $offset = 0;
                   95001:             foreach ($av as $a) {
                   95002:                 $b = trim($a[0]);
                   95003:                 if ($b{0} == '"' || $b{0} == "'") {
                   95004:                     continue;
                   95005:                 }
                   95006: 
                   95007:                 $escape = escapeshellarg($b);
                   95008:                 $pos = $a[1] + $offset;
                   95009:                 $argv = substr_replace($argv, $escape, $pos, strlen($b));
                   95010:                 $offset += 2;
                   95011:             }
                   95012:             */
                   95013: 
                   95014:             // Find all items, quoted or otherwise
                   95015:             preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
                   95016:             $argv = $av[1];
                   95017:             foreach ($av[2] as $k => $a) {
                   95018:                 if (empty($a)) {
                   95019:                     continue;
                   95020:                 }
                   95021:                 $argv[$k] = trim($a) ;
                   95022:             }
                   95023:         }
                   95024: 
                   95025:         return Console_Getopt::getopt2($argv, $short_options, $long_options);
                   95026:     }
                   95027: 
                   95028:     /**
                   95029:      * Output errors with PHP trigger_error(). You can silence the errors
                   95030:      * with prefixing a "@" sign to the function call: @System::mkdir(..);
                   95031:      *
                   95032:      * @param mixed $error a PEAR error or a string with the error message
                   95033:      * @return bool false
                   95034:      * @static
                   95035:      * @access private
                   95036:      */
                   95037:     function raiseError($error)
                   95038:     {
                   95039:         if (PEAR::isError($error)) {
                   95040:             $error = $error->getMessage();
                   95041:         }
                   95042:         trigger_error($error, E_USER_WARNING);
                   95043:         return false;
                   95044:     }
                   95045: 
                   95046:     /**
                   95047:      * Creates a nested array representing the structure of a directory
                   95048:      *
                   95049:      * System::_dirToStruct('dir1', 0) =>
                   95050:      *   Array
                   95051:      *    (
                   95052:      *    [dirs] => Array
                   95053:      *        (
                   95054:      *            [0] => dir1
                   95055:      *        )
                   95056:      *
                   95057:      *    [files] => Array
                   95058:      *        (
                   95059:      *            [0] => dir1/file2
                   95060:      *            [1] => dir1/file3
                   95061:      *        )
                   95062:      *    )
                   95063:      * @param    string  $sPath      Name of the directory
                   95064:      * @param    integer $maxinst    max. deep of the lookup
                   95065:      * @param    integer $aktinst    starting deep of the lookup
                   95066:      * @param    bool    $silent     if true, do not emit errors.
                   95067:      * @return   array   the structure of the dir
                   95068:      * @static
                   95069:      * @access   private
                   95070:      */
                   95071:     function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
                   95072:     {
                   95073:         $struct = array('dirs' => array(), 'files' => array());
                   95074:         if (($dir = @opendir($sPath)) === false) {
                   95075:             if (!$silent) {
                   95076:                 System::raiseError("Could not open dir $sPath");
                   95077:             }
                   95078:             return $struct; // XXX could not open error
                   95079:         }
                   95080: 
                   95081:         $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
                   95082:         $list = array();
                   95083:         while (false !== ($file = readdir($dir))) {
                   95084:             if ($file != '.' && $file != '..') {
                   95085:                 $list[] = $file;
                   95086:             }
                   95087:         }
                   95088: 
                   95089:         closedir($dir);
                   95090:         natsort($list);
                   95091:         if ($aktinst < $maxinst || $maxinst == 0) {
                   95092:             foreach ($list as $val) {
                   95093:                 $path = $sPath . DIRECTORY_SEPARATOR . $val;
                   95094:                 if (is_dir($path) && !is_link($path)) {
                   95095:                     $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
                   95096:                     $struct = array_merge_recursive($struct, $tmp);
                   95097:                 } else {
                   95098:                     $struct['files'][] = $path;
                   95099:                 }
                   95100:             }
                   95101:         }
                   95102: 
                   95103:         return $struct;
                   95104:     }
                   95105: 
                   95106:     /**
                   95107:      * Creates a nested array representing the structure of a directory and files
                   95108:      *
                   95109:      * @param    array $files Array listing files and dirs
                   95110:      * @return   array
                   95111:      * @static
                   95112:      * @see System::_dirToStruct()
                   95113:      */
                   95114:     function _multipleToStruct($files)
                   95115:     {
                   95116:         $struct = array('dirs' => array(), 'files' => array());
                   95117:         settype($files, 'array');
                   95118:         foreach ($files as $file) {
                   95119:             if (is_dir($file) && !is_link($file)) {
                   95120:                 $tmp    = System::_dirToStruct($file, 0);
                   95121:                 $struct = array_merge_recursive($tmp, $struct);
                   95122:             } else {
                   95123:                 if (!in_array($file, $struct['files'])) {
                   95124:                     $struct['files'][] = $file;
                   95125:                 }
                   95126:             }
                   95127:         }
                   95128:         return $struct;
                   95129:     }
                   95130: 
                   95131:     /**
                   95132:      * The rm command for removing files.
                   95133:      * Supports multiple files and dirs and also recursive deletes
                   95134:      *
                   95135:      * @param    string  $args   the arguments for rm
                   95136:      * @return   mixed   PEAR_Error or true for success
                   95137:      * @static
                   95138:      * @access   public
                   95139:      */
                   95140:     function rm($args)
                   95141:     {
                   95142:         $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
                   95143:         if (PEAR::isError($opts)) {
                   95144:             return System::raiseError($opts);
                   95145:         }
                   95146:         foreach ($opts[0] as $opt) {
                   95147:             if ($opt[0] == 'r') {
                   95148:                 $do_recursive = true;
                   95149:             }
                   95150:         }
                   95151:         $ret = true;
                   95152:         if (isset($do_recursive)) {
                   95153:             $struct = System::_multipleToStruct($opts[1]);
                   95154:             foreach ($struct['files'] as $file) {
                   95155:                 if (!@unlink($file)) {
                   95156:                     $ret = false;
                   95157:                 }
                   95158:             }
                   95159: 
                   95160:             rsort($struct['dirs']);
                   95161:             foreach ($struct['dirs'] as $dir) {
                   95162:                 if (!@rmdir($dir)) {
                   95163:                     $ret = false;
                   95164:                 }
                   95165:             }
                   95166:         } else {
                   95167:             foreach ($opts[1] as $file) {
                   95168:                 $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
                   95169:                 if (!@$delete($file)) {
                   95170:                     $ret = false;
                   95171:                 }
                   95172:             }
                   95173:         }
                   95174:         return $ret;
                   95175:     }
                   95176: 
                   95177:     /**
                   95178:      * Make directories.
                   95179:      *
                   95180:      * The -p option will create parent directories
                   95181:      * @param    string  $args    the name of the director(y|ies) to create
                   95182:      * @return   bool    True for success
                   95183:      * @static
                   95184:      * @access   public
                   95185:      */
                   95186:     function mkDir($args)
                   95187:     {
                   95188:         $opts = System::_parseArgs($args, 'pm:');
                   95189:         if (PEAR::isError($opts)) {
                   95190:             return System::raiseError($opts);
                   95191:         }
                   95192: 
                   95193:         $mode = 0777; // default mode
                   95194:         foreach ($opts[0] as $opt) {
                   95195:             if ($opt[0] == 'p') {
                   95196:                 $create_parents = true;
                   95197:             } elseif ($opt[0] == 'm') {
                   95198:                 // if the mode is clearly an octal number (starts with 0)
                   95199:                 // convert it to decimal
                   95200:                 if (strlen($opt[1]) && $opt[1]{0} == '0') {
                   95201:                     $opt[1] = octdec($opt[1]);
                   95202:                 } else {
                   95203:                     // convert to int
                   95204:                     $opt[1] += 0;
                   95205:                 }
                   95206:                 $mode = $opt[1];
                   95207:             }
                   95208:         }
                   95209: 
                   95210:         $ret = true;
                   95211:         if (isset($create_parents)) {
                   95212:             foreach ($opts[1] as $dir) {
                   95213:                 $dirstack = array();
                   95214:                 while ((!file_exists($dir) || !is_dir($dir)) &&
                   95215:                         $dir != DIRECTORY_SEPARATOR) {
                   95216:                     array_unshift($dirstack, $dir);
                   95217:                     $dir = dirname($dir);
                   95218:                 }
                   95219: 
                   95220:                 while ($newdir = array_shift($dirstack)) {
                   95221:                     if (!is_writeable(dirname($newdir))) {
                   95222:                         $ret = false;
                   95223:                         break;
                   95224:                     }
                   95225: 
                   95226:                     if (!mkdir($newdir, $mode)) {
                   95227:                         $ret = false;
                   95228:                     }
                   95229:                 }
                   95230:             }
                   95231:         } else {
                   95232:             foreach($opts[1] as $dir) {
                   95233:                 if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
                   95234:                     $ret = false;
                   95235:                 }
                   95236:             }
                   95237:         }
                   95238: 
                   95239:         return $ret;
                   95240:     }
                   95241: 
                   95242:     /**
                   95243:      * Concatenate files
                   95244:      *
                   95245:      * Usage:
                   95246:      * 1) $var = System::cat('sample.txt test.txt');
                   95247:      * 2) System::cat('sample.txt test.txt > final.txt');
                   95248:      * 3) System::cat('sample.txt test.txt >> final.txt');
                   95249:      *
                   95250:      * Note: as the class use fopen, urls should work also (test that)
                   95251:      *
                   95252:      * @param    string  $args   the arguments
                   95253:      * @return   boolean true on success
                   95254:      * @static
                   95255:      * @access   public
                   95256:      */
                   95257:     function &cat($args)
                   95258:     {
                   95259:         $ret = null;
                   95260:         $files = array();
                   95261:         if (!is_array($args)) {
                   95262:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   95263:         }
                   95264: 
                   95265:         $count_args = count($args);
                   95266:         for ($i = 0; $i < $count_args; $i++) {
                   95267:             if ($args[$i] == '>') {
                   95268:                 $mode = 'wb';
                   95269:                 $outputfile = $args[$i+1];
                   95270:                 break;
                   95271:             } elseif ($args[$i] == '>>') {
                   95272:                 $mode = 'ab+';
                   95273:                 $outputfile = $args[$i+1];
                   95274:                 break;
                   95275:             } else {
                   95276:                 $files[] = $args[$i];
                   95277:             }
                   95278:         }
                   95279:         $outputfd = false;
                   95280:         if (isset($mode)) {
                   95281:             if (!$outputfd = fopen($outputfile, $mode)) {
                   95282:                 $err = System::raiseError("Could not open $outputfile");
                   95283:                 return $err;
                   95284:             }
                   95285:             $ret = true;
                   95286:         }
                   95287:         foreach ($files as $file) {
                   95288:             if (!$fd = fopen($file, 'r')) {
                   95289:                 System::raiseError("Could not open $file");
                   95290:                 continue;
                   95291:             }
                   95292:             while ($cont = fread($fd, 2048)) {
                   95293:                 if (is_resource($outputfd)) {
                   95294:                     fwrite($outputfd, $cont);
                   95295:                 } else {
                   95296:                     $ret .= $cont;
                   95297:                 }
                   95298:             }
                   95299:             fclose($fd);
                   95300:         }
                   95301:         if (is_resource($outputfd)) {
                   95302:             fclose($outputfd);
                   95303:         }
                   95304:         return $ret;
                   95305:     }
                   95306: 
                   95307:     /**
                   95308:      * Creates temporary files or directories. This function will remove
                   95309:      * the created files when the scripts finish its execution.
                   95310:      *
                   95311:      * Usage:
                   95312:      *   1) $tempfile = System::mktemp("prefix");
                   95313:      *   2) $tempdir  = System::mktemp("-d prefix");
                   95314:      *   3) $tempfile = System::mktemp();
                   95315:      *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
                   95316:      *
                   95317:      * prefix -> The string that will be prepended to the temp name
                   95318:      *           (defaults to "tmp").
                   95319:      * -d     -> A temporary dir will be created instead of a file.
                   95320:      * -t     -> The target dir where the temporary (file|dir) will be created. If
                   95321:      *           this param is missing by default the env vars TMP on Windows or
                   95322:      *           TMPDIR in Unix will be used. If these vars are also missing
                   95323:      *           c:\windows\temp or /tmp will be used.
                   95324:      *
                   95325:      * @param   string  $args  The arguments
                   95326:      * @return  mixed   the full path of the created (file|dir) or false
                   95327:      * @see System::tmpdir()
                   95328:      * @static
                   95329:      * @access  public
                   95330:      */
                   95331:     function mktemp($args = null)
                   95332:     {
                   95333:         static $first_time = true;
                   95334:         $opts = System::_parseArgs($args, 't:d');
                   95335:         if (PEAR::isError($opts)) {
                   95336:             return System::raiseError($opts);
                   95337:         }
                   95338: 
                   95339:         foreach ($opts[0] as $opt) {
                   95340:             if ($opt[0] == 'd') {
                   95341:                 $tmp_is_dir = true;
                   95342:             } elseif ($opt[0] == 't') {
                   95343:                 $tmpdir = $opt[1];
                   95344:             }
                   95345:         }
                   95346: 
                   95347:         $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
                   95348:         if (!isset($tmpdir)) {
                   95349:             $tmpdir = System::tmpdir();
                   95350:         }
                   95351: 
                   95352:         if (!System::mkDir(array('-p', $tmpdir))) {
                   95353:             return false;
                   95354:         }
                   95355: 
                   95356:         $tmp = tempnam($tmpdir, $prefix);
                   95357:         if (isset($tmp_is_dir)) {
                   95358:             unlink($tmp); // be careful possible race condition here
                   95359:             if (!mkdir($tmp, 0700)) {
                   95360:                 return System::raiseError("Unable to create temporary directory $tmpdir");
                   95361:             }
                   95362:         }
                   95363: 
                   95364:         $GLOBALS['_System_temp_files'][] = $tmp;
                   95365:         if (isset($tmp_is_dir)) {
                   95366:             //$GLOBALS['_System_temp_files'][] = dirname($tmp);
                   95367:         }
                   95368: 
                   95369:         if ($first_time) {
                   95370:             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
                   95371:             $first_time = false;
                   95372:         }
                   95373: 
                   95374:         return $tmp;
                   95375:     }
                   95376: 
                   95377:     /**
                   95378:      * Remove temporary files created my mkTemp. This function is executed
                   95379:      * at script shutdown time
                   95380:      *
                   95381:      * @static
                   95382:      * @access private
                   95383:      */
                   95384:     function _removeTmpFiles()
                   95385:     {
                   95386:         if (count($GLOBALS['_System_temp_files'])) {
                   95387:             $delete = $GLOBALS['_System_temp_files'];
                   95388:             array_unshift($delete, '-r');
                   95389:             System::rm($delete);
                   95390:             $GLOBALS['_System_temp_files'] = array();
                   95391:         }
                   95392:     }
                   95393: 
                   95394:     /**
                   95395:      * Get the path of the temporal directory set in the system
                   95396:      * by looking in its environments variables.
                   95397:      * Note: php.ini-recommended removes the "E" from the variables_order setting,
                   95398:      * making unavaible the $_ENV array, that s why we do tests with _ENV
                   95399:      *
                   95400:      * @static
                   95401:      * @return string The temporary directory on the system
                   95402:      */
                   95403:     function tmpdir()
                   95404:     {
                   95405:         if (OS_WINDOWS) {
                   95406:             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                   95407:                 return $var;
                   95408:             }
                   95409:             if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                   95410:                 return $var;
                   95411:             }
                   95412:             if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
                   95413:                 return $var;
                   95414:             }
                   95415:             if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                   95416:                 return $var;
                   95417:             }
                   95418:             return getenv('SystemRoot') . '\temp';
                   95419:         }
                   95420:         if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
                   95421:             return $var;
                   95422:         }
                   95423:         return realpath('/tmp');
                   95424:     }
                   95425: 
                   95426:     /**
                   95427:      * The "which" command (show the full path of a command)
                   95428:      *
                   95429:      * @param string $program The command to search for
                   95430:      * @param mixed  $fallback Value to return if $program is not found
                   95431:      *
                   95432:      * @return mixed A string with the full path or false if not found
                   95433:      * @static
                   95434:      * @author Stig Bakken <ssb@php.net>
                   95435:      */
                   95436:     function which($program, $fallback = false)
                   95437:     {
                   95438:         // enforce API
                   95439:         if (!is_string($program) || '' == $program) {
                   95440:             return $fallback;
                   95441:         }
                   95442: 
                   95443:         // full path given
                   95444:         if (basename($program) != $program) {
                   95445:             $path_elements[] = dirname($program);
                   95446:             $program = basename($program);
                   95447:         } else {
                   95448:             // Honor safe mode
                   95449:             if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
                   95450:                 $path = getenv('PATH');
                   95451:                 if (!$path) {
                   95452:                     $path = getenv('Path'); // some OSes are just stupid enough to do this
                   95453:                 }
                   95454:             }
                   95455:             $path_elements = explode(PATH_SEPARATOR, $path);
                   95456:         }
                   95457: 
                   95458:         if (OS_WINDOWS) {
                   95459:             $exe_suffixes = getenv('PATHEXT')
                   95460:                                 ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
                   95461:                                 : array('.exe','.bat','.cmd','.com');
                   95462:             // allow passing a command.exe param
                   95463:             if (strpos($program, '.') !== false) {
                   95464:                 array_unshift($exe_suffixes, '');
                   95465:             }
                   95466:             // is_executable() is not available on windows for PHP4
                   95467:             $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
                   95468:         } else {
                   95469:             $exe_suffixes = array('');
                   95470:             $pear_is_executable = 'is_executable';
                   95471:         }
                   95472: 
                   95473:         foreach ($exe_suffixes as $suff) {
                   95474:             foreach ($path_elements as $dir) {
                   95475:                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
                   95476:                 if (@$pear_is_executable($file)) {
                   95477:                     return $file;
                   95478:                 }
                   95479:             }
                   95480:         }
                   95481:         return $fallback;
                   95482:     }
                   95483: 
                   95484:     /**
                   95485:      * The "find" command
                   95486:      *
                   95487:      * Usage:
                   95488:      *
                   95489:      * System::find($dir);
                   95490:      * System::find("$dir -type d");
                   95491:      * System::find("$dir -type f");
                   95492:      * System::find("$dir -name *.php");
                   95493:      * System::find("$dir -name *.php -name *.htm*");
                   95494:      * System::find("$dir -maxdepth 1");
                   95495:      *
                   95496:      * Params implmented:
                   95497:      * $dir            -> Start the search at this directory
                   95498:      * -type d         -> return only directories
                   95499:      * -type f         -> return only files
                   95500:      * -maxdepth <n>   -> max depth of recursion
                   95501:      * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
                   95502:      *
                   95503:      * @param  mixed Either array or string with the command line
                   95504:      * @return array Array of found files
                   95505:      * @static
                   95506:      *
                   95507:      */
                   95508:     function find($args)
                   95509:     {
                   95510:         if (!is_array($args)) {
                   95511:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   95512:         }
                   95513:         $dir = realpath(array_shift($args));
                   95514:         if (!$dir) {
                   95515:             return array();
                   95516:         }
                   95517:         $patterns = array();
                   95518:         $depth = 0;
                   95519:         $do_files = $do_dirs = true;
                   95520:         $args_count = count($args);
                   95521:         for ($i = 0; $i < $args_count; $i++) {
                   95522:             switch ($args[$i]) {
                   95523:                 case '-type':
                   95524:                     if (in_array($args[$i+1], array('d', 'f'))) {
                   95525:                         if ($args[$i+1] == 'd') {
                   95526:                             $do_files = false;
                   95527:                         } else {
                   95528:                             $do_dirs = false;
                   95529:                         }
                   95530:                     }
                   95531:                     $i++;
                   95532:                     break;
                   95533:                 case '-name':
                   95534:                     $name = preg_quote($args[$i+1], '#');
                   95535:                     // our magic characters ? and * have just been escaped,
                   95536:                     // so now we change the escaped versions to PCRE operators
                   95537:                     $name = strtr($name, array('\?' => '.', '\*' => '.*'));
                   95538:                     $patterns[] = '('.$name.')';
                   95539:                     $i++;
                   95540:                     break;
                   95541:                 case '-maxdepth':
                   95542:                     $depth = $args[$i+1];
                   95543:                     break;
                   95544:             }
                   95545:         }
                   95546:         $path = System::_dirToStruct($dir, $depth, 0, true);
                   95547:         if ($do_files && $do_dirs) {
                   95548:             $files = array_merge($path['files'], $path['dirs']);
                   95549:         } elseif ($do_dirs) {
                   95550:             $files = $path['dirs'];
                   95551:         } else {
                   95552:             $files = $path['files'];
                   95553:         }
                   95554:         if (count($patterns)) {
                   95555:             $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
                   95556:             $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
                   95557:             $ret = array();
                   95558:             $files_count = count($files);
                   95559:             for ($i = 0; $i < $files_count; $i++) {
                   95560:                 // only search in the part of the file below the current directory
                   95561:                 $filepart = basename($files[$i]);
                   95562:                 if (preg_match($pattern, $filepart)) {
                   95563:                     $ret[] = $files[$i];
                   95564:                 }
                   95565:             }
                   95566:             return $ret;
                   95567:         }
                   95568:         return $files;
                   95569:     }
                   95570: }<?php
                   95571: 
                   95572: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   95573: 
                   95574: /**
                   95575:  * XML_Util
                   95576:  *
                   95577:  * XML Utilities package
                   95578:  *
                   95579:  * PHP versions 4 and 5
                   95580:  *
                   95581:  * LICENSE:
                   95582:  *
                   95583:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   95584:  * All rights reserved.
                   95585:  *
                   95586:  * Redistribution and use in source and binary forms, with or without
                   95587:  * modification, are permitted provided that the following conditions
                   95588:  * are met:
                   95589:  *
                   95590:  *    * Redistributions of source code must retain the above copyright
                   95591:  *      notice, this list of conditions and the following disclaimer.
                   95592:  *    * Redistributions in binary form must reproduce the above copyright
                   95593:  *      notice, this list of conditions and the following disclaimer in the
                   95594:  *      documentation and/or other materials provided with the distribution.
                   95595:  *    * The name of the author may not be used to endorse or promote products
                   95596:  *      derived from this software without specific prior written permission.
                   95597:  *
                   95598:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   95599:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   95600:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   95601:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   95602:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   95603:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   95604:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   95605:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   95606:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   95607:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   95608:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   95609:  *
                   95610:  * @category  XML
                   95611:  * @package   XML_Util
                   95612:  * @author    Stephan Schmidt <schst@php.net>
                   95613:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   95614:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   95615:  * @version   CVS: $Id: Util.php 275418 2009-02-09 14:23:42Z ashnazg $
                   95616:  * @link      http://pear.php.net/package/XML_Util
                   95617:  */
                   95618: 
                   95619: /**
                   95620:  * error code for invalid chars in XML name
                   95621:  */
                   95622: define('XML_UTIL_ERROR_INVALID_CHARS', 51);
                   95623: 
                   95624: /**
                   95625:  * error code for invalid chars in XML name
                   95626:  */
                   95627: define('XML_UTIL_ERROR_INVALID_START', 52);
                   95628: 
                   95629: /**
                   95630:  * error code for non-scalar tag content
                   95631:  */
                   95632: define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
                   95633: 
                   95634: /**
                   95635:  * error code for missing tag name
                   95636:  */
                   95637: define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
                   95638: 
                   95639: /**
                   95640:  * replace XML entities
                   95641:  */
                   95642: define('XML_UTIL_REPLACE_ENTITIES', 1);
                   95643: 
                   95644: /**
                   95645:  * embedd content in a CData Section
                   95646:  */
                   95647: define('XML_UTIL_CDATA_SECTION', 5);
                   95648: 
                   95649: /**
                   95650:  * do not replace entitites
                   95651:  */
                   95652: define('XML_UTIL_ENTITIES_NONE', 0);
                   95653: 
                   95654: /**
                   95655:  * replace all XML entitites
                   95656:  * This setting will replace <, >, ", ' and &
                   95657:  */
                   95658: define('XML_UTIL_ENTITIES_XML', 1);
                   95659: 
                   95660: /**
                   95661:  * replace only required XML entitites
                   95662:  * This setting will replace <, " and &
                   95663:  */
                   95664: define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
                   95665: 
                   95666: /**
                   95667:  * replace HTML entitites
                   95668:  * @link http://www.php.net/htmlentities
                   95669:  */
                   95670: define('XML_UTIL_ENTITIES_HTML', 3);
                   95671: 
                   95672: /**
                   95673:  * Collapse all empty tags.
                   95674:  */
                   95675: define('XML_UTIL_COLLAPSE_ALL', 1);
                   95676: 
                   95677: /**
                   95678:  * Collapse only empty XHTML tags that have no end tag.
                   95679:  */
                   95680: define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
                   95681: 
                   95682: /**
                   95683:  * utility class for working with XML documents
                   95684:  *
                   95685: 
                   95686:  * @category  XML
                   95687:  * @package   XML_Util
                   95688:  * @author    Stephan Schmidt <schst@php.net>
                   95689:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   95690:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   95691:  * @version   Release: @version@
                   95692:  * @link      http://pear.php.net/package/XML_Util
                   95693:  */
                   95694: class XML_Util
                   95695: {
                   95696:     /**
                   95697:      * return API version
                   95698:      *
                   95699:      * @return string $version API version
                   95700:      * @access public
                   95701:      * @static
                   95702:      */
                   95703:     function apiVersion()
                   95704:     {
                   95705:         return '1.1';
                   95706:     }
                   95707: 
                   95708:     /**
                   95709:      * replace XML entities
                   95710:      *
                   95711:      * With the optional second parameter, you may select, which
                   95712:      * entities should be replaced.
                   95713:      *
                   95714:      * <code>
                   95715:      * require_once 'XML/Util.php';
                   95716:      *
                   95717:      * // replace XML entites:
                   95718:      * $string = XML_Util::replaceEntities('This string contains < & >.');
                   95719:      * </code>
                   95720:      *
                   95721:      * With the optional third parameter, you may pass the character encoding
                   95722:      * <code>
                   95723:      * require_once 'XML/Util.php';
                   95724:      *
                   95725:      * // replace XML entites in UTF-8:
                   95726:      * $string = XML_Util::replaceEntities(
                   95727:      *     'This string contains < & > as well as 盲, 枚, 脽, 脿 and 锚',
                   95728:      *     XML_UTIL_ENTITIES_HTML,
                   95729:      *     'UTF-8'
                   95730:      * );
                   95731:      * </code>
                   95732:      *
                   95733:      * @param string $string          string where XML special chars
                   95734:      *                                should be replaced
                   95735:      * @param int    $replaceEntities setting for entities in attribute values
                   95736:      *                                (one of XML_UTIL_ENTITIES_XML,
                   95737:      *                                XML_UTIL_ENTITIES_XML_REQUIRED,
                   95738:      *                                XML_UTIL_ENTITIES_HTML)
                   95739:      * @param string $encoding        encoding value (if any)...
                   95740:      *                                must be a valid encoding as determined
                   95741:      *                                by the htmlentities() function
                   95742:      *
                   95743:      * @return string string with replaced chars
                   95744:      * @access public
                   95745:      * @static
                   95746:      * @see reverseEntities()
                   95747:      */
                   95748:     function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   95749:         $encoding = 'ISO-8859-1')
                   95750:     {
                   95751:         switch ($replaceEntities) {
                   95752:         case XML_UTIL_ENTITIES_XML:
                   95753:             return strtr($string, array(
                   95754:                 '&'  => '&amp;',
                   95755:                 '>'  => '&gt;',
                   95756:                 '<'  => '&lt;',
                   95757:                 '"'  => '&quot;',
                   95758:                 '\'' => '&apos;' ));
                   95759:             break;
                   95760:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   95761:             return strtr($string, array(
                   95762:                 '&' => '&amp;',
                   95763:                 '<' => '&lt;',
                   95764:                 '"' => '&quot;' ));
                   95765:             break;
                   95766:         case XML_UTIL_ENTITIES_HTML:
                   95767:             return htmlentities($string, ENT_COMPAT, $encoding);
                   95768:             break;
                   95769:         }
                   95770:         return $string;
                   95771:     }
                   95772: 
                   95773:     /**
                   95774:      * reverse XML entities
                   95775:      *
                   95776:      * With the optional second parameter, you may select, which
                   95777:      * entities should be reversed.
                   95778:      *
                   95779:      * <code>
                   95780:      * require_once 'XML/Util.php';
                   95781:      *
                   95782:      * // reverse XML entites:
                   95783:      * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   95784:      * </code>
                   95785:      *
                   95786:      * With the optional third parameter, you may pass the character encoding
                   95787:      * <code>
                   95788:      * require_once 'XML/Util.php';
                   95789:      *
                   95790:      * // reverse XML entites in UTF-8:
                   95791:      * $string = XML_Util::reverseEntities(
                   95792:      *     'This string contains &lt; &amp; &gt; as well as'
                   95793:      *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
                   95794:      *     XML_UTIL_ENTITIES_HTML,
                   95795:      *     'UTF-8'
                   95796:      * );
                   95797:      * </code>
                   95798:      *
                   95799:      * @param string $string          string where XML special chars
                   95800:      *                                should be replaced
                   95801:      * @param int    $replaceEntities setting for entities in attribute values
                   95802:      *                                (one of XML_UTIL_ENTITIES_XML,
                   95803:      *                                XML_UTIL_ENTITIES_XML_REQUIRED,
                   95804:      *                                XML_UTIL_ENTITIES_HTML)
                   95805:      * @param string $encoding        encoding value (if any)...
                   95806:      *                                must be a valid encoding as determined
                   95807:      *                                by the html_entity_decode() function
                   95808:      *
                   95809:      * @return string string with replaced chars
                   95810:      * @access public
                   95811:      * @static
                   95812:      * @see replaceEntities()
                   95813:      */
                   95814:     function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   95815:         $encoding = 'ISO-8859-1')
                   95816:     {
                   95817:         switch ($replaceEntities) {
                   95818:         case XML_UTIL_ENTITIES_XML:
                   95819:             return strtr($string, array(
                   95820:                 '&amp;'  => '&',
                   95821:                 '&gt;'   => '>',
                   95822:                 '&lt;'   => '<',
                   95823:                 '&quot;' => '"',
                   95824:                 '&apos;' => '\'' ));
                   95825:             break;
                   95826:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   95827:             return strtr($string, array(
                   95828:                 '&amp;'  => '&',
                   95829:                 '&lt;'   => '<',
                   95830:                 '&quot;' => '"' ));
                   95831:             break;
                   95832:         case XML_UTIL_ENTITIES_HTML:
                   95833:             return html_entity_decode($string, ENT_COMPAT, $encoding);
                   95834:             break;
                   95835:         }
                   95836:         return $string;
                   95837:     }
                   95838: 
                   95839:     /**
                   95840:      * build an xml declaration
                   95841:      *
                   95842:      * <code>
                   95843:      * require_once 'XML/Util.php';
                   95844:      *
                   95845:      * // get an XML declaration:
                   95846:      * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
                   95847:      * </code>
                   95848:      *
                   95849:      * @param string $version    xml version
                   95850:      * @param string $encoding   character encoding
                   95851:      * @param bool   $standalone document is standalone (or not)
                   95852:      *
                   95853:      * @return string xml declaration
                   95854:      * @access public
                   95855:      * @static
                   95856:      * @uses attributesToString() to serialize the attributes of the XML declaration
                   95857:      */
                   95858:     function getXMLDeclaration($version = '1.0', $encoding = null,
                   95859:         $standalone = null)
                   95860:     {
                   95861:         $attributes = array(
                   95862:             'version' => $version,
                   95863:         );
                   95864:         // add encoding
                   95865:         if ($encoding !== null) {
                   95866:             $attributes['encoding'] = $encoding;
                   95867:         }
                   95868:         // add standalone, if specified
                   95869:         if ($standalone !== null) {
                   95870:             $attributes['standalone'] = $standalone ? 'yes' : 'no';
                   95871:         }
                   95872: 
                   95873:         return sprintf('<?xml%s?>',
                   95874:             XML_Util::attributesToString($attributes, false));
                   95875:     }
                   95876: 
                   95877:     /**
                   95878:      * build a document type declaration
                   95879:      *
                   95880:      * <code>
                   95881:      * require_once 'XML/Util.php';
                   95882:      *
                   95883:      * // get a doctype declaration:
                   95884:      * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
                   95885:      * </code>
                   95886:      *
                   95887:      * @param string $root        name of the root tag
                   95888:      * @param string $uri         uri of the doctype definition
                   95889:      *                            (or array with uri and public id)
                   95890:      * @param string $internalDtd internal dtd entries
                   95891:      *
                   95892:      * @return string doctype declaration
                   95893:      * @access public
                   95894:      * @static
                   95895:      * @since 0.2
                   95896:      */
                   95897:     function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
                   95898:     {
                   95899:         if (is_array($uri)) {
                   95900:             $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
                   95901:         } elseif (!empty($uri)) {
                   95902:             $ref = sprintf(' SYSTEM "%s"', $uri);
                   95903:         } else {
                   95904:             $ref = '';
                   95905:         }
                   95906: 
                   95907:         if (empty($internalDtd)) {
                   95908:             return sprintf('<!DOCTYPE %s%s>', $root, $ref);
                   95909:         } else {
                   95910:             return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
                   95911:         }
                   95912:     }
                   95913: 
                   95914:     /**
                   95915:      * create string representation of an attribute list
                   95916:      *
                   95917:      * <code>
                   95918:      * require_once 'XML/Util.php';
                   95919:      *
                   95920:      * // build an attribute string
                   95921:      * $att = array(
                   95922:      *              'foo'   =>  'bar',
                   95923:      *              'argh'  =>  'tomato'
                   95924:      *            );
                   95925:      *
                   95926:      * $attList = XML_Util::attributesToString($att);
                   95927:      * </code>
                   95928:      *
                   95929:      * @param array      $attributes attribute array
                   95930:      * @param bool|array $sort       sort attribute list alphabetically,
                   95931:      *                               may also be an assoc array containing
                   95932:      *                               the keys 'sort', 'multiline', 'indent',
                   95933:      *                               'linebreak' and 'entities'
                   95934:      * @param bool       $multiline  use linebreaks, if more than
                   95935:      *                               one attribute is given
                   95936:      * @param string     $indent     string used for indentation of
                   95937:      *                               multiline attributes
                   95938:      * @param string     $linebreak  string used for linebreaks of
                   95939:      *                               multiline attributes
                   95940:      * @param int        $entities   setting for entities in attribute values
                   95941:      *                               (one of XML_UTIL_ENTITIES_NONE,
                   95942:      *                               XML_UTIL_ENTITIES_XML,
                   95943:      *                               XML_UTIL_ENTITIES_XML_REQUIRED,
                   95944:      *                               XML_UTIL_ENTITIES_HTML)
                   95945:      *
                   95946:      * @return string string representation of the attributes
                   95947:      * @access public
                   95948:      * @static
                   95949:      * @uses replaceEntities() to replace XML entities in attribute values
                   95950:      * @todo allow sort also to be an options array
                   95951:      */
                   95952:     function attributesToString($attributes, $sort = true, $multiline = false,
                   95953:         $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
                   95954:     {
                   95955:         /*
                   95956:          * second parameter may be an array
                   95957:          */
                   95958:         if (is_array($sort)) {
                   95959:             if (isset($sort['multiline'])) {
                   95960:                 $multiline = $sort['multiline'];
                   95961:             }
                   95962:             if (isset($sort['indent'])) {
                   95963:                 $indent = $sort['indent'];
                   95964:             }
                   95965:             if (isset($sort['linebreak'])) {
                   95966:                 $multiline = $sort['linebreak'];
                   95967:             }
                   95968:             if (isset($sort['entities'])) {
                   95969:                 $entities = $sort['entities'];
                   95970:             }
                   95971:             if (isset($sort['sort'])) {
                   95972:                 $sort = $sort['sort'];
                   95973:             } else {
                   95974:                 $sort = true;
                   95975:             }
                   95976:         }
                   95977:         $string = '';
                   95978:         if (is_array($attributes) && !empty($attributes)) {
                   95979:             if ($sort) {
                   95980:                 ksort($attributes);
                   95981:             }
                   95982:             if ( !$multiline || count($attributes) == 1) {
                   95983:                 foreach ($attributes as $key => $value) {
                   95984:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   95985:                         if ($entities === XML_UTIL_CDATA_SECTION) {
                   95986:                             $entities = XML_UTIL_ENTITIES_XML;
                   95987:                         }
                   95988:                         $value = XML_Util::replaceEntities($value, $entities);
                   95989:                     }
                   95990:                     $string .= ' ' . $key . '="' . $value . '"';
                   95991:                 }
                   95992:             } else {
                   95993:                 $first = true;
                   95994:                 foreach ($attributes as $key => $value) {
                   95995:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   95996:                         $value = XML_Util::replaceEntities($value, $entities);
                   95997:                     }
                   95998:                     if ($first) {
                   95999:                         $string .= ' ' . $key . '="' . $value . '"';
                   96000:                         $first   = false;
                   96001:                     } else {
                   96002:                         $string .= $linebreak . $indent . $key . '="' . $value . '"';
                   96003:                     }
                   96004:                 }
                   96005:             }
                   96006:         }
                   96007:         return $string;
                   96008:     }
                   96009: 
                   96010:     /**
                   96011:      * Collapses empty tags.
                   96012:      *
                   96013:      * @param string $xml  XML
                   96014:      * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
                   96015:      *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
                   96016:      *
                   96017:      * @return string XML
                   96018:      * @access public
                   96019:      * @static
                   96020:      * @todo PEAR CS - unable to avoid "space after open parens" error
                   96021:      *       in the IF branch
                   96022:      */
                   96023:     function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
                   96024:     {
                   96025:         if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
                   96026:             return preg_replace(
                   96027:                 '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                   96028:                 . 'param)([^>]*)><\/\\1>/s',
                   96029:                 '<\\1\\2 />',
                   96030:                 $xml);
                   96031:         } else {
                   96032:             return preg_replace('/<(\w+)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml);
                   96033:         }
                   96034:     }
                   96035: 
                   96036:     /**
                   96037:      * create a tag
                   96038:      *
                   96039:      * This method will call XML_Util::createTagFromArray(), which
                   96040:      * is more flexible.
                   96041:      *
                   96042:      * <code>
                   96043:      * require_once 'XML/Util.php';
                   96044:      *
                   96045:      * // create an XML tag:
                   96046:      * $tag = XML_Util::createTag('myNs:myTag',
                   96047:      *     array('foo' => 'bar'),
                   96048:      *     'This is inside the tag',
                   96049:      *     'http://www.w3c.org/myNs#');
                   96050:      * </code>
                   96051:      *
                   96052:      * @param string $qname           qualified tagname (including namespace)
                   96053:      * @param array  $attributes      array containg attributes
                   96054:      * @param mixed  $content         the content
                   96055:      * @param string $namespaceUri    URI of the namespace
                   96056:      * @param int    $replaceEntities whether to replace XML special chars in
                   96057:      *                                content, embedd it in a CData section
                   96058:      *                                or none of both
                   96059:      * @param bool   $multiline       whether to create a multiline tag where
                   96060:      *                                each attribute gets written to a single line
                   96061:      * @param string $indent          string used to indent attributes
                   96062:      *                                (_auto indents attributes so they start
                   96063:      *                                at the same column)
                   96064:      * @param string $linebreak       string used for linebreaks
                   96065:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   96066:      *
                   96067:      * @return string XML tag
                   96068:      * @access public
                   96069:      * @static
                   96070:      * @see createTagFromArray()
                   96071:      * @uses createTagFromArray() to create the tag
                   96072:      */
                   96073:     function createTag($qname, $attributes = array(), $content = null,
                   96074:         $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
                   96075:         $multiline = false, $indent = '_auto', $linebreak = "\n",
                   96076:         $sortAttributes = true)
                   96077:     {
                   96078:         $tag = array(
                   96079:             'qname'      => $qname,
                   96080:             'attributes' => $attributes
                   96081:         );
                   96082: 
                   96083:         // add tag content
                   96084:         if ($content !== null) {
                   96085:             $tag['content'] = $content;
                   96086:         }
                   96087: 
                   96088:         // add namespace Uri
                   96089:         if ($namespaceUri !== null) {
                   96090:             $tag['namespaceUri'] = $namespaceUri;
                   96091:         }
                   96092: 
                   96093:         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,
                   96094:             $indent, $linebreak, $sortAttributes);
                   96095:     }
                   96096: 
                   96097:     /**
                   96098:      * create a tag from an array
                   96099:      * this method awaits an array in the following format
                   96100:      * <pre>
                   96101:      * array(
                   96102:      *     // qualified name of the tag
                   96103:      *     'qname' => $qname
                   96104:      *
                   96105:      *     // namespace prefix (optional, if qname is specified or no namespace)
                   96106:      *     'namespace' => $namespace
                   96107:      *
                   96108:      *     // local part of the tagname (optional, if qname is specified)
                   96109:      *     'localpart' => $localpart,
                   96110:      *
                   96111:      *     // array containing all attributes (optional)
                   96112:      *     'attributes' => array(),
                   96113:      *
                   96114:      *     // tag content (optional)
                   96115:      *     'content' => $content,
                   96116:      *
                   96117:      *     // namespaceUri for the given namespace (optional)
                   96118:      *     'namespaceUri' => $namespaceUri
                   96119:      * )
                   96120:      * </pre>
                   96121:      *
                   96122:      * <code>
                   96123:      * require_once 'XML/Util.php';
                   96124:      *
                   96125:      * $tag = array(
                   96126:      *     'qname'        => 'foo:bar',
                   96127:      *     'namespaceUri' => 'http://foo.com',
                   96128:      *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   96129:      *     'content'      => 'I\'m inside the tag',
                   96130:      * );
                   96131:      * // creating a tag with qualified name and namespaceUri
                   96132:      * $string = XML_Util::createTagFromArray($tag);
                   96133:      * </code>
                   96134:      *
                   96135:      * @param array  $tag             tag definition
                   96136:      * @param int    $replaceEntities whether to replace XML special chars in
                   96137:      *                                content, embedd it in a CData section
                   96138:      *                                or none of both
                   96139:      * @param bool   $multiline       whether to create a multiline tag where each
                   96140:      *                                attribute gets written to a single line
                   96141:      * @param string $indent          string used to indent attributes
                   96142:      *                                (_auto indents attributes so they start
                   96143:      *                                at the same column)
                   96144:      * @param string $linebreak       string used for linebreaks
                   96145:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   96146:      *
                   96147:      * @return string XML tag
                   96148:      * @access public
                   96149:      * @static
                   96150:      * @see createTag()
                   96151:      * @uses attributesToString() to serialize the attributes of the tag
                   96152:      * @uses splitQualifiedName() to get local part and namespace of a qualified name
                   96153:      * @uses createCDataSection()
                   96154:      * @uses raiseError()
                   96155:      */
                   96156:     function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
                   96157:         $multiline = false, $indent = '_auto', $linebreak = "\n",
                   96158:         $sortAttributes = true)
                   96159:     {
                   96160:         if (isset($tag['content']) && !is_scalar($tag['content'])) {
                   96161:             return XML_Util::raiseError('Supplied non-scalar value as tag content',
                   96162:             XML_UTIL_ERROR_NON_SCALAR_CONTENT);
                   96163:         }
                   96164: 
                   96165:         if (!isset($tag['qname']) && !isset($tag['localPart'])) {
                   96166:             return XML_Util::raiseError('You must either supply a qualified name '
                   96167:                 . '(qname) or local tag name (localPart).',
                   96168:                 XML_UTIL_ERROR_NO_TAG_NAME);
                   96169:         }
                   96170: 
                   96171:         // if no attributes hav been set, use empty attributes
                   96172:         if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
                   96173:             $tag['attributes'] = array();
                   96174:         }
                   96175: 
                   96176:         if (isset($tag['namespaces'])) {
                   96177:             foreach ($tag['namespaces'] as $ns => $uri) {
                   96178:                 $tag['attributes']['xmlns:' . $ns] = $uri;
                   96179:             }
                   96180:         }
                   96181: 
                   96182:         if (!isset($tag['qname'])) {
                   96183:             // qualified name is not given
                   96184: 
                   96185:             // check for namespace
                   96186:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   96187:                 $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
                   96188:             } else {
                   96189:                 $tag['qname'] = $tag['localPart'];
                   96190:             }
                   96191:         } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
                   96192:             // namespace URI is set, but no namespace
                   96193: 
                   96194:             $parts = XML_Util::splitQualifiedName($tag['qname']);
                   96195: 
                   96196:             $tag['localPart'] = $parts['localPart'];
                   96197:             if (isset($parts['namespace'])) {
                   96198:                 $tag['namespace'] = $parts['namespace'];
                   96199:             }
                   96200:         }
                   96201: 
                   96202:         if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
                   96203:             // is a namespace given
                   96204:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   96205:                 $tag['attributes']['xmlns:' . $tag['namespace']] =
                   96206:                     $tag['namespaceUri'];
                   96207:             } else {
                   96208:                 // define this Uri as the default namespace
                   96209:                 $tag['attributes']['xmlns'] = $tag['namespaceUri'];
                   96210:             }
                   96211:         }
                   96212: 
                   96213:         // check for multiline attributes
                   96214:         if ($multiline === true) {
                   96215:             if ($indent === '_auto') {
                   96216:                 $indent = str_repeat(' ', (strlen($tag['qname'])+2));
                   96217:             }
                   96218:         }
                   96219: 
                   96220:         // create attribute list
                   96221:         $attList = XML_Util::attributesToString($tag['attributes'],
                   96222:             $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
                   96223:         if (!isset($tag['content']) || (string)$tag['content'] == '') {
                   96224:             $tag = sprintf('<%s%s />', $tag['qname'], $attList);
                   96225:         } else {
                   96226:             switch ($replaceEntities) {
                   96227:             case XML_UTIL_ENTITIES_NONE:
                   96228:                 break;
                   96229:             case XML_UTIL_CDATA_SECTION:
                   96230:                 $tag['content'] = XML_Util::createCDataSection($tag['content']);
                   96231:                 break;
                   96232:             default:
                   96233:                 $tag['content'] = XML_Util::replaceEntities($tag['content'],
                   96234:                     $replaceEntities);
                   96235:                 break;
                   96236:             }
                   96237:             $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
                   96238:                 $tag['qname']);
                   96239:         }
                   96240:         return $tag;
                   96241:     }
                   96242: 
                   96243:     /**
                   96244:      * create a start element
                   96245:      *
                   96246:      * <code>
                   96247:      * require_once 'XML/Util.php';
                   96248:      *
                   96249:      * // create an XML start element:
                   96250:      * $tag = XML_Util::createStartElement('myNs:myTag',
                   96251:      *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
                   96252:      * </code>
                   96253:      *
                   96254:      * @param string $qname          qualified tagname (including namespace)
                   96255:      * @param array  $attributes     array containg attributes
                   96256:      * @param string $namespaceUri   URI of the namespace
                   96257:      * @param bool   $multiline      whether to create a multiline tag where each
                   96258:      *                               attribute gets written to a single line
                   96259:      * @param string $indent         string used to indent attributes (_auto indents
                   96260:      *                               attributes so they start at the same column)
                   96261:      * @param string $linebreak      string used for linebreaks
                   96262:      * @param bool   $sortAttributes Whether to sort the attributes or not
                   96263:      *
                   96264:      * @return string XML start element
                   96265:      * @access public
                   96266:      * @static
                   96267:      * @see createEndElement(), createTag()
                   96268:      */
                   96269:     function createStartElement($qname, $attributes = array(), $namespaceUri = null,
                   96270:         $multiline = false, $indent = '_auto', $linebreak = "\n",
                   96271:         $sortAttributes = true)
                   96272:     {
                   96273:         // if no attributes hav been set, use empty attributes
                   96274:         if (!isset($attributes) || !is_array($attributes)) {
                   96275:             $attributes = array();
                   96276:         }
                   96277: 
                   96278:         if ($namespaceUri != null) {
                   96279:             $parts = XML_Util::splitQualifiedName($qname);
                   96280:         }
                   96281: 
                   96282:         // check for multiline attributes
                   96283:         if ($multiline === true) {
                   96284:             if ($indent === '_auto') {
                   96285:                 $indent = str_repeat(' ', (strlen($qname)+2));
                   96286:             }
                   96287:         }
                   96288: 
                   96289:         if ($namespaceUri != null) {
                   96290:             // is a namespace given
                   96291:             if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                   96292:                 $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
                   96293:             } else {
                   96294:                 // define this Uri as the default namespace
                   96295:                 $attributes['xmlns'] = $namespaceUri;
                   96296:             }
                   96297:         }
                   96298: 
                   96299:         // create attribute list
                   96300:         $attList = XML_Util::attributesToString($attributes, $sortAttributes,
                   96301:             $multiline, $indent, $linebreak);
                   96302:         $element = sprintf('<%s%s>', $qname, $attList);
                   96303:         return  $element;
                   96304:     }
                   96305: 
                   96306:     /**
                   96307:      * create an end element
                   96308:      *
                   96309:      * <code>
                   96310:      * require_once 'XML/Util.php';
                   96311:      *
                   96312:      * // create an XML start element:
                   96313:      * $tag = XML_Util::createEndElement('myNs:myTag');
                   96314:      * </code>
                   96315:      *
                   96316:      * @param string $qname qualified tagname (including namespace)
                   96317:      *
                   96318:      * @return string XML end element
                   96319:      * @access public
                   96320:      * @static
                   96321:      * @see createStartElement(), createTag()
                   96322:      */
                   96323:     function createEndElement($qname)
                   96324:     {
                   96325:         $element = sprintf('</%s>', $qname);
                   96326:         return $element;
                   96327:     }
                   96328: 
                   96329:     /**
                   96330:      * create an XML comment
                   96331:      *
                   96332:      * <code>
                   96333:      * require_once 'XML/Util.php';
                   96334:      *
                   96335:      * // create an XML start element:
                   96336:      * $tag = XML_Util::createComment('I am a comment');
                   96337:      * </code>
                   96338:      *
                   96339:      * @param string $content content of the comment
                   96340:      *
                   96341:      * @return string XML comment
                   96342:      * @access public
                   96343:      * @static
                   96344:      */
                   96345:     function createComment($content)
                   96346:     {
                   96347:         $comment = sprintf('<!-- %s -->', $content);
                   96348:         return $comment;
                   96349:     }
                   96350: 
                   96351:     /**
                   96352:      * create a CData section
                   96353:      *
                   96354:      * <code>
                   96355:      * require_once 'XML/Util.php';
                   96356:      *
                   96357:      * // create a CData section
                   96358:      * $tag = XML_Util::createCDataSection('I am content.');
                   96359:      * </code>
                   96360:      *
                   96361:      * @param string $data data of the CData section
                   96362:      *
                   96363:      * @return string CData section with content
                   96364:      * @access public
                   96365:      * @static
                   96366:      */
                   96367:     function createCDataSection($data)
                   96368:     {
                   96369:         return sprintf('<![CDATA[%s]]>',
                   96370:             preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
                   96371: 
                   96372:     }
                   96373: 
                   96374:     /**
                   96375:      * split qualified name and return namespace and local part
                   96376:      *
                   96377:      * <code>
                   96378:      * require_once 'XML/Util.php';
                   96379:      *
                   96380:      * // split qualified tag
                   96381:      * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
                   96382:      * </code>
                   96383:      * the returned array will contain two elements:
                   96384:      * <pre>
                   96385:      * array(
                   96386:      *     'namespace' => 'xslt',
                   96387:      *     'localPart' => 'stylesheet'
                   96388:      * );
                   96389:      * </pre>
                   96390:      *
                   96391:      * @param string $qname     qualified tag name
                   96392:      * @param string $defaultNs default namespace (optional)
                   96393:      *
                   96394:      * @return array array containing namespace and local part
                   96395:      * @access public
                   96396:      * @static
                   96397:      */
                   96398:     function splitQualifiedName($qname, $defaultNs = null)
                   96399:     {
                   96400:         if (strstr($qname, ':')) {
                   96401:             $tmp = explode(':', $qname);
                   96402:             return array(
                   96403:                 'namespace' => $tmp[0],
                   96404:                 'localPart' => $tmp[1]
                   96405:             );
                   96406:         }
                   96407:         return array(
                   96408:             'namespace' => $defaultNs,
                   96409:             'localPart' => $qname
                   96410:         );
                   96411:     }
                   96412: 
                   96413:     /**
                   96414:      * check, whether string is valid XML name
                   96415:      *
                   96416:      * <p>XML names are used for tagname, attribute names and various
                   96417:      * other, lesser known entities.</p>
                   96418:      * <p>An XML name may only consist of alphanumeric characters,
                   96419:      * dashes, undescores and periods, and has to start with a letter
                   96420:      * or an underscore.</p>
                   96421:      *
                   96422:      * <code>
                   96423:      * require_once 'XML/Util.php';
                   96424:      *
                   96425:      * // verify tag name
                   96426:      * $result = XML_Util::isValidName('invalidTag?');
                   96427:      * if (is_a($result, 'PEAR_Error')) {
                   96428:      *    print 'Invalid XML name: ' . $result->getMessage();
                   96429:      * }
                   96430:      * </code>
                   96431:      *
                   96432:      * @param string $string string that should be checked
                   96433:      *
                   96434:      * @return mixed true, if string is a valid XML name, PEAR error otherwise
                   96435:      * @access public
                   96436:      * @static
                   96437:      * @todo support for other charsets
                   96438:      * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
                   96439:      */
                   96440:     function isValidName($string)
                   96441:     {
                   96442:         // check for invalid chars
                   96443:         if (!preg_match('/^[[:alpha:]_]\\z/', $string{0})) {
                   96444:             return XML_Util::raiseError('XML names may only start with letter '
                   96445:                 . 'or underscore', XML_UTIL_ERROR_INVALID_START);
                   96446:         }
                   96447: 
                   96448:         // check for invalid chars
                   96449:         if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
                   96450:             $string)
                   96451:         ) {
                   96452:             return XML_Util::raiseError('XML names may only contain alphanumeric '
                   96453:                 . 'chars, period, hyphen, colon and underscores',
                   96454:                 XML_UTIL_ERROR_INVALID_CHARS);
                   96455:         }
                   96456:         // XML name is valid
                   96457:         return true;
                   96458:     }
                   96459: 
                   96460:     /**
                   96461:      * replacement for XML_Util::raiseError
                   96462:      *
                   96463:      * Avoids the necessity to always require
                   96464:      * PEAR.php
                   96465:      *
                   96466:      * @param string $msg  error message
                   96467:      * @param int    $code error code
                   96468:      *
                   96469:      * @return PEAR_Error
                   96470:      * @access public
                   96471:      * @static
                   96472:      * @todo PEAR CS - should this use include_once instead?
                   96473:      */
                   96474:     function raiseError($msg, $code)
                   96475:     {
                   96476:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   96477:         return PEAR::raiseError($msg, $code);
                   96478:     }
                   96479: }
                   96480: ?>
                   96481: package.xml100644   1750   1750       36035 11117075467   6455 <?xml version="1.0" encoding="UTF-8"?>
                   96482: <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">
                   96483:  <name>XML_Util</name>
                   96484:  <channel>pear.php.net</channel>
                   96485:  <summary>XML utility class</summary>
                   96486:  <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>
                   96487:  <lead>
                   96488:   <name>Chuck Burgess</name>
                   96489:   <user>ashnazg</user>
                   96490:   <email>ashnazg@php.net</email>
                   96491:   <active>yes</active>
                   96492:  </lead>
                   96493:  <lead>
                   96494:   <name>Stephan Schmidt</name>
                   96495:   <user>schst</user>
                   96496:   <email>schst@php-tools.net</email>
                   96497:   <active>no</active>
                   96498:  </lead>
                   96499:  <helper>
                   96500:   <name>Davey Shafik</name>
                   96501:   <user>davey</user>
                   96502:   <email>davey@php.net</email>
                   96503:   <active>no</active>
                   96504:  </helper>
                   96505:  <date>2008-12-07</date>
                   96506:  <time>19:41:10</time>
                   96507:  <version>
                   96508:   <release>1.2.1</release>
                   96509:   <api>1.2.0</api>
                   96510:  </version>
                   96511:  <stability>
                   96512:   <release>stable</release>
                   96513:   <api>stable</api>
                   96514:  </stability>
                   96515:  <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96516:  <notes>Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil]</notes>
                   96517:  <contents>
                   96518:   <dir baseinstalldir="XML" name="/">
                   96519:    <file baseinstalldir="XML" md5sum="06b6662b91b1a466e7b5113f37d4725f" name="examples/example.php" role="doc" />
                   96520:    <file baseinstalldir="XML" md5sum="77355702c9e861d3fc0a5318ea689eee" name="examples/example2.php" role="doc" />
                   96521:    <file baseinstalldir="XML" md5sum="0af0cff09232a6c275803bb36213cdd9" name="tests/AllTests.php" role="test" />
                   96522:    <file baseinstalldir="XML" md5sum="73088689d58b71cd4f86013c88b72216" name="tests/testBasic_apiVersion.phpt" role="test" />
                   96523:    <file baseinstalldir="XML" md5sum="4b17c0df7fbfb1bb2f3f636ebd6c2cbd" name="tests/testBasic_attributesToString.phpt" role="test" />
                   96524:    <file baseinstalldir="XML" md5sum="dc4202f1451bbeb62a5bc7d56a7c774c" name="tests/testBasic_collapseEmptyTags.phpt" role="test" />
                   96525:    <file baseinstalldir="XML" md5sum="4c87fda94fdfb7a78ba84998d6e28f45" name="tests/testBasic_createCDataSection.phpt" role="test" />
                   96526:    <file baseinstalldir="XML" md5sum="c101844768f146653c59c81978060158" name="tests/testBasic_createComment.phpt" role="test" />
                   96527:    <file baseinstalldir="XML" md5sum="ba75d66c2f0fb0010c71f3bcd1f64eb2" name="tests/testBasic_createEndElement.phpt" role="test" />
                   96528:    <file baseinstalldir="XML" md5sum="ad786fb687e1eea1f6890a7424709c79" name="tests/testBasic_createStartElement.phpt" role="test" />
                   96529:    <file baseinstalldir="XML" md5sum="5f453edadebaa3435c8e6f09a3aaaa9c" name="tests/testBasic_createTag.phpt" role="test" />
                   96530:    <file baseinstalldir="XML" md5sum="d2792da0d9c5f0987ee4587912017aa9" name="tests/testBasic_createTagFromArray.phpt" role="test" />
                   96531:    <file baseinstalldir="XML" md5sum="817882a0ab33e60f17ee71874ad975f0" name="tests/testBasic_getDocTypeDeclaration.phpt" role="test" />
                   96532:    <file baseinstalldir="XML" md5sum="5bc1926a488a6b63ec6366bfcf06a50a" name="tests/testBasic_getXmlDeclaration.phpt" role="test" />
                   96533:    <file baseinstalldir="XML" md5sum="a727860d55c14194fdaffa839a59a540" name="tests/testBasic_isValidName.phpt" role="test" />
                   96534:    <file baseinstalldir="XML" md5sum="300a6192f7cc6f7bc3d8f2576b51e4b0" name="tests/testBasic_raiseError.phpt" role="test" />
                   96535:    <file baseinstalldir="XML" md5sum="e6717d43001775cccd52bd5195cf02e0" name="tests/testBasic_replaceEntities.phpt" role="test" />
                   96536:    <file baseinstalldir="XML" md5sum="431856aa83a23396a9f00915dd2be192" name="tests/testBasic_reverseEntities.phpt" role="test" />
                   96537:    <file baseinstalldir="XML" md5sum="ab035534463cae8cc903e907aead8ffe" name="tests/testBasic_splitQualifiedName.phpt" role="test" />
                   96538:    <file baseinstalldir="XML" md5sum="1850856692ff6c6df5e8acb16e1080ce" name="tests/testBug_4950.phpt" role="test" />
                   96539:    <file baseinstalldir="XML" md5sum="b4127883df40a4b0d1736ad42215ee25" name="tests/testBug_5392.phpt" role="test" />
                   96540:    <file baseinstalldir="XML" md5sum="9bb265dafaaf06c86ca5c48f50368ded" name="Util.php" role="php">
                   96541:     <tasks:replace from="@version@" to="version" type="package-info" />
                   96542:    </file>
                   96543:   </dir>
                   96544:  </contents>
                   96545:  <dependencies>
                   96546:   <required>
                   96547:    <php>
                   96548:     <min>4.3.0</min>
                   96549:    </php>
                   96550:    <pearinstaller>
                   96551:     <min>1.4.3</min>
                   96552:    </pearinstaller>
                   96553:    <extension>
                   96554:     <name>pcre</name>
                   96555:    </extension>
                   96556:   </required>
                   96557:  </dependencies>
                   96558:  <phprelease />
                   96559:  <changelog>
                   96560:   <release>
                   96561:    <version>
                   96562:     <release>1.2.1</release>
                   96563:     <api>1.2.0</api>
                   96564:    </version>
                   96565:    <stability>
                   96566:     <release>stable</release>
                   96567:     <api>stable</api>
                   96568:    </stability>
                   96569:    <date>2008-12-07</date>
                   96570:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96571:    <notes>Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil]</notes>
                   96572:   </release>
                   96573:   <release>
                   96574:    <version>
                   96575:     <release>1.2.0</release>
                   96576:     <api>1.2.0</api>
                   96577:    </version>
                   96578:    <stability>
                   96579:     <release>stable</release>
                   96580:     <api>stable</api>
                   96581:    </stability>
                   96582:    <date>2008-07-26</date>
                   96583:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96584:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   96585: Added a test suite against all API methods [ashnazg]
                   96586: Switch to package.xml v2 [ashnazg]
                   96587: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   96588: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   96589: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   96590: -- (this fix differs from the one in v1.2.0a1)</notes>
                   96591:   </release>
                   96592:   <release>
                   96593:    <version>
                   96594:     <release>1.2.0RC1</release>
                   96595:     <api>1.2.0</api>
                   96596:    </version>
                   96597:    <stability>
                   96598:     <release>beta</release>
                   96599:     <api>beta</api>
                   96600:    </stability>
                   96601:    <date>2008-07-12</date>
                   96602:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96603:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   96604: Added a test suite against all API methods [ashnazg]
                   96605: Switch to package.xml v2 [ashnazg]
                   96606: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   96607: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   96608: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   96609: -- (this fix differs from the one in v1.2.0a1)</notes>
                   96610:   </release>
                   96611:   <release>
                   96612:    <version>
                   96613:     <release>1.2.0a2</release>
                   96614:     <api>1.2.0</api>
                   96615:    </version>
                   96616:    <stability>
                   96617:     <release>alpha</release>
                   96618:     <api>alpha</api>
                   96619:    </stability>
                   96620:    <date>2008-05-22</date>
                   96621:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96622:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   96623: Added a test suite against all API methods [ashnazg]
                   96624: Switch to package.xml v2 [ashnazg]
                   96625: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   96626: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   96627: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   96628: -- (this fix differs from the one in v1.2.0a1)</notes>
                   96629:   </release>
                   96630:   <release>
                   96631:    <version>
                   96632:     <release>1.2.0a1</release>
                   96633:     <api>1.2.0</api>
                   96634:    </version>
                   96635:    <stability>
                   96636:     <release>alpha</release>
                   96637:     <api>alpha</api>
                   96638:    </stability>
                   96639:    <date>2008-05-04</date>
                   96640:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   96641:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   96642: Added a test suite against all API methods [ashnazg]
                   96643: Switch to package.xml v2 [ashnazg]
                   96644: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|ja.doma]</notes>
                   96645:   </release>
                   96646:   <release>
                   96647:    <version>
                   96648:     <release>1.1.4</release>
                   96649:     <api>1.1.4</api>
                   96650:    </version>
                   96651:    <stability>
                   96652:     <release>stable</release>
                   96653:     <api>stable</api>
                   96654:    </stability>
                   96655:    <date>2006-12-16</date>
                   96656:    <license uri="http://www.php.net/license">PHP License</license>
                   96657:    <notes>- Fixed bug #9561: Not allowing underscores in middle of tags</notes>
                   96658:   </release>
                   96659:   <release>
                   96660:    <version>
                   96661:     <release>1.1.2</release>
                   96662:     <api>1.1.2</api>
                   96663:    </version>
                   96664:    <stability>
                   96665:     <release>stable</release>
                   96666:     <api>stable</api>
                   96667:    </stability>
                   96668:    <date>2006-12-01</date>
                   96669:    <license uri="http://www.php.net/license">PHP License</license>
                   96670:    <notes>- fixed bug #5419: isValidName() now checks for character classes
                   96671: - implemented request #8196: added optional parameter to influence array sorting to createTag() createTagFromArray() and createStartElement()</notes>
                   96672:   </release>
                   96673:   <release>
                   96674:    <version>
                   96675:     <release>1.1.1</release>
                   96676:     <api>1.1.1</api>
                   96677:    </version>
                   96678:    <stability>
                   96679:     <release>stable</release>
                   96680:     <api>stable</api>
                   96681:    </stability>
                   96682:    <date>2004-12-23</date>
                   96683:    <license uri="http://www.php.net/license">PHP License</license>
                   96684:    <notes>- fixed bug in replaceEntities() and reverseEntities() in conjunction with XML_UTIL_ENTITIES_HTML
                   96685: - 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>
                   96686:   </release>
                   96687:   <release>
                   96688:    <version>
                   96689:     <release>1.1.0</release>
                   96690:     <api>1.1.0</api>
                   96691:    </version>
                   96692:    <stability>
                   96693:     <release>stable</release>
                   96694:     <api>stable</api>
                   96695:    </stability>
                   96696:    <date>2004-11-19</date>
                   96697:    <license uri="http://www.php.net/license">PHP License</license>
                   96698:    <notes>- Added collapseEmptyTags (patch by Sebastian Bergmann and Thomas Duffey)</notes>
                   96699:   </release>
                   96700:   <release>
                   96701:    <version>
                   96702:     <release>1.0.0</release>
                   96703:     <api>1.0.0</api>
                   96704:    </version>
                   96705:    <stability>
                   96706:     <release>stable</release>
                   96707:     <api>stable</api>
                   96708:    </stability>
                   96709:    <date>2004-10-28</date>
                   96710:    <license uri="http://www.php.net/license">PHP License</license>
                   96711:    <notes>- Added reverseEntities() (request #2639)</notes>
                   96712:   </release>
                   96713:   <release>
                   96714:    <version>
                   96715:     <release>0.6.1</release>
                   96716:     <api>0.6.1</api>
                   96717:    </version>
                   96718:    <stability>
                   96719:     <release>stable</release>
                   96720:     <api>stable</api>
                   96721:    </stability>
                   96722:    <date>2004-10-28</date>
                   96723:    <license uri="http://www.php.net/license">PHP License</license>
                   96724:    <notes>- Added check for tag name (either as local part or qualified name) in createTagFromArray() (bug #1083)</notes>
                   96725:   </release>
                   96726:   <release>
                   96727:    <version>
                   96728:     <release>0.6.0</release>
                   96729:     <api>0.6.0</api>
                   96730:    </version>
                   96731:    <stability>
                   96732:     <release>stable</release>
                   96733:     <api>stable</api>
                   96734:    </stability>
                   96735:    <date>2004-06-07</date>
                   96736:    <license uri="http://www.php.net/license">PHP License</license>
                   96737:    <notes>- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey)
                   96738: - added optional parameter to replaceEntities() to define the set of entities to replace
                   96739: - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann)
                   96740: - 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)
                   96741: - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error</notes>
                   96742:   </release>
                   96743:   <release>
                   96744:    <version>
                   96745:     <release>0.6.0beta1</release>
                   96746:     <api>0.6.0beta1</api>
                   96747:    </version>
                   96748:    <stability>
                   96749:     <release>beta</release>
                   96750:     <api>beta</api>
                   96751:    </stability>
                   96752:    <date>2004-05-24</date>
                   96753:    <license uri="http://www.php.net/license">PHP License</license>
                   96754:    <notes>- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey)
                   96755: - added optional parameter to replaceEntities() to define the set of entities to replace
                   96756: - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann)
                   96757: - 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)
                   96758: - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error</notes>
                   96759:   </release>
                   96760:   <release>
                   96761:    <version>
                   96762:     <release>0.5.2</release>
                   96763:     <api>0.5.2</api>
                   96764:    </version>
                   96765:    <stability>
                   96766:     <release>stable</release>
                   96767:     <api>stable</api>
                   96768:    </stability>
                   96769:    <date>2003-11-22</date>
                   96770:    <license uri="http://www.php.net/license">PHP License</license>
                   96771:    <notes>now creates XHTML compliant empty tags (Davey),
                   96772: minor whitespace fixes (Davey)</notes>
                   96773:   </release>
                   96774:   <release>
                   96775:    <version>
                   96776:     <release>0.5.1</release>
                   96777:     <api>0.5.1</api>
                   96778:    </version>
                   96779:    <stability>
                   96780:     <release>stable</release>
                   96781:     <api>stable</api>
                   96782:    </stability>
                   96783:    <date>2003-09-26</date>
                   96784:    <license uri="http://www.php.net/license">PHP License</license>
                   96785:    <notes>added default namespace parameter (optional) in splitQualifiedName() (requested by Sebastian Bergmann)</notes>
                   96786:   </release>
                   96787:   <release>
                   96788:    <version>
                   96789:     <release>0.5</release>
                   96790:     <api>0.5</api>
                   96791:    </version>
                   96792:    <stability>
                   96793:     <release>stable</release>
                   96794:     <api>stable</api>
                   96795:    </stability>
                   96796:    <date>2003-09-23</date>
                   96797:    <license uri="http://www.php.net/license">PHP License</license>
                   96798:    <notes>added support for multiline attributes in attributesToString(), createTag*() and createStartElement (requested by Yavor Shahpasov for XML_Serializer),
                   96799: added createComment</notes>
                   96800:   </release>
                   96801:   <release>
                   96802:    <version>
                   96803:     <release>0.4</release>
                   96804:     <api>0.4</api>
                   96805:    </version>
                   96806:    <stability>
                   96807:     <release>stable</release>
                   96808:     <api>stable</api>
                   96809:    </stability>
                   96810:    <date>2003-09-21</date>
                   96811:    <license uri="http://www.php.net/license">PHP License</license>
                   96812:    <notes>added createCDataSection(),
                   96813: added support for CData sections in createTag* methods,
                   96814: fixed bug #23,
                   96815: fixed bug in splitQualifiedName()</notes>
                   96816:   </release>
                   96817:   <release>
                   96818:    <version>
                   96819:     <release>0.3</release>
                   96820:     <api>0.3</api>
                   96821:    </version>
                   96822:    <stability>
                   96823:     <release>stable</release>
                   96824:     <api>stable</api>
                   96825:    </stability>
                   96826:    <date>2003-09-12</date>
                   96827:    <license uri="http://www.php.net/license">PHP License</license>
                   96828:    <notes>added createStartElement() and createEndElement()</notes>
                   96829:   </release>
                   96830:   <release>
                   96831:    <version>
                   96832:     <release>0.2.1</release>
                   96833:     <api>0.2.1</api>
                   96834:    </version>
                   96835:    <stability>
                   96836:     <release>stable</release>
                   96837:     <api>stable</api>
                   96838:    </stability>
                   96839:    <date>2003-09-05</date>
                   96840:    <license uri="http://www.php.net/license">PHP License</license>
                   96841:    <notes>fixed bug with zero as tag content in createTagFromArray and createTag</notes>
                   96842:   </release>
                   96843:   <release>
                   96844:    <version>
                   96845:     <release>0.2</release>
                   96846:     <api>0.2</api>
                   96847:    </version>
                   96848:    <stability>
                   96849:     <release>stable</release>
                   96850:     <api>stable</api>
                   96851:    </stability>
                   96852:    <date>2003-08-12</date>
                   96853:    <license uri="http://www.php.net/license">PHP License</license>
                   96854:    <notes>added XML_Util::getDocTypeDeclaration()</notes>
                   96855:   </release>
                   96856:   <release>
                   96857:    <version>
                   96858:     <release>0.1.1</release>
                   96859:     <api>0.1.1</api>
                   96860:    </version>
                   96861:    <stability>
                   96862:     <release>stable</release>
                   96863:     <api>stable</api>
                   96864:    </stability>
                   96865:    <date>2003-08-02</date>
                   96866:    <license uri="http://www.php.net/license">PHP License</license>
                   96867:    <notes>bugfix: removed bug in createTagFromArray</notes>
                   96868:   </release>
                   96869:   <release>
                   96870:    <version>
                   96871:     <release>0.1</release>
                   96872:     <api>0.1</api>
                   96873:    </version>
                   96874:    <stability>
                   96875:     <release>stable</release>
                   96876:     <api>stable</api>
                   96877:    </stability>
                   96878:    <date>2003-08-01</date>
                   96879:    <license uri="http://www.php.net/license">PHP License</license>
                   96880:    <notes>inital release</notes>
                   96881:   </release>
                   96882:  </changelog>
                   96883: </package>
                   96884: XML_Util-1.2.1/examples/example.php100644   1750   1750       21775 11117075466  12420 <?php
                   96885: 
                   96886: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   96887: 
                   96888: /**
                   96889:  * Examples (file #1)
                   96890:  *
                   96891:  * several examples for the methods of XML_Util
                   96892:  * 
                   96893:  * PHP versions 4 and 5
                   96894:  *
                   96895:  * LICENSE:
                   96896:  *
                   96897:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   96898:  * All rights reserved.
                   96899:  *
                   96900:  * Redistribution and use in source and binary forms, with or without
                   96901:  * modification, are permitted provided that the following conditions
                   96902:  * are met:
                   96903:  *
                   96904:  *    * Redistributions of source code must retain the above copyright
                   96905:  *      notice, this list of conditions and the following disclaimer.
                   96906:  *    * Redistributions in binary form must reproduce the above copyright
                   96907:  *      notice, this list of conditions and the following disclaimer in the
                   96908:  *      documentation and/or other materials provided with the distribution.
                   96909:  *    * The name of the author may not be used to endorse or promote products
                   96910:  *      derived from this software without specific prior written permission.
                   96911:  *
                   96912:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   96913:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   96914:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   96915:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   96916:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   96917:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   96918:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   96919:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   96920:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   96921:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   96922:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   96923:  *
                   96924:  * @category   XML
                   96925:  * @package    XML_Util
                   96926:  * @subpackage Examples
                   96927:  * @author     Stephan Schmidt <schst@php.net>
                   96928:  * @copyright  2003-2008 Stephan Schmidt <schst@php.net>
                   96929:  * @license    http://opensource.org/licenses/bsd-license New BSD License
                   96930:  * @version    CVS: $Id: example.php,v 1.17 2008/05/05 19:05:28 ashnazg Exp $
                   96931:  * @link       http://pear.php.net/package/XML_Util
                   96932:  */
                   96933: 
                   96934:     /**
                   96935:      * set error level
                   96936:      */
                   96937:     error_reporting(E_ALL);
                   96938: 
                   96939:     require_once 'XML/Util.php';
                   96940:     
                   96941:     /**
                   96942:      * replacing XML entities
                   96943:      */
                   96944:     print 'replace XML entities:<br>';
                   96945:     print XML_Util::replaceEntities('This string contains < & >.');
                   96946:     print "\n<br><br>\n";
                   96947: 
                   96948:     /**
                   96949:      * reversing XML entities
                   96950:      */
                   96951:     print 'replace XML entities:<br>';
                   96952:     print XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   96953:     print "\n<br><br>\n";
                   96954: 
                   96955:     /**
                   96956:      * building XML declaration
                   96957:      */
                   96958:     print 'building XML declaration:<br>';
                   96959:     print htmlspecialchars(XML_Util::getXMLDeclaration());
                   96960:     print "\n<br><br>\n";
                   96961: 
                   96962:     print 'building XML declaration with additional attributes:<br>';
                   96963:     print htmlspecialchars(XML_Util::getXMLDeclaration('1.0', 'UTF-8', true));
                   96964:     print "\n<br><br>\n";
                   96965: 
                   96966:     /**
                   96967:      * building document type declaration
                   96968:      */
                   96969:     print 'building DocType declaration:<br>';
                   96970:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   96971:         'http://pear.php.net/dtd/package-1.0'));
                   96972:     print "\n<br><br>\n";
                   96973: 
                   96974:     print 'building DocType declaration with public ID (does not exist):<br>';
                   96975:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   96976:         array('uri' => 'http://pear.php.net/dtd/package-1.0', 
                   96977:             'id' => '-//PHP//PEAR/DTD PACKAGE 0.1')));
                   96978:     print "\n<br><br>\n";
                   96979: 
                   96980:     print 'building DocType declaration with internal DTD:<br>';
                   96981:     print '<pre>';
                   96982:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   96983:         'http://pear.php.net/dtd/package-1.0', 
                   96984:         '<!ELEMENT additionalInfo (#PCDATA)>'));
                   96985:     print '</pre>';
                   96986:     print "\n<br><br>\n";
                   96987: 
                   96988:     /**
                   96989:      * creating an attribute string
                   96990:      */
                   96991:     $att = array(
                   96992:         'foo'  => 'bar',
                   96993:         'argh' => 'tomato'
                   96994:     );
                   96995: 
                   96996:     print 'converting array to string:<br>';
                   96997:     print XML_Util::attributesToString($att);
                   96998:     print "\n<br><br>\n";
                   96999: 
                   97000: 
                   97001:     /**
                   97002:      * creating an attribute string with linebreaks
                   97003:      */
                   97004:     $att = array(
                   97005:         'foo'  => 'bar',
                   97006:         'argh' => 'tomato'
                   97007:     );
                   97008: 
                   97009:     print 'converting array to string (including line breaks):<br>';
                   97010:     print '<pre>';
                   97011:     print XML_Util::attributesToString($att, true, true);
                   97012:     print '</pre>';
                   97013:     print "\n<br><br>\n";
                   97014: 
                   97015: 
                   97016:     /**
                   97017:      * splitting a qualified tag name
                   97018:      */
                   97019:     print 'splitting qualified tag name:<br>';
                   97020:     print '<pre>';
                   97021:     print_r(XML_Util::splitQualifiedName('xslt:stylesheet'));
                   97022:     print '</pre>';
                   97023:     print "\n<br>\n";
                   97024: 
                   97025: 
                   97026:     /**
                   97027:      * splitting a qualified tag name (no namespace)
                   97028:      */
                   97029:     print 'splitting qualified tag name (no namespace):<br>';
                   97030:     print '<pre>';
                   97031:     print_r(XML_Util::splitQualifiedName('foo'));
                   97032:     print '</pre>';
                   97033:     print "\n<br>\n";
                   97034: 
                   97035:     /**
                   97036:      * splitting a qualified tag name (no namespace, but default namespace specified)
                   97037:      */
                   97038:     print 'splitting qualified tag name '
                   97039:         . '(no namespace, but default namespace specified):<br>';
                   97040:     print '<pre>';
                   97041:     print_r(XML_Util::splitQualifiedName('foo', 'bar'));
                   97042:     print '</pre>';
                   97043:     print "\n<br>\n";
                   97044: 
                   97045:     /**
                   97046:      * verifying XML names
                   97047:      */
                   97048:     print 'verifying \'My private tag\':<br>';
                   97049:     print '<pre>';
                   97050:     print_r(XML_Util::isValidname('My Private Tag'));
                   97051:     print '</pre>';
                   97052:     print "\n<br><br>\n";
                   97053:     
                   97054:     print 'verifying \'-MyTag\':<br>';
                   97055:     print '<pre>';
                   97056:     print_r(XML_Util::isValidname('-MyTag'));
                   97057:     print '</pre>';
                   97058:     print "\n<br><br>\n";
                   97059: 
                   97060:     /**
                   97061:      * creating an XML tag
                   97062:      */
                   97063:     $tag = array(
                   97064:         'namespace'  => 'foo',
                   97065:         'localPart'  => 'bar',
                   97066:         'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   97067:         'content'    => 'I\'m inside the tag'
                   97068:     );
                   97069: 
                   97070:     print 'creating a tag with namespace and local part:<br>';
                   97071:     print htmlentities(XML_Util::createTagFromArray($tag));
                   97072:     print "\n<br><br>\n";
                   97073: 
                   97074:     /**
                   97075:      * creating an XML tag
                   97076:      */
                   97077:     $tag = array(
                   97078:         'qname'        => 'foo:bar',
                   97079:         'namespaceUri' => 'http://foo.com',
                   97080:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   97081:         'content'      => 'I\'m inside the tag'
                   97082:     );
                   97083: 
                   97084:     print 'creating a tag with qualified name and namespaceUri:<br>';
                   97085:     print htmlentities(XML_Util::createTagFromArray($tag));
                   97086:     print "\n<br><br>\n";
                   97087: 
                   97088:     /**
                   97089:      * creating an XML tag
                   97090:      */
                   97091:     $tag = array(
                   97092:         'qname'        => 'bar',
                   97093:         'namespaceUri' => 'http://foo.com',
                   97094:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable')
                   97095:     );
                   97096: 
                   97097:     print 'creating an empty tag without namespace but namespace Uri:<br>';
                   97098:     print htmlentities(XML_Util::createTagFromArray($tag));
                   97099:     print "\n<br><br>\n";
                   97100: 
                   97101:     /**
                   97102:      * creating an XML tag with more namespaces
                   97103:      */
                   97104:     $tag = array(
                   97105:         'namespace'   => 'foo',
                   97106:         'localPart'   => 'bar',
                   97107:         'attributes'  => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   97108:         'content'     => 'I\'m inside the tag',
                   97109:         'namespaces'  => array(
                   97110:             'bar'  => 'http://bar.com',
                   97111:             'pear' => 'http://pear.php.net',
                   97112:         )
                   97113:     );
                   97114: 
                   97115:     print 'creating an XML tag with more namespaces:<br />';
                   97116:     print htmlentities(XML_Util::createTagFromArray($tag));
                   97117:     print "\n<br><br>\n";
                   97118: 
                   97119:     /**
                   97120:      * creating an XML tag with a CData Section
                   97121:      */
                   97122:     $tag = array(
                   97123:         'qname'      => 'foo',
                   97124:         'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   97125:         'content'    => 'I\'m inside the tag'
                   97126:     );
                   97127: 
                   97128:     print 'creating a tag with CData section:<br>';
                   97129:     print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_CDATA_SECTION));
                   97130:     print "\n<br><br>\n";
                   97131: 
                   97132:     /**
                   97133:      * creating an XML tag with a CData Section
                   97134:      */
                   97135:     $tag = array(
                   97136:         'qname'      => 'foo',
                   97137:         'attributes' => array('key' => 'value', 'argh' => 't黷'),
                   97138:         'content'    => 
                   97139:             'Also XHTML-tags can be created '
                   97140:             . 'and HTML entities can be replaced     <>.'
                   97141:     );
                   97142: 
                   97143:     print 'creating a tag with HTML entities:<br>';
                   97144:     print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_ENTITIES_HTML));
                   97145:     print "\n<br><br>\n";
                   97146: 
                   97147:     /**
                   97148:     * creating an XML tag with createTag
                   97149:     */
                   97150:     print 'creating a tag with createTag:<br>';
                   97151:     print htmlentities(XML_Util::createTag('myNs:myTag', 
                   97152:         array('foo' => 'bar'), 
                   97153:         'This is inside the tag', 
                   97154:         'http://www.w3c.org/myNs#'));
                   97155:     print "\n<br><br>\n";
                   97156: 
                   97157:     
                   97158:     /**
                   97159:      * trying to create an XML tag with an array as content
                   97160:      */
                   97161:     $tag = array(
                   97162:         'qname'   => 'bar',
                   97163:         'content' => array('foo' => 'bar')
                   97164:     );
                   97165:     print 'trying to create an XML tag with an array as content:<br>';
                   97166:     print '<pre>';
                   97167:     print_r(XML_Util::createTagFromArray($tag));
                   97168:     print '</pre>';
                   97169:     print "\n<br><br>\n";
                   97170:     
                   97171:     /**
                   97172:      * trying to create an XML tag without a name
                   97173:      */
                   97174:     $tag = array(
                   97175:         'attributes' => array('foo' => 'bar'),
                   97176:     );
                   97177:     print 'trying to create an XML tag without a name:<br>';
                   97178:     print '<pre>';
                   97179:     print_r(XML_Util::createTagFromArray($tag));
                   97180:     print '</pre>';
                   97181:     print "\n<br><br>\n";
                   97182: ?>
                   97183: XML_Util-1.2.1/examples/example2.php100644   1750   1750       11441 11117075466  12467 <?php
                   97184: 
                   97185: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   97186: 
                   97187: /**
                   97188:  * Examples (file #2)
                   97189:  *
                   97190:  * several examples for the methods of XML_Util
                   97191:  * 
                   97192:  * PHP versions 4 and 5
                   97193:  *
                   97194:  * LICENSE:
                   97195:  *
                   97196:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   97197:  * All rights reserved.
                   97198:  *
                   97199:  * Redistribution and use in source and binary forms, with or without
                   97200:  * modification, are permitted provided that the following conditions
                   97201:  * are met:
                   97202:  *
                   97203:  *    * Redistributions of source code must retain the above copyright
                   97204:  *      notice, this list of conditions and the following disclaimer.
                   97205:  *    * Redistributions in binary form must reproduce the above copyright
                   97206:  *      notice, this list of conditions and the following disclaimer in the
                   97207:  *      documentation and/or other materials provided with the distribution.
                   97208:  *    * The name of the author may not be used to endorse or promote products
                   97209:  *      derived from this software without specific prior written permission.
                   97210:  *
                   97211:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   97212:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   97213:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   97214:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   97215:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   97216:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   97217:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   97218:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   97219:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   97220:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   97221:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   97222:  *
                   97223:  * @category   XML
                   97224:  * @package    XML_Util
                   97225:  * @subpackage Examples
                   97226:  * @author     Stephan Schmidt <schst@php.net>
                   97227:  * @copyright  2003-2008 Stephan Schmidt <schst@php.net>
                   97228:  * @license    http://opensource.org/licenses/bsd-license New BSD License
                   97229:  * @version    CVS: $Id: example2.php,v 1.11 2008/05/05 19:03:13 ashnazg Exp $
                   97230:  * @link       http://pear.php.net/package/XML_Util
                   97231:  */
                   97232: 
                   97233:     /**
                   97234:      * set error level
                   97235:      */
                   97236:     error_reporting(E_ALL);
                   97237: 
                   97238:     require_once 'XML/Util.php';
                   97239: 
                   97240:     /**
                   97241:      * creating a start element
                   97242:      */
                   97243:     print 'creating a start element:<br>';
                   97244:     print htmlentities(XML_Util::createStartElement('myNs:myTag', 
                   97245:         array('foo' => 'bar'), 'http://www.w3c.org/myNs#'));
                   97246:     print "\n<br><br>\n";
                   97247: 
                   97248: 
                   97249:     /**
                   97250:      * creating a start element
                   97251:      */
                   97252:     print 'creating a start element:<br>';
                   97253:     print htmlentities(XML_Util::createStartElement('myTag', 
                   97254:         array(), 'http://www.w3c.org/myNs#'));
                   97255:     print "\n<br><br>\n";
                   97256: 
                   97257:     /**
                   97258:      * creating a start element
                   97259:      */
                   97260:     print 'creating a start element:<br>';
                   97261:     print '<pre>';
                   97262:     print htmlentities(XML_Util::createStartElement('myTag', 
                   97263:         array('foo' => 'bar', 'argh' => 'tomato'), 
                   97264:         'http://www.w3c.org/myNs#', true));
                   97265:     print '</pre>';
                   97266:     print "\n<br><br>\n";
                   97267: 
                   97268: 
                   97269:     /**
                   97270:      * creating an end element
                   97271:      */
                   97272:     print 'creating an end element:<br>';
                   97273:     print htmlentities(XML_Util::createEndElement('myNs:myTag'));
                   97274:     print "\n<br><br>\n";
                   97275: 
                   97276:     /**
                   97277:      * creating a CData section
                   97278:      */
                   97279:     print 'creating a CData section:<br>';
                   97280:     print htmlentities(XML_Util::createCDataSection('I am content.'));
                   97281:     print "\n<br><br>\n";
                   97282: 
                   97283:     /**
                   97284:      * creating a comment
                   97285:      */
                   97286:     print 'creating a comment:<br>';
                   97287:     print htmlentities(XML_Util::createComment('I am a comment.'));
                   97288:     print "\n<br><br>\n";
                   97289: 
                   97290:     /**
                   97291:      * creating an XML tag with multiline mode
                   97292:      */
                   97293:     $tag = array(
                   97294:         'qname'        => 'foo:bar',
                   97295:         'namespaceUri' => 'http://foo.com',
                   97296:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   97297:         'content'      => 'I\'m inside the tag & contain dangerous chars'
                   97298:     );
                   97299: 
                   97300:     print 'creating a tag with qualified name and namespaceUri:<br>';
                   97301:     print '<pre>';
                   97302:     print htmlentities(XML_Util::createTagFromArray($tag, 
                   97303:         XML_UTIL_REPLACE_ENTITIES, true));
                   97304:     print '</pre>';
                   97305:     print "\n<br><br>\n";
                   97306: 
                   97307:     /**
                   97308:      * create an attribute string without replacing the entities
                   97309:      */
                   97310:     $atts = array('series' => 'Starsky &amp; Hutch', 'channel' => 'ABC');
                   97311:     print 'creating a attribute string, '
                   97312:         . 'entities in values already had been replaced:<br>';
                   97313:     print htmlentities(XML_Util::attributesToString($atts, 
                   97314:         true, false, false, false, XML_UTIL_ENTITIES_NONE));
                   97315:     print "\n<br><br>\n";
                   97316: 
                   97317:     /**
                   97318:      * using the array-syntax for attributesToString()
                   97319:      */
                   97320:     $atts = array('series' => 'Starsky &amp; Hutch', 'channel' => 'ABC');
                   97321:     print 'using the array-syntax for attributesToString()<br>';
                   97322:     print htmlentities(XML_Util::attributesToString($atts, 
                   97323:         array('entities' => XML_UTIL_ENTITIES_NONE)));
                   97324:     print "\n<br><br>\n";
                   97325: 
                   97326: 
                   97327: ?>
                   97328: XML_Util-1.2.1/tests/AllTests.php100644   1750   1750        7060 11117075466  12013 <?php
                   97329: 
                   97330: /**
                   97331:  * Master Unit Test Suite file for XML_Util
                   97332:  * 
                   97333:  * This top-level test suite file organizes 
                   97334:  * all class test suite files, 
                   97335:  * so that the full suite can be run 
                   97336:  * by PhpUnit or via "pear run-tests -u". 
                   97337:  *
                   97338:  * PHP version 5
                   97339:  *
                   97340:  * @category   XML
                   97341:  * @package    XML_Util
                   97342:  * @subpackage UnitTesting
                   97343:  * @author     Chuck Burgess <ashnazg@php.net>
                   97344:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   97345:  * @version    CVS: $Id: AllTests.php,v 1.5 2008/05/30 11:53:09 ashnazg Exp $
                   97346:  * @link       http://pear.php.net/package/XML_Util
                   97347:  * @since      1.2.0a1
                   97348:  */
                   97349: 
                   97350: 
                   97351: /**
                   97352:  * Check PHP version... PhpUnit v3+ requires at least PHP v5.1.4
                   97353:  */
                   97354: if (version_compare(PHP_VERSION, "5.1.4") < 0) {
                   97355:     // Cannnot run test suites
                   97356:     echo 'Cannot run test suite via PhpUnit... requires at least PHP v5.1.4.' . PHP_EOL;
                   97357:     echo 'Use "pear run-tests -p xml_util" to run the PHPT tests directly.' . PHP_EOL
                   97358: ;
                   97359:     exit(1);
                   97360: }
                   97361: 
                   97362: 
                   97363: /**
                   97364:  * Derive the "main" method name
                   97365:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   97366:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   97367:  */
                   97368: if (!defined('PHPUnit_MAIN_METHOD')) {
                   97369:     define('PHPUnit_MAIN_METHOD', 'XML_Util_AllTests::main');
                   97370: }
                   97371: 
                   97372: 
                   97373: /*
                   97374:  * Files needed by PhpUnit
                   97375:  */
                   97376: require_once 'PHPUnit/Framework.php';
                   97377: require_once 'PHPUnit/TextUI/TestRunner.php';
                   97378: require_once 'PHPUnit/Extensions/PhptTestSuite.php';
                   97379: 
                   97380: /*
                   97381:  * You must add each additional class-level test suite file here
                   97382:  */
                   97383: // there are no PhpUnit test files... only PHPTs.. so nothing is listed here
                   97384: 
                   97385: /**
                   97386:  * directory where PHPT tests are located
                   97387:  */
                   97388: define('XML_UTIL_DIR_PHPT', dirname(__FILE__));
                   97389: 
                   97390: /**
                   97391:  * Master Unit Test Suite class for XML_Util
                   97392:  * 
                   97393:  * This top-level test suite class organizes 
                   97394:  * all class test suite files, 
                   97395:  * so that the full suite can be run 
                   97396:  * by PhpUnit or via "pear run-tests -up xml_util". 
                   97397:  *
                   97398:  * @category   XML
                   97399:  * @package    XML_Util
                   97400:  * @subpackage UnitTesting
                   97401:  * @author     Chuck Burgess <ashnazg@php.net>
                   97402:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   97403:  * @version    Release: @package_version@
                   97404:  * @link       http://pear.php.net/package/XML_Util
                   97405:  * @since      1.2.0a1
                   97406:  */
                   97407: class XML_Util_AllTests
                   97408: {
                   97409: 
                   97410:     /**
                   97411:      * Launches the TextUI test runner
                   97412:      *
                   97413:      * @return void
                   97414:      * @uses PHPUnit_TextUI_TestRunner
                   97415:      */
                   97416:     public static function main()
                   97417:     {
                   97418:         PHPUnit_TextUI_TestRunner::run(self::suite());
                   97419:     }
                   97420: 
                   97421: 
                   97422:     /**
                   97423:      * Adds all class test suites into the master suite
                   97424:      *
                   97425:      * @return PHPUnit_Framework_TestSuite a master test suite
                   97426:      *                                     containing all class test suites
                   97427:      * @uses PHPUnit_Framework_TestSuite
                   97428:      */ 
                   97429:     public static function suite()
                   97430:     {
                   97431:         $suite = new PHPUnit_Framework_TestSuite(
                   97432:             'XML_Util Full Suite of Unit Tests');
                   97433: 
                   97434:         /*
                   97435:          * You must add each additional class-level test suite name here
                   97436:          */
                   97437:         // there are no PhpUnit test files... only PHPTs.. so nothing is listed here
                   97438: 
                   97439:         /*
                   97440:          * add PHPT tests
                   97441:          */
                   97442:         $phpt = new PHPUnit_Extensions_PhptTestSuite(XML_UTIL_DIR_PHPT);
                   97443:         $suite->addTestSuite($phpt);
                   97444: 
                   97445:         return $suite;
                   97446:     }
                   97447: }
                   97448: 
                   97449: /**
                   97450:  * Call the main method if this file is executed directly
                   97451:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   97452:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   97453:  */
                   97454: if (PHPUnit_MAIN_METHOD == 'XML_Util_AllTests::main') {
                   97455:     XML_Util_AllTests::main();
                   97456: }
                   97457: 
                   97458: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   97459: ?>
                   97460: XML_Util-1.2.1/tests/testBasic_apiVersion.phpt100644   1750   1750         701 11117075466  14537 --TEST--
                   97461: XML_Util::apiVersion() basic tests
                   97462: --CREDITS--
                   97463: Chuck Burgess <ashnazg@php.net>
                   97464: # created for v1.2.0a1 2008-05-04
                   97465: --FILE--
                   97466: <?php
                   97467: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97468: echo '=====XML_Util::apiVersion() basic tests=====' . PHP_EOL . PHP_EOL;
                   97469: 
                   97470: echo "TEST:  basic apiVersion() call" . PHP_EOL;
                   97471: echo XML_Util::apiVersion() . PHP_EOL;
                   97472: ?>
                   97473: --EXPECT--
                   97474: =====XML_Util::apiVersion() basic tests=====
                   97475: 
                   97476: TEST:  basic apiVersion() call
                   97477: 1.1
                   97478: XML_Util-1.2.1/tests/testBasic_attributesToString.phpt100644   1750   1750        7057 11117075466  16333 --TEST--
                   97479: XML_Util::attributesToString() basic tests
                   97480: --CREDITS--
                   97481: Chuck Burgess <ashnazg@php.net>
                   97482: # created for v1.2.0a1 2008-05-04
                   97483: --FILE--
                   97484: <?php
                   97485: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97486: echo '=====XML_Util::attributesToString() basic tests=====' . PHP_EOL . PHP_EOL;
                   97487: 
                   97488: $att = array("foo" => "bar", "boo" => "baz");
                   97489: $sort1 = array(
                   97490:     'multiline' => true, 
                   97491:     'indent'    => '----', 
                   97492:     'linebreak' => "^", 
                   97493:     'entities'  => XML_UTIL_ENTITIES_XML, 
                   97494:     'sort'      => true
                   97495: );
                   97496: $sort2 = array(
                   97497:     'multiline' => true, 
                   97498:     'indent'    => '----', 
                   97499:     'linebreak' => "^", 
                   97500:     'entities'  => XML_UTIL_ENTITIES_XML, 
                   97501: );
                   97502: 
                   97503: echo "TEST:  basic usage" . PHP_EOL;
                   97504: echo XML_Util::attributesToString($att) . PHP_EOL . PHP_EOL;
                   97505: 
                   97506: echo "TEST:  explicit \$sort = true" . PHP_EOL;
                   97507: echo XML_Util::attributesToString($att, true) . PHP_EOL . PHP_EOL;
                   97508: 
                   97509: echo "TEST:  explicit \$sort = false" . PHP_EOL;
                   97510: echo XML_Util::attributesToString($att, false) . PHP_EOL . PHP_EOL;
                   97511: 
                   97512: echo "TEST:  explicit \$multiline = false" . PHP_EOL;
                   97513: echo XML_Util::attributesToString($att, true, false) . PHP_EOL . PHP_EOL;
                   97514: 
                   97515: echo "TEST:  explicit \$multiline = true" . PHP_EOL;
                   97516: echo XML_Util::attributesToString($att, true, true) . PHP_EOL . PHP_EOL;
                   97517: 
                   97518: echo "TEST:  explicit \$indent = '        ' (8 spaces)" . PHP_EOL;
                   97519: echo XML_Util::attributesToString($att, true, true, '        ') . PHP_EOL . PHP_EOL;
                   97520: 
                   97521: echo "TEST:  explicit \$linebreak = '^' (some dummy char)" . PHP_EOL;
                   97522: echo XML_Util::attributesToString($att, true, true, '^') . PHP_EOL . PHP_EOL;
                   97523: 
                   97524: echo "TEST:  passing \$sort array of options that includes 'sort'" . PHP_EOL;
                   97525: echo XML_Util::attributesToString($att, $sort1) . PHP_EOL . PHP_EOL;
                   97526: 
                   97527: echo "TEST:  passing \$sort array of options that doesn't include 'sort'" . PHP_EOL;
                   97528: echo XML_Util::attributesToString($att, $sort2) . PHP_EOL . PHP_EOL;
                   97529: 
                   97530: echo "TEST:  do not replace entities" . PHP_EOL;
                   97531: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   97532: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   97533:     XML_UTIL_ENTITIES_NONE) . PHP_EOL . PHP_EOL;
                   97534: 
                   97535: echo "TEST:  replace all XML entities" . PHP_EOL;
                   97536: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   97537: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   97538:     XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   97539: 
                   97540: echo "TEST:  replace only required XML entities" . PHP_EOL;
                   97541: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   97542: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   97543:     XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   97544: 
                   97545: echo "TEST:  replace HTML entities" . PHP_EOL;
                   97546: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   97547: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   97548:     XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   97549: ?>
                   97550: --EXPECT--
                   97551: =====XML_Util::attributesToString() basic tests=====
                   97552: 
                   97553: TEST:  basic usage
                   97554:  boo="baz" foo="bar"
                   97555: 
                   97556: TEST:  explicit $sort = true
                   97557:  boo="baz" foo="bar"
                   97558: 
                   97559: TEST:  explicit $sort = false
                   97560:  foo="bar" boo="baz"
                   97561: 
                   97562: TEST:  explicit $multiline = false
                   97563:  boo="baz" foo="bar"
                   97564: 
                   97565: TEST:  explicit $multiline = true
                   97566:  boo="baz"
                   97567:     foo="bar"
                   97568: 
                   97569: TEST:  explicit $indent = '        ' (8 spaces)
                   97570:  boo="baz"
                   97571:         foo="bar"
                   97572: 
                   97573: TEST:  explicit $linebreak = '^' (some dummy char)
                   97574:  boo="baz"
                   97575: ^foo="bar"
                   97576: 
                   97577: TEST:  passing $sort array of options that includes 'sort'
                   97578:  boo="baz"
                   97579: ----foo="bar"
                   97580: 
                   97581: TEST:  passing $sort array of options that doesn't include 'sort'
                   97582:  boo="baz"
                   97583: ----foo="bar"
                   97584: 
                   97585: TEST:  do not replace entities
                   97586:  boo="b><z" foo="b@&r"
                   97587: 
                   97588: TEST:  replace all XML entities
                   97589:  boo="b&gt;&lt;z" foo="b@&amp;r"
                   97590: 
                   97591: TEST:  replace only required XML entities
                   97592:  boo="b>&lt;z" foo="b@&amp;r"
                   97593: 
                   97594: TEST:  replace HTML entities
                   97595:  boo="b&gt;&lt;z" foo="b@&amp;r"
                   97596: XML_Util-1.2.1/tests/testBasic_collapseEmptyTags.phpt100644   1750   1750        3403 11117075466  16102 --TEST--
                   97597: XML_Util::collapseEmptyTags() basic tests
                   97598: --CREDITS--
                   97599: Chuck Burgess <ashnazg@php.net>
                   97600: # created for v1.2.0a1 2008-05-04
                   97601: --FILE--
                   97602: <?php
                   97603: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97604: echo '=====XML_Util::collapseEmptyTags() basic tests=====' . PHP_EOL . PHP_EOL;
                   97605: 
                   97606: $emptyTag = "<foo></foo>";
                   97607: $otherTag = "<bar>baz</bar>";
                   97608: $xhtmlTag = "<b></b>";
                   97609: 
                   97610: echo "TEST:  basic usage" . PHP_EOL;
                   97611: echo XML_Util::collapseEmptyTags($emptyTag) . PHP_EOL . PHP_EOL;
                   97612: 
                   97613: echo "TEST:  basic usage alongside non-empty tag" . PHP_EOL;
                   97614: echo XML_Util::collapseEmptyTags($emptyTag . $otherTag) . PHP_EOL . PHP_EOL;
                   97615: 
                   97616: echo "TEST:  one empty tag, with COLLAPSE_ALL set" . PHP_EOL;
                   97617: echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL;
                   97618: 
                   97619: echo "TEST:  one empty tag alongside non-empty tag, with COLLAPSE_ALL set" . PHP_EOL;
                   97620: echo XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL;
                   97621: 
                   97622: echo "TEST:  one empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL;
                   97623: echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL;
                   97624: 
                   97625: echo "TEST:  one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL;
                   97626: echo XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL;
                   97627: ?>
                   97628: --EXPECT--
                   97629: =====XML_Util::collapseEmptyTags() basic tests=====
                   97630: 
                   97631: TEST:  basic usage
                   97632: <foo />
                   97633: 
                   97634: TEST:  basic usage alongside non-empty tag
                   97635: <foo /><bar>baz</bar>
                   97636: 
                   97637: TEST:  one empty tag, with COLLAPSE_ALL set
                   97638: <foo />
                   97639: 
                   97640: TEST:  one empty tag alongside non-empty tag, with COLLAPSE_ALL set
                   97641: <foo /><bar>baz</bar>
                   97642: 
                   97643: TEST:  one empty tag, with COLLAPSE_XHTML_ONLY set
                   97644: <foo></foo>
                   97645: 
                   97646: TEST:  one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set
                   97647: <foo></foo><b></b><bar>baz</bar>
                   97648: XML_Util-1.2.1/tests/testBasic_createCDataSection.phpt100644   1750   1750         756 11117075466  16117 --TEST--
                   97649: XML_Util::createCDataSection() basic tests
                   97650: --CREDITS--
                   97651: Chuck Burgess <ashnazg@php.net>
                   97652: # created for v1.2.0a1 2008-05-04
                   97653: --FILE--
                   97654: <?php
                   97655: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97656: echo '=====XML_Util::createCDataSection() basic tests=====' . PHP_EOL . PHP_EOL;
                   97657: 
                   97658: echo "TEST:  basic usage" . PHP_EOL;
                   97659: echo XML_Util::createCDataSection("I am content.") . PHP_EOL;
                   97660: ?>
                   97661: --EXPECT--
                   97662: =====XML_Util::createCDataSection() basic tests=====
                   97663: 
                   97664: TEST:  basic usage
                   97665: <![CDATA[I am content.]]>
                   97666: XML_Util-1.2.1/tests/testBasic_createComment.phpt100644   1750   1750         727 11117075466  15216 --TEST--
                   97667: XML_Util::createComment() basic tests
                   97668: --CREDITS--
                   97669: Chuck Burgess <ashnazg@php.net>
                   97670: # created for v1.2.0a1 2008-05-04
                   97671: --FILE--
                   97672: <?php
                   97673: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97674: echo '=====XML_Util::createComment() basic tests=====' . PHP_EOL . PHP_EOL;
                   97675: 
                   97676: echo "TEST:  basic usage" . PHP_EOL;
                   97677: echo XML_Util::createComment("I am comment.") . PHP_EOL;
                   97678: ?>
                   97679: --EXPECT--
                   97680: =====XML_Util::createComment() basic tests=====
                   97681: 
                   97682: TEST:  basic usage
                   97683: <!-- I am comment. -->
                   97684: XML_Util-1.2.1/tests/testBasic_createEndElement.phpt100644   1750   1750        1270 11117075466  15646 --TEST--
                   97685: XML_Util::createEndElement() basic tests
                   97686: --CREDITS--
                   97687: Chuck Burgess <ashnazg@php.net>
                   97688: # created for v1.2.0a1 2008-05-04
                   97689: --FILE--
                   97690: <?php
                   97691: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97692: echo '=====XML_Util::createEndElement() basic tests=====' . PHP_EOL . PHP_EOL;
                   97693: 
                   97694: echo "TEST:  basic usage (myTag)" . PHP_EOL;
                   97695: echo XML_Util::createEndElement("myTag") . PHP_EOL . PHP_EOL;
                   97696: 
                   97697: echo "TEST:  basic usage with a namespaced tag (myNs:myTag)" . PHP_EOL;
                   97698: echo XML_Util::createEndElement("myNs:myTag") . PHP_EOL . PHP_EOL;
                   97699: ?>
                   97700: --EXPECT--
                   97701: =====XML_Util::createEndElement() basic tests=====
                   97702: 
                   97703: TEST:  basic usage (myTag)
                   97704: </myTag>
                   97705: 
                   97706: TEST:  basic usage with a namespaced tag (myNs:myTag)
                   97707: </myNs:myTag>
                   97708: XML_Util-1.2.1/tests/testBasic_createStartElement.phpt100644   1750   1750        7275 11117075466  16250 --TEST--
                   97709: XML_Util::createStartElement() basic tests
                   97710: --CREDITS--
                   97711: Chuck Burgess <ashnazg@php.net>
                   97712: # created for v1.2.0a1 2008-05-04
                   97713: --FILE--
                   97714: <?php
                   97715: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97716: echo '=====XML_Util::createStartElement() basic tests=====' . PHP_EOL . PHP_EOL;
                   97717: 
                   97718: echo "TEST:  tag only" . PHP_EOL;
                   97719: echo XML_Util::createStartElement(
                   97720:     "myNs:myTag"
                   97721: ) . PHP_EOL . PHP_EOL;
                   97722: 
                   97723: echo "TEST:  tag with attributes" . PHP_EOL;
                   97724: echo XML_Util::createStartElement(
                   97725:     "myNs:myTag", 
                   97726:     array("foo" => "bar")
                   97727: ) . PHP_EOL . PHP_EOL;
                   97728: 
                   97729: echo "TEST:  tag only, passing '' as attribute arg" . PHP_EOL;
                   97730: echo XML_Util::createStartElement(
                   97731:     'myNs:myTag',
                   97732:     ''
                   97733: ) . PHP_EOL . PHP_EOL;
                   97734: 
                   97735: echo "TEST:  tag with attributes and namespace" . PHP_EOL;
                   97736: echo XML_Util::createStartElement(
                   97737:     "myNs:myTag", 
                   97738:     array("foo" => "bar"),
                   97739:     "http://www.w3c.org/myNs#"
                   97740: ) . PHP_EOL . PHP_EOL;
                   97741: 
                   97742: echo "TEST:  tag with empty attributes, whose namespaceUri is not a full namespace" . PHP_EOL;
                   97743: echo XML_Util::createStartElement(
                   97744:     'myTag',
                   97745:     '',
                   97746:     'foo'
                   97747: ) . PHP_EOL . PHP_EOL;
                   97748: 
                   97749: echo "TEST:  tag with attributes, namespace, and multiline = true" . PHP_EOL;
                   97750: echo XML_Util::createStartElement(
                   97751:     "myNs:myTag", 
                   97752:     array("foo" => "bar"),
                   97753:     "http://www.w3c.org/myNs#",
                   97754:     true
                   97755: ) . PHP_EOL . PHP_EOL;
                   97756: 
                   97757: echo "TEST:  tag with attributes, namespace, multiline = true, and indent = (2 spaces only)" . PHP_EOL;
                   97758: echo XML_Util::createStartElement(
                   97759:     "myNs:myTag", 
                   97760:     array("foo" => "bar"),
                   97761:     "http://www.w3c.org/myNs#",
                   97762:     true,
                   97763:     '  '
                   97764: ) . PHP_EOL . PHP_EOL;
                   97765: 
                   97766: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^'" . PHP_EOL;
                   97767: echo XML_Util::createStartElement(
                   97768:     "myNs:myTag", 
                   97769:     array("foo" => "bar"),
                   97770:     "http://www.w3c.org/myNs#",
                   97771:     true,
                   97772:     '  ',
                   97773:     '^'
                   97774: ) . PHP_EOL . PHP_EOL;
                   97775: 
                   97776: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true" . PHP_EOL;
                   97777: echo XML_Util::createStartElement(
                   97778:     "myNs:myTag", 
                   97779:     array("foo" => "bar", "boo" => "baz"),
                   97780:     "http://www.w3c.org/myNs#",
                   97781:     true,
                   97782:     '  ',
                   97783:     '^',
                   97784:     true
                   97785: ) . PHP_EOL . PHP_EOL;
                   97786: 
                   97787: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false" . PHP_EOL;
                   97788: echo XML_Util::createStartElement(
                   97789:     "myNs:myTag", 
                   97790:     array("foo" => "bar", "boo" => "baz"),
                   97791:     "http://www.w3c.org/myNs#",
                   97792:     true,
                   97793:     '  ',
                   97794:     '^',
                   97795:     false
                   97796: ) . PHP_EOL . PHP_EOL;
                   97797: ?>
                   97798: --EXPECT--
                   97799: =====XML_Util::createStartElement() basic tests=====
                   97800: 
                   97801: TEST:  tag only
                   97802: <myNs:myTag>
                   97803: 
                   97804: TEST:  tag with attributes
                   97805: <myNs:myTag foo="bar">
                   97806: 
                   97807: TEST:  tag only, passing '' as attribute arg
                   97808: <myNs:myTag>
                   97809: 
                   97810: TEST:  tag with attributes and namespace
                   97811: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">
                   97812: 
                   97813: TEST:  tag with empty attributes, whose namespaceUri is not a full namespace
                   97814: <myTag xmlns="foo">
                   97815: 
                   97816: TEST:  tag with attributes, namespace, and multiline = true
                   97817: <myNs:myTag foo="bar"
                   97818:             xmlns:myNs="http://www.w3c.org/myNs#">
                   97819: 
                   97820: TEST:  tag with attributes, namespace, multiline = true, and indent = (2 spaces only)
                   97821: <myNs:myTag foo="bar"
                   97822:   xmlns:myNs="http://www.w3c.org/myNs#">
                   97823: 
                   97824: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^'
                   97825: <myNs:myTag foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   97826: 
                   97827: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true
                   97828: <myNs:myTag boo="baz"^  foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   97829: 
                   97830: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false
                   97831: <myNs:myTag foo="bar"^  boo="baz"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   97832: XML_Util-1.2.1/tests/testBasic_createTag.phpt100644   1750   1750       13434 11117075466  14366 --TEST--
                   97833: XML_Util::createTag() basic tests
                   97834: --CREDITS--
                   97835: Chuck Burgess <ashnazg@php.net>
                   97836: # created for v1.2.0a1 2008-05-04
                   97837: --FILE--
                   97838: <?php
                   97839: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97840: echo '=====XML_Util::createTag() basic tests=====' . PHP_EOL . PHP_EOL;
                   97841: 
                   97842: echo "TEST:  tag with attribute" . PHP_EOL;
                   97843: echo XML_Util::createTag(
                   97844:     "myNs:myTag", 
                   97845:     array("foo" => "bar")
                   97846: ) . PHP_EOL . PHP_EOL;
                   97847: 
                   97848: echo "TEST:  tag with attribute and content" . PHP_EOL;
                   97849: echo XML_Util::createTag(
                   97850:     "myNs:myTag", 
                   97851:     array("foo" => "bar"), 
                   97852:     "This is inside the tag"
                   97853: ) . PHP_EOL . PHP_EOL;
                   97854: 
                   97855: echo "TEST:  tag with attribute, content, and namespace" . PHP_EOL;
                   97856: echo XML_Util::createTag(
                   97857:     "myNs:myTag", 
                   97858:     array("foo" => "bar"), 
                   97859:     "This is inside the tag",
                   97860:     "http://www.w3c.org/myNs#"
                   97861: ) . PHP_EOL . PHP_EOL;
                   97862: 
                   97863: echo "TEST:  tag with attribute, content, namespace, and REPLACE_ENTITIES" . PHP_EOL;
                   97864: echo XML_Util::createTag(
                   97865:     "myNs:myTag", 
                   97866:     array("foo" => "bar"), 
                   97867:     "This is inside the tag and has < & @ > in it",
                   97868:     "http://www.w3c.org/myNs#",
                   97869:     XML_UTIL_REPLACE_ENTITIES
                   97870: ) . PHP_EOL . PHP_EOL;
                   97871: 
                   97872: echo "TEST:  tag with attribute, content, namespace, and CDATA_SECTION" . PHP_EOL;
                   97873: echo XML_Util::createTag(
                   97874:     "myNs:myTag", 
                   97875:     array("foo" => "bar"), 
                   97876:     "This is inside the tag and has < & @ > in it",
                   97877:     "http://www.w3c.org/myNs#",
                   97878:     XML_UTIL_CDATA_SECTION
                   97879: ) . PHP_EOL . PHP_EOL;
                   97880: 
                   97881: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false" . PHP_EOL;
                   97882: echo XML_Util::createTag(
                   97883:     "myNs:myTag", 
                   97884:     array("foo" => "bar"), 
                   97885:     "This is inside the tag and has < & @ > in it",
                   97886:     "http://www.w3c.org/myNs#",
                   97887:     XML_UTIL_REPLACE_ENTITIES,
                   97888:     false
                   97889: ) . PHP_EOL . PHP_EOL;
                   97890: 
                   97891: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true" . PHP_EOL;
                   97892: echo XML_Util::createTag(
                   97893:     "myNs:myTag", 
                   97894:     array("foo" => "bar"), 
                   97895:     "This is inside the tag and has < & @ > in it",
                   97896:     "http://www.w3c.org/myNs#",
                   97897:     XML_UTIL_REPLACE_ENTITIES,
                   97898:     true
                   97899: ) . PHP_EOL . PHP_EOL;
                   97900: 
                   97901: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL;
                   97902: echo XML_Util::createTag(
                   97903:     "myNs:myTag", 
                   97904:     array("foo" => "bar"), 
                   97905:     "This is inside the tag and has < & @ > in it",
                   97906:     "http://www.w3c.org/myNs#",
                   97907:     XML_UTIL_REPLACE_ENTITIES,
                   97908:     true,
                   97909:     '  '
                   97910: ) . PHP_EOL . PHP_EOL;
                   97911: 
                   97912: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL;
                   97913: echo XML_Util::createTag(
                   97914:     "myNs:myTag", 
                   97915:     array("foo" => "bar"), 
                   97916:     "This is inside the tag and has < & @ > in it",
                   97917:     "http://www.w3c.org/myNs#",
                   97918:     XML_UTIL_REPLACE_ENTITIES,
                   97919:     true,
                   97920:     '  ',
                   97921:     '^'
                   97922: ) . PHP_EOL . PHP_EOL;
                   97923: 
                   97924: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true" . PHP_EOL;
                   97925: echo XML_Util::createTag(
                   97926:     "myNs:myTag", 
                   97927:     array("foo" => "bar", "boo" => "baz"), 
                   97928:     "This is inside the tag and has < & @ > in it",
                   97929:     "http://www.w3c.org/myNs#",
                   97930:     XML_UTIL_REPLACE_ENTITIES,
                   97931:     true,
                   97932:     '  ',
                   97933:     '^',
                   97934:     true
                   97935: ) . PHP_EOL . PHP_EOL;
                   97936: 
                   97937: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false" . PHP_EOL;
                   97938: echo XML_Util::createTag(
                   97939:     "myNs:myTag", 
                   97940:     array("foo" => "bar", "boo" => "baz"), 
                   97941:     "This is inside the tag and has < & @ > in it",
                   97942:     "http://www.w3c.org/myNs#",
                   97943:     XML_UTIL_REPLACE_ENTITIES,
                   97944:     true,
                   97945:     '  ',
                   97946:     '^',
                   97947:     false
                   97948: ) . PHP_EOL . PHP_EOL;
                   97949: ?>
                   97950: --EXPECT--
                   97951: =====XML_Util::createTag() basic tests=====
                   97952: 
                   97953: TEST:  tag with attribute
                   97954: <myNs:myTag foo="bar" />
                   97955: 
                   97956: TEST:  tag with attribute and content
                   97957: <myNs:myTag foo="bar">This is inside the tag</myNs:myTag>
                   97958: 
                   97959: TEST:  tag with attribute, content, and namespace
                   97960: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag</myNs:myTag>
                   97961: 
                   97962: TEST:  tag with attribute, content, namespace, and REPLACE_ENTITIES
                   97963: <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>
                   97964: 
                   97965: TEST:  tag with attribute, content, namespace, and CDATA_SECTION
                   97966: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#"><![CDATA[This is inside the tag and has < & @ > in it]]></myNs:myTag>
                   97967: 
                   97968: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false
                   97969: <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>
                   97970: 
                   97971: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true
                   97972: <myNs:myTag foo="bar"
                   97973:             xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   97974: 
                   97975: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)
                   97976: <myNs:myTag foo="bar"
                   97977:   xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   97978: 
                   97979: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'
                   97980: <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>
                   97981: 
                   97982: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true
                   97983: <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>
                   97984: 
                   97985: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false
                   97986: <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>
                   97987: XML_Util-1.2.1/tests/testBasic_createTagFromArray.phpt100644   1750   1750       22131 11117075466  16203 --TEST--
                   97988: XML_Util::createTagFromArray() basic tests
                   97989: --CREDITS--
                   97990: Chuck Burgess <ashnazg@php.net>
                   97991: # created for v1.2.0a1 2008-05-04
                   97992: --FILE--
                   97993: <?php
                   97994: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   97995: echo '=====XML_Util::createTagFromArray() basic tests=====' . PHP_EOL . PHP_EOL;
                   97996: 
                   97997: $bad = array(
                   97998:     "foo" => "bar",
                   97999: );
                   98000: $tag1 = array(
                   98001:     "qname"        => "foo:bar",
                   98002: );
                   98003: $tag2 = array(
                   98004:     "qname"        => "foo:bar",
                   98005:     "namespaceUri" => "http://foo.com",
                   98006: );
                   98007: $tag3 = array(
                   98008:     "qname"        => "foo:bar",
                   98009:     "namespaceUri" => "http://foo.com",
                   98010:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   98011: );
                   98012: $tag4 = array(
                   98013:     "qname"        => "foo:bar",
                   98014:     "namespaceUri" => "http://foo.com",
                   98015:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   98016:     "content"      => "I'm inside the tag",
                   98017: );
                   98018: $tag5 = array(
                   98019:     "qname"        => "foo:bar",
                   98020:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   98021:     "content"      => "I'm inside the tag",
                   98022: );
                   98023: $tag6 = array(
                   98024:     "qname"        => "foo:bar",
                   98025:     "namespaceUri" => "http://foo.com",
                   98026:     "content"      => "I'm inside the tag",
                   98027: );
                   98028: $tag7 = array(
                   98029:     "namespaceUri" => "http://foo.com",
                   98030:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   98031:     "content"      => "I'm inside the tag",
                   98032: );
                   98033: 
                   98034: $tag8 = array(
                   98035:     'content'      => array('foo', 'bar')
                   98036: );
                   98037: 
                   98038: $tag9 = array(
                   98039:     'qname'        => 'foo:bar',
                   98040:     'namespaces'   => array('ns1' => 'uri1', 'ns2' => 'uri2')
                   98041: );
                   98042: 
                   98043: $tag10 = array(
                   98044:     'namespace'    => 'http://foo.org',
                   98045:     'localPart'    => 'bar'
                   98046: );
                   98047: 
                   98048: $tag11 = array(
                   98049:     'namespace'    => '',
                   98050:     'localPart'    => 'bar'
                   98051: );
                   98052: 
                   98053: $tag12 = array(
                   98054:     'localPart'    => 'foo',
                   98055:     'namespaceUri' => 'http://bar.org'
                   98056: );
                   98057: 
                   98058: echo "TEST:  basic usage with an invalid array" . PHP_EOL;
                   98059: echo XML_Util::createTagFromArray($bad) . PHP_EOL . PHP_EOL;
                   98060: 
                   98061: echo "TEST:  basic usage with a valid array (qname only)" . PHP_EOL;
                   98062: echo XML_Util::createTagFromArray($tag1) . PHP_EOL . PHP_EOL;
                   98063: 
                   98064: echo "TEST:  basic usage with a valid array (qname and namespaceUri)" . PHP_EOL;
                   98065: echo XML_Util::createTagFromArray($tag2) . PHP_EOL . PHP_EOL;
                   98066: 
                   98067: echo "TEST:  basic usage with a valid array (qname, namespaceUri, and attributes)" . PHP_EOL;
                   98068: echo XML_Util::createTagFromArray($tag3) . PHP_EOL . PHP_EOL;
                   98069: 
                   98070: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content)" . PHP_EOL;
                   98071: echo XML_Util::createTagFromArray($tag4) . PHP_EOL . PHP_EOL;
                   98072: 
                   98073: echo "TEST:  basic usage with a valid array (qname, attributes, and content)" . PHP_EOL;
                   98074: echo XML_Util::createTagFromArray($tag5) . PHP_EOL . PHP_EOL;
                   98075: 
                   98076: echo "TEST:  basic usage with a valid array (qname, namespaceUri, and content)" . PHP_EOL;
                   98077: echo XML_Util::createTagFromArray($tag6) . PHP_EOL . PHP_EOL;
                   98078: 
                   98079: echo "TEST:  basic usage with a valid array (namespaceUri, attributes, and content)" . PHP_EOL;
                   98080: echo XML_Util::createTagFromArray($tag7) . PHP_EOL . PHP_EOL;
                   98081: 
                   98082: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES" . PHP_EOL;
                   98083: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES) . PHP_EOL . PHP_EOL;
                   98084: 
                   98085: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE" . PHP_EOL;
                   98086: echo XML_Util::createTagFromArray($tag4, XML_UTIL_ENTITIES_NONE) . PHP_EOL . PHP_EOL;
                   98087: 
                   98088: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false" . PHP_EOL;
                   98089: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, false) . PHP_EOL . PHP_EOL;
                   98090: 
                   98091: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true" . PHP_EOL;
                   98092: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true) . PHP_EOL . PHP_EOL;
                   98093: 
                   98094: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL;
                   98095: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ') . PHP_EOL . PHP_EOL;
                   98096: 
                   98097: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL;
                   98098: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^') . PHP_EOL . PHP_EOL;
                   98099: 
                   98100: 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;
                   98101: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^', true) . PHP_EOL . PHP_EOL;
                   98102: 
                   98103: 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;
                   98104: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^', false) . PHP_EOL . PHP_EOL;
                   98105: 
                   98106: echo 'TEST:  cause a non-scalar error on the content tag' . PHP_EOL;
                   98107: echo XML_Util::createTagFromArray($tag8) . PHP_EOL . PHP_EOL;
                   98108: 
                   98109: echo 'TEST:  handle an array of namespaces being passed' . PHP_EOL;
                   98110: echo XML_Util::createTagFromArray($tag9) . PHP_EOL . PHP_EOL;
                   98111: 
                   98112: echo 'TEST:  qname is derived from namespace + localPart' . PHP_EOL;
                   98113: echo XML_Util::createTagFromArray($tag10) . PHP_EOL . PHP_EOL;
                   98114: 
                   98115: echo 'TEST:  qname is derived from localPart only' . PHP_EOL;
                   98116: echo XML_Util::createTagFromArray($tag11) . PHP_EOL . PHP_EOL;
                   98117: 
                   98118: echo 'TEST:  namespaceUri is given, but namespace is not' . PHP_EOL;
                   98119: echo XML_Util::createTagFromArray($tag12) . PHP_EOL . PHP_EOL;
                   98120: ?>
                   98121: --EXPECT--
                   98122: =====XML_Util::createTagFromArray() basic tests=====
                   98123: 
                   98124: TEST:  basic usage with an invalid array
                   98125: You must either supply a qualified name (qname) or local tag name (localPart).
                   98126: 
                   98127: TEST:  basic usage with a valid array (qname only)
                   98128: <foo:bar />
                   98129: 
                   98130: TEST:  basic usage with a valid array (qname and namespaceUri)
                   98131: <foo:bar xmlns:foo="http://foo.com" />
                   98132: 
                   98133: TEST:  basic usage with a valid array (qname, namespaceUri, and attributes)
                   98134: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com" />
                   98135: 
                   98136: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content)
                   98137: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98138: 
                   98139: TEST:  basic usage with a valid array (qname, attributes, and content)
                   98140: <foo:bar argh="fruit&amp;vegetable" key="value">I&apos;m inside the tag</foo:bar>
                   98141: 
                   98142: TEST:  basic usage with a valid array (qname, namespaceUri, and content)
                   98143: <foo:bar xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98144: 
                   98145: TEST:  basic usage with a valid array (namespaceUri, attributes, and content)
                   98146: You must either supply a qualified name (qname) or local tag name (localPart).
                   98147: 
                   98148: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES
                   98149: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98150: 
                   98151: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE
                   98152: <foo:bar argh="fruit&vegetable" key="value" xmlns:foo="http://foo.com">I'm inside the tag</foo:bar>
                   98153: 
                   98154: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false
                   98155: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98156: 
                   98157: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true
                   98158: <foo:bar argh="fruit&amp;vegetable"
                   98159:          key="value"
                   98160:          xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98161: 
                   98162: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)
                   98163: <foo:bar argh="fruit&amp;vegetable"
                   98164:   key="value"
                   98165:   xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98166: 
                   98167: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'
                   98168: <foo:bar argh="fruit&amp;vegetable"^  key="value"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98169: 
                   98170: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true
                   98171: <foo:bar argh="fruit&amp;vegetable"^  key="value"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98172: 
                   98173: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false
                   98174: <foo:bar key="value"^  argh="fruit&amp;vegetable"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   98175: 
                   98176: TEST:  cause a non-scalar error on the content tag
                   98177: Supplied non-scalar value as tag content
                   98178: 
                   98179: TEST:  handle an array of namespaces being passed
                   98180: <foo:bar xmlns:ns1="uri1" xmlns:ns2="uri2" />
                   98181: 
                   98182: TEST:  qname is derived from namespace + localPart
                   98183: <http://foo.org:bar />
                   98184: 
                   98185: TEST:  qname is derived from localPart only
                   98186: <bar />
                   98187: 
                   98188: TEST:  namespaceUri is given, but namespace is not
                   98189: <foo xmlns="http://bar.org" />
                   98190: XML_Util-1.2.1/tests/testBasic_getDocTypeDeclaration.phpt100644   1750   1750        2754 11117075466  16667 --TEST--
                   98191: XML_Util::getDocTypeDeclaration() basic tests
                   98192: --CREDITS--
                   98193: Chuck Burgess <ashnazg@php.net>
                   98194: # created for v1.2.0a1 2008-05-04
                   98195: --FILE--
                   98196: <?php
                   98197: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98198: echo '=====XML_Util::getDocTypeDeclaration() basic tests=====' . PHP_EOL . PHP_EOL;
                   98199: 
                   98200: echo "TEST:  using root only" . PHP_EOL;
                   98201: echo XML_Util::getDocTypeDeclaration("rootTag") . PHP_EOL . PHP_EOL;
                   98202: 
                   98203: echo "TEST:  using root and a string URI" . PHP_EOL;
                   98204: echo XML_Util::getDocTypeDeclaration("rootTag", "myDocType.dtd") . PHP_EOL . PHP_EOL;
                   98205: 
                   98206: $uri = array(
                   98207:     'uri' => 'http://pear.php.net/dtd/package-1.0',
                   98208:     'id' => '-//PHP//PEAR/DTD PACKAGE 0.1'
                   98209: );
                   98210: $dtdEntry = '<!ELEMENT additionalInfo (#PCDATA)>';
                   98211: 
                   98212: echo "TEST:  using root and an array URI" . PHP_EOL;
                   98213: echo XML_Util::getDocTypeDeclaration("rootTag", $uri) . PHP_EOL . PHP_EOL;
                   98214: 
                   98215: echo "TEST:  using root and an array URI and an internal DTD entry" . PHP_EOL;
                   98216: echo XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry) . PHP_EOL . PHP_EOL;
                   98217: ?>
                   98218: --EXPECT--
                   98219: =====XML_Util::getDocTypeDeclaration() basic tests=====
                   98220: 
                   98221: TEST:  using root only
                   98222: <!DOCTYPE rootTag>
                   98223: 
                   98224: TEST:  using root and a string URI
                   98225: <!DOCTYPE rootTag SYSTEM "myDocType.dtd">
                   98226: 
                   98227: TEST:  using root and an array URI
                   98228: <!DOCTYPE rootTag PUBLIC "-//PHP//PEAR/DTD PACKAGE 0.1" "http://pear.php.net/dtd/package-1.0">
                   98229: 
                   98230: TEST:  using root and an array URI and an internal DTD entry
                   98231: <!DOCTYPE rootTag PUBLIC "-//PHP//PEAR/DTD PACKAGE 0.1" "http://pear.php.net/dtd/package-1.0" [
                   98232: <!ELEMENT additionalInfo (#PCDATA)>
                   98233: ]>
                   98234: XML_Util-1.2.1/tests/testBasic_getXmlDeclaration.phpt100644   1750   1750        2217 11117075466  16052 --TEST--
                   98235: XML_Util::getXmlDeclaration() basic tests
                   98236: --CREDITS--
                   98237: Chuck Burgess <ashnazg@php.net>
                   98238: # created for v1.2.0a1 2008-05-04
                   98239: --FILE--
                   98240: <?php
                   98241: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98242: echo '=====XML_Util::getXmlDeclaration() basic tests=====' . PHP_EOL . PHP_EOL;
                   98243: 
                   98244: echo "TEST:  using version only" . PHP_EOL;
                   98245: echo XML_Util::getXMLDeclaration("1.0") . PHP_EOL . PHP_EOL;
                   98246: 
                   98247: echo "TEST:  using version and encoding" . PHP_EOL;
                   98248: echo XML_Util::getXMLDeclaration("1.0", "UTF-8") . PHP_EOL . PHP_EOL;
                   98249: 
                   98250: echo "TEST:  using version, encoding, and standalone flag" . PHP_EOL;
                   98251: echo XML_Util::getXMLDeclaration("1.0", "UTF-8", true) . PHP_EOL . PHP_EOL;
                   98252: 
                   98253: echo "TEST:  using version and standalone flag" . PHP_EOL;
                   98254: echo XML_Util::getXMLDeclaration("1.0", null, true) . PHP_EOL . PHP_EOL;
                   98255: ?>
                   98256: --EXPECT--
                   98257: =====XML_Util::getXmlDeclaration() basic tests=====
                   98258: 
                   98259: TEST:  using version only
                   98260: <?xml version="1.0"?>
                   98261: 
                   98262: TEST:  using version and encoding
                   98263: <?xml version="1.0" encoding="UTF-8"?>
                   98264: 
                   98265: TEST:  using version, encoding, and standalone flag
                   98266: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                   98267: 
                   98268: TEST:  using version and standalone flag
                   98269: <?xml version="1.0" standalone="yes"?>
                   98270: XML_Util-1.2.1/tests/testBasic_isValidName.phpt100644   1750   1750        2602 11117075466  14636 --TEST--
                   98271: XML_Util::isValidName() basic tests
                   98272: --CREDITS--
                   98273: Chuck Burgess <ashnazg@php.net>
                   98274: # created for v1.2.0a1 2008-05-04
                   98275: --FILE--
                   98276: <?php
                   98277: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98278: echo '=====XML_Util::isValidName() basic tests=====' . PHP_EOL . PHP_EOL;
                   98279: 
                   98280: echo "TEST:  valid tag" . PHP_EOL;
                   98281: $result = XML_Util::isValidName("alpha-x_y_z.123");
                   98282: if (is_a($result, 'PEAR_Error')) {
                   98283:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   98284: } else {
                   98285:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   98286: }
                   98287: 
                   98288: echo "TEST:  invalid tag" . PHP_EOL;
                   98289: $result = XML_Util::isValidName("invalidTag?");
                   98290: if (is_a($result, 'PEAR_Error')) {
                   98291:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   98292: } else {
                   98293:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   98294: }
                   98295: 
                   98296: echo "TEST:  invalid tag that doesn't start with a letter" . PHP_EOL;
                   98297: $result = XML_Util::isValidName("1234five");
                   98298: if (is_a($result, 'PEAR_Error')) {
                   98299:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   98300: } else {
                   98301:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   98302: }
                   98303: 
                   98304: ?>
                   98305: --EXPECT--
                   98306: =====XML_Util::isValidName() basic tests=====
                   98307: 
                   98308: TEST:  valid tag
                   98309: Valid XML name.
                   98310: 
                   98311: TEST:  invalid tag
                   98312: Invalid XML name: XML names may only contain alphanumeric chars, period, hyphen, colon and underscores
                   98313: 
                   98314: TEST:  invalid tag that doesn't start with a letter
                   98315: Invalid XML name: XML names may only start with letter or underscore
                   98316: XML_Util-1.2.1/tests/testBasic_raiseError.phpt100644   1750   1750         766 11117075466  14550 --TEST--
                   98317: XML_Util::raiseError() basic tests
                   98318: --CREDITS--
                   98319: Chuck Burgess <ashnazg@php.net>
                   98320: # created for v1.2.0a1 2008-05-04
                   98321: --FILE--
                   98322: <?php
                   98323: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98324: echo '=====XML_Util::raiseError() basic tests=====' . PHP_EOL . PHP_EOL;
                   98325: 
                   98326: $error = XML_Util::raiseError("I am an error", 12345);
                   98327: if (is_a($error, 'PEAR_Error')) {
                   98328:     print "PEAR Error: " . $error->getMessage() . PHP_EOL;
                   98329: }
                   98330: ?>
                   98331: --EXPECT--
                   98332: =====XML_Util::raiseError() basic tests=====
                   98333: 
                   98334: PEAR Error: I am an error
                   98335: XML_Util-1.2.1/tests/testBasic_replaceEntities.phpt100644   1750   1750        6260 11117075466  15566 --TEST--
                   98336: XML_Util::replaceEntities() basic tests
                   98337: --CREDITS--
                   98338: Chuck Burgess <ashnazg@php.net>
                   98339: # created for v1.2.0a1 2008-05-04
                   98340: --FILE--
                   98341: <?php
                   98342: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98343: echo '=====XML_Util::replaceEntities() basic tests=====' . PHP_EOL . PHP_EOL;
                   98344: 
                   98345: $data = 'This string contains < & >.';
                   98346: $utf8 = 'This data contains special chars like <, >, & and " as well as 盲, 枚, 脽, 脿 and 锚';
                   98347: 
                   98348: echo "TEST:  basic usage" . PHP_EOL;
                   98349: echo XML_Util::replaceEntities($data) . PHP_EOL . PHP_EOL;
                   98350: 
                   98351: echo "TEST:  basic usage but with bogus \$replaceEntities arg" . PHP_EOL;
                   98352: echo XML_Util::replaceEntities($data, 'I_AM_BOGUS') . PHP_EOL . PHP_EOL;
                   98353: 
                   98354: echo "TEST:  basic usage with ENTITIES_XML" . PHP_EOL;
                   98355: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   98356: 
                   98357: echo "TEST:  basic usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   98358: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98359: 
                   98360: echo "TEST:  utf8 usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   98361: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98362: 
                   98363: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED" . PHP_EOL;
                   98364: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   98365: 
                   98366: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   98367: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98368: 
                   98369: echo "TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   98370: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98371: 
                   98372: echo "TEST:  basic usage with ENTITIES_HTML" . PHP_EOL;
                   98373: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   98374: 
                   98375: echo "TEST:  basic usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   98376: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98377: 
                   98378: echo "TEST:  utf8 usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   98379: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98380: ?>
                   98381: --EXPECT--
                   98382: =====XML_Util::replaceEntities() basic tests=====
                   98383: 
                   98384: TEST:  basic usage
                   98385: This string contains &lt; &amp; &gt;.
                   98386: 
                   98387: TEST:  basic usage but with bogus $replaceEntities arg
                   98388: This string contains < & >.
                   98389: 
                   98390: TEST:  basic usage with ENTITIES_XML
                   98391: This string contains &lt; &amp; &gt;.
                   98392: 
                   98393: TEST:  basic usage with ENTITIES_XML and UTF-8
                   98394: This string contains &lt; &amp; &gt;.
                   98395: 
                   98396: TEST:  utf8 usage with ENTITIES_XML and UTF-8
                   98397: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as 盲, 枚, 脽, 脿 and 锚
                   98398: 
                   98399: TEST:  basic usage with ENTITIES_XML_REQUIRED
                   98400: This string contains &lt; &amp; >.
                   98401: 
                   98402: TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8
                   98403: This string contains &lt; &amp; >.
                   98404: 
                   98405: TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8
                   98406: This data contains special chars like &lt;, >, &amp; and &quot; as well as 盲, 枚, 脽, 脿 and 锚
                   98407: 
                   98408: TEST:  basic usage with ENTITIES_HTML
                   98409: This string contains &lt; &amp; &gt;.
                   98410: 
                   98411: TEST:  basic usage with ENTITIES_HTML and UTF-8
                   98412: This string contains &lt; &amp; &gt;.
                   98413: 
                   98414: TEST:  utf8 usage with ENTITIES_HTML and UTF-8
                   98415: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   98416: 
                   98417: XML_Util-1.2.1/tests/testBasic_reverseEntities.phpt100644   1750   1750        6241 11117075466  15625 --TEST--
                   98418: XML_Util::reverseEntities() basic tests
                   98419: --CREDITS--
                   98420: Chuck Burgess <ashnazg@php.net>
                   98421: # created for v1.2.0a1 2008-05-04
                   98422: --FILE--
                   98423: <?php
                   98424: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98425: echo '=====XML_Util::reverseEntities() basic tests=====' . PHP_EOL . PHP_EOL;
                   98426: 
                   98427: $data = 'This string contains &lt; &amp; &gt;.';
                   98428: $utf8 = 'This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;';
                   98429: 
                   98430: echo "TEST:  basic usage" . PHP_EOL;
                   98431: echo XML_Util::reverseEntities($data) . PHP_EOL . PHP_EOL;
                   98432: 
                   98433: echo "TEST:  basic usage but with bogus \$replaceEntities arg" . PHP_EOL;
                   98434: echo XML_Util::reverseEntities($data, 'I_AM_BOGUS') . PHP_EOL . PHP_EOL;
                   98435: 
                   98436: echo "TEST:  basic usage with ENTITIES_XML" . PHP_EOL;
                   98437: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   98438: 
                   98439: echo "TEST:  basic usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   98440: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98441: 
                   98442: echo "TEST:  utf8 usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   98443: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98444: 
                   98445: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED" . PHP_EOL;
                   98446: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   98447: 
                   98448: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   98449: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98450: 
                   98451: echo "TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   98452: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98453: 
                   98454: echo "TEST:  basic usage with ENTITIES_HTML" . PHP_EOL;
                   98455: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   98456: 
                   98457: echo "TEST:  basic usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   98458: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98459: 
                   98460: echo "TEST:  utf8 usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   98461: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   98462: ?>
                   98463: --EXPECT--
                   98464: =====XML_Util::reverseEntities() basic tests=====
                   98465: 
                   98466: TEST:  basic usage
                   98467: This string contains < & >.
                   98468: 
                   98469: TEST:  basic usage but with bogus $replaceEntities arg
                   98470: This string contains &lt; &amp; &gt;.
                   98471: 
                   98472: TEST:  basic usage with ENTITIES_XML
                   98473: This string contains < & >.
                   98474: 
                   98475: TEST:  basic usage with ENTITIES_XML and UTF-8
                   98476: This string contains < & >.
                   98477: 
                   98478: TEST:  utf8 usage with ENTITIES_XML and UTF-8
                   98479: This data contains special chars like <, >, & and " as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   98480: 
                   98481: TEST:  basic usage with ENTITIES_XML_REQUIRED
                   98482: This string contains < & &gt;.
                   98483: 
                   98484: TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8
                   98485: This string contains < & &gt;.
                   98486: 
                   98487: TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8
                   98488: This data contains special chars like <, &gt;, & and " as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   98489: 
                   98490: TEST:  basic usage with ENTITIES_HTML
                   98491: This string contains < & >.
                   98492: 
                   98493: TEST:  basic usage with ENTITIES_HTML and UTF-8
                   98494: This string contains < & >.
                   98495: 
                   98496: TEST:  utf8 usage with ENTITIES_HTML and UTF-8
                   98497: This data contains special chars like <, >, & and " as well as 盲, 枚, 脽, 脿 and 锚
                   98498: XML_Util-1.2.1/tests/testBasic_splitQualifiedName.phpt100644   1750   1750        1727 11117075466  16231 --TEST--
                   98499: XML_Util::splitQualifiedName() basic tests
                   98500: --CREDITS--
                   98501: Chuck Burgess <ashnazg@php.net>
                   98502: # created for v1.2.0a1 2008-05-04
                   98503: --FILE--
                   98504: <?php
                   98505: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98506: echo '=====XML_Util::splitQualifiedName() basic tests=====' . PHP_EOL . PHP_EOL;
                   98507: 
                   98508: echo "TEST:  basic usage without namespace" . PHP_EOL;
                   98509: $return = XML_Util::splitQualifiedName("xslt:stylesheet");
                   98510: echo "namespace => " . $return['namespace'] . PHP_EOL;
                   98511: echo "localPart => " . $return['localPart'] . PHP_EOL;
                   98512: echo PHP_EOL;
                   98513: 
                   98514: echo "TEST:  basic usage with namespace" . PHP_EOL;
                   98515: $return = XML_Util::splitQualifiedName("stylesheet", "myNs");
                   98516: echo "namespace => " . $return['namespace'] . PHP_EOL;
                   98517: echo "localPart => " . $return['localPart'] . PHP_EOL;
                   98518: echo PHP_EOL;
                   98519: ?>
                   98520: --EXPECT--
                   98521: =====XML_Util::splitQualifiedName() basic tests=====
                   98522: 
                   98523: TEST:  basic usage without namespace
                   98524: namespace => xslt
                   98525: localPart => stylesheet
                   98526: 
                   98527: TEST:  basic usage with namespace
                   98528: namespace => myNs
                   98529: localPart => stylesheet
                   98530: XML_Util-1.2.1/tests/testBug_4950.phpt100644   1750   1750        1243 11117075466  12537 --TEST--
                   98531: XML_Util tests for Bug #4950 "Incorrect CDATA serializing"
                   98532: --CREDITS--
                   98533: Chuck Burgess <ashnazg@php.net>
                   98534: # created for v1.2.0a1 2008-05-04
                   98535: --FILE--
                   98536: <?php
                   98537: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98538: echo '=====XML_Util tests for Bug #4950 "Incorrect CDATA serializing"=====' . PHP_EOL . PHP_EOL;
                   98539: 
                   98540: echo "TEST:  test case provided in bug report" . PHP_EOL;
                   98541: echo XML_Util::createTag("test", array(), "Content ]]></test> here!",
                   98542:     null, XML_UTIL_CDATA_SECTION) . PHP_EOL;
                   98543: 
                   98544: ?>
                   98545: --EXPECT--
                   98546: =====XML_Util tests for Bug #4950 "Incorrect CDATA serializing"=====
                   98547: 
                   98548: TEST:  test case provided in bug report
                   98549: <test><![CDATA[Content ]]]]><![CDATA[></test> here!]]></test>
                   98550: 
                   98551: XML_Util-1.2.1/tests/testBug_5392.phpt100644   1750   1750        2111 11117075466  12533 --TEST--
                   98552: XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"
                   98553: --CREDITS--
                   98554: Chuck Burgess <ashnazg@php.net>
                   98555: # created for v1.2.0a1 2008-05-04
                   98556: --FILE--
                   98557: <?php
                   98558: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   98559: echo '=====XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"=====' . PHP_EOL . PHP_EOL;
                   98560: 
                   98561: echo "TEST:  test case provided in bug report" . PHP_EOL;
                   98562: $data = 'This data contains special chars like <, >, & and " as well as 盲, 枚, 脽, 脿 and 锚';
                   98563: 
                   98564: $replaced = XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8');
                   98565: 
                   98566: $reversed = XML_Util::reverseEntities($replaced, XML_UTIL_ENTITIES_HTML, 'UTF-8');
                   98567: 
                   98568: echo $replaced . PHP_EOL;
                   98569: echo $reversed . PHP_EOL;
                   98570: 
                   98571: ?>
                   98572: --EXPECT--
                   98573: =====XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"=====
                   98574: 
                   98575: TEST:  test case provided in bug report
                   98576: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   98577: This data contains special chars like <, >, & and " as well as 盲, 枚, 脽, 脿 and 锚
                   98578: XML_Util-1.2.1/Util.php100644   1750   1750       73350 11117075466  10060 <?php
                   98579: 
                   98580: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   98581: 
                   98582: /**
                   98583:  * XML_Util
                   98584:  *
                   98585:  * XML Utilities package
                   98586:  * 
                   98587:  * PHP versions 4 and 5
                   98588:  *
                   98589:  * LICENSE:
                   98590:  *
                   98591:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   98592:  * All rights reserved.
                   98593:  *
                   98594:  * Redistribution and use in source and binary forms, with or without
                   98595:  * modification, are permitted provided that the following conditions
                   98596:  * are met:
                   98597:  *
                   98598:  *    * Redistributions of source code must retain the above copyright
                   98599:  *      notice, this list of conditions and the following disclaimer.
                   98600:  *    * Redistributions in binary form must reproduce the above copyright
                   98601:  *      notice, this list of conditions and the following disclaimer in the
                   98602:  *      documentation and/or other materials provided with the distribution.
                   98603:  *    * The name of the author may not be used to endorse or promote products
                   98604:  *      derived from this software without specific prior written permission.
                   98605:  *
                   98606:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   98607:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   98608:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   98609:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   98610:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   98611:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   98612:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   98613:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   98614:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   98615:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   98616:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   98617:  *
                   98618:  * @category  XML
                   98619:  * @package   XML_Util
                   98620:  * @author    Stephan Schmidt <schst@php.net>
                   98621:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   98622:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   98623:  * @version   CVS: $Id: Util.php,v 1.38 2008/11/13 00:03:38 ashnazg Exp $
                   98624:  * @link      http://pear.php.net/package/XML_Util
                   98625:  */
                   98626: 
                   98627: /**
                   98628:  * error code for invalid chars in XML name
                   98629:  */
                   98630: define('XML_UTIL_ERROR_INVALID_CHARS', 51);
                   98631: 
                   98632: /**
                   98633:  * error code for invalid chars in XML name
                   98634:  */
                   98635: define('XML_UTIL_ERROR_INVALID_START', 52);
                   98636: 
                   98637: /**
                   98638:  * error code for non-scalar tag content
                   98639:  */
                   98640: define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
                   98641: 
                   98642: /**
                   98643:  * error code for missing tag name
                   98644:  */
                   98645: define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
                   98646: 
                   98647: /**
                   98648:  * replace XML entities
                   98649:  */
                   98650: define('XML_UTIL_REPLACE_ENTITIES', 1);
                   98651: 
                   98652: /**
                   98653:  * embedd content in a CData Section
                   98654:  */
                   98655: define('XML_UTIL_CDATA_SECTION', 5);
                   98656: 
                   98657: /**
                   98658:  * do not replace entitites
                   98659:  */
                   98660: define('XML_UTIL_ENTITIES_NONE', 0);
                   98661: 
                   98662: /**
                   98663:  * replace all XML entitites
                   98664:  * This setting will replace <, >, ", ' and &
                   98665:  */
                   98666: define('XML_UTIL_ENTITIES_XML', 1);
                   98667: 
                   98668: /**
                   98669:  * replace only required XML entitites
                   98670:  * This setting will replace <, " and &
                   98671:  */
                   98672: define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
                   98673: 
                   98674: /**
                   98675:  * replace HTML entitites
                   98676:  * @link http://www.php.net/htmlentities
                   98677:  */
                   98678: define('XML_UTIL_ENTITIES_HTML', 3);
                   98679: 
                   98680: /**
                   98681:  * Collapse all empty tags.
                   98682:  */
                   98683: define('XML_UTIL_COLLAPSE_ALL', 1);
                   98684: 
                   98685: /**
                   98686:  * Collapse only empty XHTML tags that have no end tag.
                   98687:  */
                   98688: define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
                   98689: 
                   98690: /**
                   98691:  * utility class for working with XML documents
                   98692:  *
                   98693: 
                   98694:  * @category  XML
                   98695:  * @package   XML_Util
                   98696:  * @author    Stephan Schmidt <schst@php.net>
                   98697:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   98698:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   98699:  * @version   Release: 1.2.1
                   98700:  * @link      http://pear.php.net/package/XML_Util
                   98701:  */
                   98702: class XML_Util
                   98703: {
                   98704:     /**
                   98705:      * return API version
                   98706:      *
                   98707:      * @return string $version API version
                   98708:      * @access public
                   98709:      * @static
                   98710:      */
                   98711:     function apiVersion()
                   98712:     {
                   98713:         return '1.1';
                   98714:     }
                   98715: 
                   98716:     /**
                   98717:      * replace XML entities
                   98718:      *
                   98719:      * With the optional second parameter, you may select, which
                   98720:      * entities should be replaced.
                   98721:      *
                   98722:      * <code>
                   98723:      * require_once 'XML/Util.php';
                   98724:      *
                   98725:      * // replace XML entites:
                   98726:      * $string = XML_Util::replaceEntities('This string contains < & >.');
                   98727:      * </code>
                   98728:      *
                   98729:      * With the optional third parameter, you may pass the character encoding
                   98730:      * <code>
                   98731:      * require_once 'XML/Util.php';
                   98732:      *
                   98733:      * // replace XML entites in UTF-8:
                   98734:      * $string = XML_Util::replaceEntities(
                   98735:      *     'This string contains < & > as well as 盲, 枚, 脽, 脿 and 锚',
                   98736:      *     XML_UTIL_ENTITIES_HTML,
                   98737:      *     'UTF-8'
                   98738:      * );
                   98739:      * </code>
                   98740:      *
                   98741:      * @param string $string          string where XML special chars 
                   98742:      *                                should be replaced
                   98743:      * @param int    $replaceEntities setting for entities in attribute values 
                   98744:      *                                (one of XML_UTIL_ENTITIES_XML, 
                   98745:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
                   98746:      *                                XML_UTIL_ENTITIES_HTML)
                   98747:      * @param string $encoding        encoding value (if any)...
                   98748:      *                                must be a valid encoding as determined
                   98749:      *                                by the htmlentities() function
                   98750:      *
                   98751:      * @return string string with replaced chars
                   98752:      * @access public
                   98753:      * @static
                   98754:      * @see reverseEntities()
                   98755:      */
                   98756:     function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   98757:         $encoding = 'ISO-8859-1')
                   98758:     {
                   98759:         switch ($replaceEntities) {
                   98760:         case XML_UTIL_ENTITIES_XML:
                   98761:             return strtr($string, array(
                   98762:                 '&'  => '&amp;',
                   98763:                 '>'  => '&gt;',
                   98764:                 '<'  => '&lt;',
                   98765:                 '"'  => '&quot;',
                   98766:                 '\'' => '&apos;' ));
                   98767:             break;
                   98768:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   98769:             return strtr($string, array(
                   98770:                 '&' => '&amp;',
                   98771:                 '<' => '&lt;',
                   98772:                 '"' => '&quot;' ));
                   98773:             break;
                   98774:         case XML_UTIL_ENTITIES_HTML:
                   98775:             return htmlentities($string, ENT_COMPAT, $encoding);
                   98776:             break;
                   98777:         }
                   98778:         return $string;
                   98779:     }
                   98780: 
                   98781:     /**
                   98782:      * reverse XML entities
                   98783:      *
                   98784:      * With the optional second parameter, you may select, which
                   98785:      * entities should be reversed.
                   98786:      *
                   98787:      * <code>
                   98788:      * require_once 'XML/Util.php';
                   98789:      *
                   98790:      * // reverse XML entites:
                   98791:      * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   98792:      * </code>
                   98793:      *
                   98794:      * With the optional third parameter, you may pass the character encoding
                   98795:      * <code>
                   98796:      * require_once 'XML/Util.php';
                   98797:      *
                   98798:      * // reverse XML entites in UTF-8:
                   98799:      * $string = XML_Util::reverseEntities(
                   98800:      *     'This string contains &lt; &amp; &gt; as well as'
                   98801:      *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
                   98802:      *     XML_UTIL_ENTITIES_HTML,
                   98803:      *     'UTF-8'
                   98804:      * );
                   98805:      * </code>
                   98806:      *
                   98807:      * @param string $string          string where XML special chars 
                   98808:      *                                should be replaced
                   98809:      * @param int    $replaceEntities setting for entities in attribute values 
                   98810:      *                                (one of XML_UTIL_ENTITIES_XML, 
                   98811:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
                   98812:      *                                XML_UTIL_ENTITIES_HTML)
                   98813:      * @param string $encoding        encoding value (if any)...
                   98814:      *                                must be a valid encoding as determined
                   98815:      *                                by the html_entity_decode() function
                   98816:      *
                   98817:      * @return string string with replaced chars
                   98818:      * @access public
                   98819:      * @static
                   98820:      * @see replaceEntities()
                   98821:      */
                   98822:     function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   98823:         $encoding = 'ISO-8859-1')
                   98824:     {
                   98825:         switch ($replaceEntities) {
                   98826:         case XML_UTIL_ENTITIES_XML:
                   98827:             return strtr($string, array(
                   98828:                 '&amp;'  => '&',
                   98829:                 '&gt;'   => '>',
                   98830:                 '&lt;'   => '<',
                   98831:                 '&quot;' => '"',
                   98832:                 '&apos;' => '\'' ));
                   98833:             break;
                   98834:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   98835:             return strtr($string, array(
                   98836:                 '&amp;'  => '&',
                   98837:                 '&lt;'   => '<',
                   98838:                 '&quot;' => '"' ));
                   98839:             break;
                   98840:         case XML_UTIL_ENTITIES_HTML:
                   98841:             return html_entity_decode($string, ENT_COMPAT, $encoding);
                   98842:             break;
                   98843:         }
                   98844:         return $string;
                   98845:     }
                   98846: 
                   98847:     /**
                   98848:      * build an xml declaration
                   98849:      *
                   98850:      * <code>
                   98851:      * require_once 'XML/Util.php';
                   98852:      *
                   98853:      * // get an XML declaration:
                   98854:      * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
                   98855:      * </code>
                   98856:      *
                   98857:      * @param string $version    xml version
                   98858:      * @param string $encoding   character encoding
                   98859:      * @param bool   $standalone document is standalone (or not)
                   98860:      *
                   98861:      * @return string xml declaration
                   98862:      * @access public
                   98863:      * @static
                   98864:      * @uses attributesToString() to serialize the attributes of the XML declaration
                   98865:      */
                   98866:     function getXMLDeclaration($version = '1.0', $encoding = null, 
                   98867:         $standalone = null)
                   98868:     {
                   98869:         $attributes = array(
                   98870:             'version' => $version,
                   98871:         );
                   98872:         // add encoding
                   98873:         if ($encoding !== null) {
                   98874:             $attributes['encoding'] = $encoding;
                   98875:         }
                   98876:         // add standalone, if specified
                   98877:         if ($standalone !== null) {
                   98878:             $attributes['standalone'] = $standalone ? 'yes' : 'no';
                   98879:         }
                   98880: 
                   98881:         return sprintf('<?xml%s?>', 
                   98882:             XML_Util::attributesToString($attributes, false));
                   98883:     }
                   98884: 
                   98885:     /**
                   98886:      * build a document type declaration
                   98887:      *
                   98888:      * <code>
                   98889:      * require_once 'XML/Util.php';
                   98890:      *
                   98891:      * // get a doctype declaration:
                   98892:      * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
                   98893:      * </code>
                   98894:      *
                   98895:      * @param string $root        name of the root tag
                   98896:      * @param string $uri         uri of the doctype definition 
                   98897:      *                            (or array with uri and public id)
                   98898:      * @param string $internalDtd internal dtd entries
                   98899:      *
                   98900:      * @return string doctype declaration
                   98901:      * @access public
                   98902:      * @static
                   98903:      * @since 0.2
                   98904:      */
                   98905:     function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
                   98906:     {
                   98907:         if (is_array($uri)) {
                   98908:             $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
                   98909:         } elseif (!empty($uri)) {
                   98910:             $ref = sprintf(' SYSTEM "%s"', $uri);
                   98911:         } else {
                   98912:             $ref = '';
                   98913:         }
                   98914: 
                   98915:         if (empty($internalDtd)) {
                   98916:             return sprintf('<!DOCTYPE %s%s>', $root, $ref);
                   98917:         } else {
                   98918:             return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
                   98919:         }
                   98920:     }
                   98921: 
                   98922:     /**
                   98923:      * create string representation of an attribute list
                   98924:      *
                   98925:      * <code>
                   98926:      * require_once 'XML/Util.php';
                   98927:      *
                   98928:      * // build an attribute string
                   98929:      * $att = array(
                   98930:      *              'foo'   =>  'bar',
                   98931:      *              'argh'  =>  'tomato'
                   98932:      *            );
                   98933:      *
                   98934:      * $attList = XML_Util::attributesToString($att);
                   98935:      * </code>
                   98936:      *
                   98937:      * @param array      $attributes attribute array
                   98938:      * @param bool|array $sort       sort attribute list alphabetically, 
                   98939:      *                               may also be an assoc array containing 
                   98940:      *                               the keys 'sort', 'multiline', 'indent', 
                   98941:      *                               'linebreak' and 'entities'
                   98942:      * @param bool       $multiline  use linebreaks, if more than 
                   98943:      *                               one attribute is given
                   98944:      * @param string     $indent     string used for indentation of 
                   98945:      *                               multiline attributes
                   98946:      * @param string     $linebreak  string used for linebreaks of 
                   98947:      *                               multiline attributes
                   98948:      * @param int        $entities   setting for entities in attribute values 
                   98949:      *                               (one of XML_UTIL_ENTITIES_NONE, 
                   98950:      *                               XML_UTIL_ENTITIES_XML, 
                   98951:      *                               XML_UTIL_ENTITIES_XML_REQUIRED, 
                   98952:      *                               XML_UTIL_ENTITIES_HTML)
                   98953:      *
                   98954:      * @return string string representation of the attributes
                   98955:      * @access public
                   98956:      * @static
                   98957:      * @uses replaceEntities() to replace XML entities in attribute values
                   98958:      * @todo allow sort also to be an options array
                   98959:      */
                   98960:     function attributesToString($attributes, $sort = true, $multiline = false, 
                   98961:         $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
                   98962:     {
                   98963:         /*
                   98964:          * second parameter may be an array
                   98965:          */
                   98966:         if (is_array($sort)) {
                   98967:             if (isset($sort['multiline'])) {
                   98968:                 $multiline = $sort['multiline'];
                   98969:             }
                   98970:             if (isset($sort['indent'])) {
                   98971:                 $indent = $sort['indent'];
                   98972:             }
                   98973:             if (isset($sort['linebreak'])) {
                   98974:                 $multiline = $sort['linebreak'];
                   98975:             }
                   98976:             if (isset($sort['entities'])) {
                   98977:                 $entities = $sort['entities'];
                   98978:             }
                   98979:             if (isset($sort['sort'])) {
                   98980:                 $sort = $sort['sort'];
                   98981:             } else {
                   98982:                 $sort = true;
                   98983:             }
                   98984:         }
                   98985:         $string = '';
                   98986:         if (is_array($attributes) && !empty($attributes)) {
                   98987:             if ($sort) {
                   98988:                 ksort($attributes);
                   98989:             }
                   98990:             if ( !$multiline || count($attributes) == 1) {
                   98991:                 foreach ($attributes as $key => $value) {
                   98992:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   98993:                         if ($entities === XML_UTIL_CDATA_SECTION) {
                   98994:                             $entities = XML_UTIL_ENTITIES_XML;
                   98995:                         }
                   98996:                         $value = XML_Util::replaceEntities($value, $entities);
                   98997:                     }
                   98998:                     $string .= ' ' . $key . '="' . $value . '"';
                   98999:                 }
                   99000:             } else {
                   99001:                 $first = true;
                   99002:                 foreach ($attributes as $key => $value) {
                   99003:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   99004:                         $value = XML_Util::replaceEntities($value, $entities);
                   99005:                     }
                   99006:                     if ($first) {
                   99007:                         $string .= ' ' . $key . '="' . $value . '"';
                   99008:                         $first   = false;
                   99009:                     } else {
                   99010:                         $string .= $linebreak . $indent . $key . '="' . $value . '"';
                   99011:                     }
                   99012:                 }
                   99013:             }
                   99014:         }
                   99015:         return $string;
                   99016:     }
                   99017: 
                   99018:     /**
                   99019:      * Collapses empty tags.
                   99020:      *
                   99021:      * @param string $xml  XML
                   99022:      * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
                   99023:      *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
                   99024:      *
                   99025:      * @return string XML
                   99026:      * @access public
                   99027:      * @static
                   99028:      * @todo PEAR CS - unable to avoid "space after open parens" error
                   99029:      *       in the IF branch
                   99030:      */
                   99031:     function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) 
                   99032:     {
                   99033:         if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
                   99034:             return preg_replace(
                   99035:                 '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                   99036:                 . 'param)([^>]*)><\/\\1>/s',
                   99037:                 '<\\1\\2 />',
                   99038:                 $xml);
                   99039:         } else {
                   99040:             return preg_replace('/<(\w+)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml);
                   99041:         }
                   99042:     }
                   99043: 
                   99044:     /**
                   99045:      * create a tag
                   99046:      *
                   99047:      * This method will call XML_Util::createTagFromArray(), which
                   99048:      * is more flexible.
                   99049:      *
                   99050:      * <code>
                   99051:      * require_once 'XML/Util.php';
                   99052:      *
                   99053:      * // create an XML tag:
                   99054:      * $tag = XML_Util::createTag('myNs:myTag', 
                   99055:      *     array('foo' => 'bar'), 
                   99056:      *     'This is inside the tag', 
                   99057:      *     'http://www.w3c.org/myNs#');
                   99058:      * </code>
                   99059:      *
                   99060:      * @param string $qname           qualified tagname (including namespace)
                   99061:      * @param array  $attributes      array containg attributes
                   99062:      * @param mixed  $content         the content
                   99063:      * @param string $namespaceUri    URI of the namespace
                   99064:      * @param int    $replaceEntities whether to replace XML special chars in 
                   99065:      *                                content, embedd it in a CData section 
                   99066:      *                                or none of both
                   99067:      * @param bool   $multiline       whether to create a multiline tag where 
                   99068:      *                                each attribute gets written to a single line
                   99069:      * @param string $indent          string used to indent attributes 
                   99070:      *                                (_auto indents attributes so they start 
                   99071:      *                                at the same column)
                   99072:      * @param string $linebreak       string used for linebreaks
                   99073:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   99074:      *
                   99075:      * @return string XML tag
                   99076:      * @access public
                   99077:      * @static
                   99078:      * @see createTagFromArray()
                   99079:      * @uses createTagFromArray() to create the tag
                   99080:      */
                   99081:     function createTag($qname, $attributes = array(), $content = null, 
                   99082:         $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, 
                   99083:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   99084:         $sortAttributes = true)
                   99085:     {
                   99086:         $tag = array(
                   99087:             'qname'      => $qname,
                   99088:             'attributes' => $attributes
                   99089:         );
                   99090: 
                   99091:         // add tag content
                   99092:         if ($content !== null) {
                   99093:             $tag['content'] = $content;
                   99094:         }
                   99095: 
                   99096:         // add namespace Uri
                   99097:         if ($namespaceUri !== null) {
                   99098:             $tag['namespaceUri'] = $namespaceUri;
                   99099:         }
                   99100: 
                   99101:         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, 
                   99102:             $indent, $linebreak, $sortAttributes);
                   99103:     }
                   99104: 
                   99105:     /**
                   99106:      * create a tag from an array
                   99107:      * this method awaits an array in the following format
                   99108:      * <pre>
                   99109:      * array(
                   99110:      *     // qualified name of the tag
                   99111:      *     'qname' => $qname        
                   99112:      *
                   99113:      *     // namespace prefix (optional, if qname is specified or no namespace)
                   99114:      *     'namespace' => $namespace    
                   99115:      *
                   99116:      *     // local part of the tagname (optional, if qname is specified)
                   99117:      *     'localpart' => $localpart,   
                   99118:      *
                   99119:      *     // array containing all attributes (optional)
                   99120:      *     'attributes' => array(),      
                   99121:      *
                   99122:      *     // tag content (optional)
                   99123:      *     'content' => $content,     
                   99124:      *
                   99125:      *     // namespaceUri for the given namespace (optional)
                   99126:      *     'namespaceUri' => $namespaceUri 
                   99127:      * )
                   99128:      * </pre>
                   99129:      *
                   99130:      * <code>
                   99131:      * require_once 'XML/Util.php';
                   99132:      *
                   99133:      * $tag = array(
                   99134:      *     'qname'        => 'foo:bar',
                   99135:      *     'namespaceUri' => 'http://foo.com',
                   99136:      *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   99137:      *     'content'      => 'I\'m inside the tag',
                   99138:      * );
                   99139:      * // creating a tag with qualified name and namespaceUri
                   99140:      * $string = XML_Util::createTagFromArray($tag);
                   99141:      * </code>
                   99142:      *
                   99143:      * @param array  $tag             tag definition
                   99144:      * @param int    $replaceEntities whether to replace XML special chars in 
                   99145:      *                                content, embedd it in a CData section 
                   99146:      *                                or none of both
                   99147:      * @param bool   $multiline       whether to create a multiline tag where each 
                   99148:      *                                attribute gets written to a single line
                   99149:      * @param string $indent          string used to indent attributes 
                   99150:      *                                (_auto indents attributes so they start 
                   99151:      *                                at the same column)
                   99152:      * @param string $linebreak       string used for linebreaks
                   99153:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   99154:      *
                   99155:      * @return string XML tag
                   99156:      * @access public
                   99157:      * @static
                   99158:      * @see createTag()
                   99159:      * @uses attributesToString() to serialize the attributes of the tag
                   99160:      * @uses splitQualifiedName() to get local part and namespace of a qualified name
                   99161:      * @uses createCDataSection()
                   99162:      * @uses raiseError()
                   99163:      */
                   99164:     function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
                   99165:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   99166:         $sortAttributes = true)
                   99167:     {
                   99168:         if (isset($tag['content']) && !is_scalar($tag['content'])) {
                   99169:             return XML_Util::raiseError('Supplied non-scalar value as tag content',
                   99170:             XML_UTIL_ERROR_NON_SCALAR_CONTENT);
                   99171:         }
                   99172: 
                   99173:         if (!isset($tag['qname']) && !isset($tag['localPart'])) {
                   99174:             return XML_Util::raiseError('You must either supply a qualified name '
                   99175:                 . '(qname) or local tag name (localPart).', 
                   99176:                 XML_UTIL_ERROR_NO_TAG_NAME);
                   99177:         }
                   99178: 
                   99179:         // if no attributes hav been set, use empty attributes
                   99180:         if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
                   99181:             $tag['attributes'] = array();
                   99182:         }
                   99183: 
                   99184:         if (isset($tag['namespaces'])) {
                   99185:             foreach ($tag['namespaces'] as $ns => $uri) {
                   99186:                 $tag['attributes']['xmlns:' . $ns] = $uri;
                   99187:             }
                   99188:         }
                   99189: 
                   99190:         if (!isset($tag['qname'])) {
                   99191:             // qualified name is not given
                   99192: 
                   99193:             // check for namespace
                   99194:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   99195:                 $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
                   99196:             } else {
                   99197:                 $tag['qname'] = $tag['localPart'];
                   99198:             }
                   99199:         } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
                   99200:             // namespace URI is set, but no namespace
                   99201: 
                   99202:             $parts = XML_Util::splitQualifiedName($tag['qname']);
                   99203: 
                   99204:             $tag['localPart'] = $parts['localPart'];
                   99205:             if (isset($parts['namespace'])) {
                   99206:                 $tag['namespace'] = $parts['namespace'];
                   99207:             }
                   99208:         }
                   99209: 
                   99210:         if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
                   99211:             // is a namespace given
                   99212:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   99213:                 $tag['attributes']['xmlns:' . $tag['namespace']] =
                   99214:                     $tag['namespaceUri'];
                   99215:             } else {
                   99216:                 // define this Uri as the default namespace
                   99217:                 $tag['attributes']['xmlns'] = $tag['namespaceUri'];
                   99218:             }
                   99219:         }
                   99220: 
                   99221:         // check for multiline attributes
                   99222:         if ($multiline === true) {
                   99223:             if ($indent === '_auto') {
                   99224:                 $indent = str_repeat(' ', (strlen($tag['qname'])+2));
                   99225:             }
                   99226:         }
                   99227: 
                   99228:         // create attribute list
                   99229:         $attList = XML_Util::attributesToString($tag['attributes'], 
                   99230:             $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
                   99231:         if (!isset($tag['content']) || (string)$tag['content'] == '') {
                   99232:             $tag = sprintf('<%s%s />', $tag['qname'], $attList);
                   99233:         } else {
                   99234:             switch ($replaceEntities) {
                   99235:             case XML_UTIL_ENTITIES_NONE:
                   99236:                 break;
                   99237:             case XML_UTIL_CDATA_SECTION:
                   99238:                 $tag['content'] = XML_Util::createCDataSection($tag['content']);
                   99239:                 break;
                   99240:             default:
                   99241:                 $tag['content'] = XML_Util::replaceEntities($tag['content'], 
                   99242:                     $replaceEntities);
                   99243:                 break;
                   99244:             }
                   99245:             $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
                   99246:                 $tag['qname']);
                   99247:         }
                   99248:         return $tag;
                   99249:     }
                   99250: 
                   99251:     /**
                   99252:      * create a start element
                   99253:      *
                   99254:      * <code>
                   99255:      * require_once 'XML/Util.php';
                   99256:      *
                   99257:      * // create an XML start element:
                   99258:      * $tag = XML_Util::createStartElement('myNs:myTag', 
                   99259:      *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
                   99260:      * </code>
                   99261:      *
                   99262:      * @param string $qname          qualified tagname (including namespace)
                   99263:      * @param array  $attributes     array containg attributes
                   99264:      * @param string $namespaceUri   URI of the namespace
                   99265:      * @param bool   $multiline      whether to create a multiline tag where each 
                   99266:      *                               attribute gets written to a single line
                   99267:      * @param string $indent         string used to indent attributes (_auto indents
                   99268:      *                               attributes so they start at the same column)
                   99269:      * @param string $linebreak      string used for linebreaks
                   99270:      * @param bool   $sortAttributes Whether to sort the attributes or not
                   99271:      *
                   99272:      * @return string XML start element
                   99273:      * @access public
                   99274:      * @static
                   99275:      * @see createEndElement(), createTag()
                   99276:      */
                   99277:     function createStartElement($qname, $attributes = array(), $namespaceUri = null,
                   99278:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   99279:         $sortAttributes = true)
                   99280:     {
                   99281:         // if no attributes hav been set, use empty attributes
                   99282:         if (!isset($attributes) || !is_array($attributes)) {
                   99283:             $attributes = array();
                   99284:         }
                   99285: 
                   99286:         if ($namespaceUri != null) {
                   99287:             $parts = XML_Util::splitQualifiedName($qname);
                   99288:         }
                   99289: 
                   99290:         // check for multiline attributes
                   99291:         if ($multiline === true) {
                   99292:             if ($indent === '_auto') {
                   99293:                 $indent = str_repeat(' ', (strlen($qname)+2));
                   99294:             }
                   99295:         }
                   99296: 
                   99297:         if ($namespaceUri != null) {
                   99298:             // is a namespace given
                   99299:             if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                   99300:                 $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
                   99301:             } else {
                   99302:                 // define this Uri as the default namespace
                   99303:                 $attributes['xmlns'] = $namespaceUri;
                   99304:             }
                   99305:         }
                   99306: 
                   99307:         // create attribute list
                   99308:         $attList = XML_Util::attributesToString($attributes, $sortAttributes, 
                   99309:             $multiline, $indent, $linebreak);
                   99310:         $element = sprintf('<%s%s>', $qname, $attList);
                   99311:         return  $element;
                   99312:     }
                   99313: 
                   99314:     /**
                   99315:      * create an end element
                   99316:      *
                   99317:      * <code>
                   99318:      * require_once 'XML/Util.php';
                   99319:      *
                   99320:      * // create an XML start element:
                   99321:      * $tag = XML_Util::createEndElement('myNs:myTag');
                   99322:      * </code>
                   99323:      *
                   99324:      * @param string $qname qualified tagname (including namespace)
                   99325:      *
                   99326:      * @return string XML end element
                   99327:      * @access public
                   99328:      * @static
                   99329:      * @see createStartElement(), createTag()
                   99330:      */
                   99331:     function createEndElement($qname)
                   99332:     {
                   99333:         $element = sprintf('</%s>', $qname);
                   99334:         return $element;
                   99335:     }
                   99336: 
                   99337:     /**
                   99338:      * create an XML comment
                   99339:      *
                   99340:      * <code>
                   99341:      * require_once 'XML/Util.php';
                   99342:      *
                   99343:      * // create an XML start element:
                   99344:      * $tag = XML_Util::createComment('I am a comment');
                   99345:      * </code>
                   99346:      *
                   99347:      * @param string $content content of the comment
                   99348:      *
                   99349:      * @return string XML comment
                   99350:      * @access public
                   99351:      * @static
                   99352:      */
                   99353:     function createComment($content)
                   99354:     {
                   99355:         $comment = sprintf('<!-- %s -->', $content);
                   99356:         return $comment;
                   99357:     }
                   99358: 
                   99359:     /**
                   99360:      * create a CData section
                   99361:      *
                   99362:      * <code>
                   99363:      * require_once 'XML/Util.php';
                   99364:      *
                   99365:      * // create a CData section
                   99366:      * $tag = XML_Util::createCDataSection('I am content.');
                   99367:      * </code>
                   99368:      *
                   99369:      * @param string $data data of the CData section
                   99370:      *
                   99371:      * @return string CData section with content
                   99372:      * @access public
                   99373:      * @static
                   99374:      */
                   99375:     function createCDataSection($data)
                   99376:     {
                   99377:         return sprintf('<![CDATA[%s]]>', 
                   99378:             preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
                   99379: 
                   99380:     }
                   99381: 
                   99382:     /**
                   99383:      * split qualified name and return namespace and local part
                   99384:      *
                   99385:      * <code>
                   99386:      * require_once 'XML/Util.php';
                   99387:      *
                   99388:      * // split qualified tag
                   99389:      * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
                   99390:      * </code>
                   99391:      * the returned array will contain two elements:
                   99392:      * <pre>
                   99393:      * array(
                   99394:      *     'namespace' => 'xslt',
                   99395:      *     'localPart' => 'stylesheet'
                   99396:      * );
                   99397:      * </pre>
                   99398:      *
                   99399:      * @param string $qname     qualified tag name
                   99400:      * @param string $defaultNs default namespace (optional)
                   99401:      *
                   99402:      * @return array array containing namespace and local part
                   99403:      * @access public
                   99404:      * @static
                   99405:      */
                   99406:     function splitQualifiedName($qname, $defaultNs = null)
                   99407:     {
                   99408:         if (strstr($qname, ':')) {
                   99409:             $tmp = explode(':', $qname);
                   99410:             return array(
                   99411:                 'namespace' => $tmp[0],
                   99412:                 'localPart' => $tmp[1]
                   99413:             );
                   99414:         }
                   99415:         return array(
                   99416:             'namespace' => $defaultNs,
                   99417:             'localPart' => $qname
                   99418:         );
                   99419:     }
                   99420: 
                   99421:     /**
                   99422:      * check, whether string is valid XML name
                   99423:      *
                   99424:      * <p>XML names are used for tagname, attribute names and various
                   99425:      * other, lesser known entities.</p>
                   99426:      * <p>An XML name may only consist of alphanumeric characters,
                   99427:      * dashes, undescores and periods, and has to start with a letter
                   99428:      * or an underscore.</p>
                   99429:      *
                   99430:      * <code>
                   99431:      * require_once 'XML/Util.php';
                   99432:      *
                   99433:      * // verify tag name
                   99434:      * $result = XML_Util::isValidName('invalidTag?');
                   99435:      * if (is_a($result, 'PEAR_Error')) {
                   99436:      *    print 'Invalid XML name: ' . $result->getMessage();
                   99437:      * }
                   99438:      * </code>
                   99439:      *
                   99440:      * @param string $string string that should be checked
                   99441:      *
                   99442:      * @return mixed true, if string is a valid XML name, PEAR error otherwise
                   99443:      * @access public
                   99444:      * @static
                   99445:      * @todo support for other charsets
                   99446:      * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
                   99447:      */
                   99448:     function isValidName($string)
                   99449:     {
                   99450:         // check for invalid chars
                   99451:         if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
                   99452:             return XML_Util::raiseError('XML names may only start with letter '
                   99453:                 . 'or underscore', XML_UTIL_ERROR_INVALID_START);
                   99454:         }
                   99455: 
                   99456:         // check for invalid chars
                   99457:         if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/',
                   99458:             $string)
                   99459:         ) {
                   99460:             return XML_Util::raiseError('XML names may only contain alphanumeric '
                   99461:                 . 'chars, period, hyphen, colon and underscores', 
                   99462:                 XML_UTIL_ERROR_INVALID_CHARS);
                   99463:         }
                   99464:         // XML name is valid
                   99465:         return true;
                   99466:     }
                   99467: 
                   99468:     /**
                   99469:      * replacement for XML_Util::raiseError
                   99470:      *
                   99471:      * Avoids the necessity to always require
                   99472:      * PEAR.php
                   99473:      *
                   99474:      * @param string $msg  error message
                   99475:      * @param int    $code error code
                   99476:      *
                   99477:      * @return PEAR_Error
                   99478:      * @access public
                   99479:      * @static
                   99480:      * @todo PEAR CS - should this use include_once instead?
                   99481:      */
                   99482:     function raiseError($msg, $code)
                   99483:     {
                   99484:         require_once 'PEAR.php';
                   99485:         return PEAR::raiseError($msg, $code);
                   99486:     }
                   99487: }
                   99488: ?>
                   99489: package.sig100644   1750   1750         305 11117075544   6362 -----BEGIN PGP SIGNATURE-----
                   99490: Version: GnuPG v1.4.9 (GNU/Linux)
                   99491: 
                   99492: iEYEABECAAYFAkk8e2QACgkQcqMhusJF8XULZgCg0iwVLWueraJzK5s1AesDkVzv
                   99493: GucAn22sSv3QiTSUWG9BmakiW9hFsb4V
                   99494: =g2mr
                   99495: -----END PGP SIGNATURE-----
                   99496: 搑栐钺3𗸊0C矒GBMB

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