Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Package.php
Go to the documentation of this file.
1<?php
15
20define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
25define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
26
57{
90 var $_downloadDeps = array();
94 var $_valid = false;
98 var $_analyzed = false;
107 var $_explicitState = false;
111 var $_explicitGroup = false;
127 var $_validated = false;
128
132 function __construct(&$downloader)
133 {
134 $this->_downloader = &$downloader;
135 $this->_config = &$this->_downloader->config;
136 $this->_registry = &$this->_config->getRegistry();
137 $options = $downloader->getOptions();
138 if (isset($options['packagingroot'])) {
139 $this->_config->setInstallRoot($options['packagingroot']);
140 $this->_installRegistry = &$this->_config->getRegistry();
141 $this->_config->setInstallRoot(false);
142 } else {
143 $this->_installRegistry = &$this->_registry;
144 }
145 $this->_valid = $this->_analyzed = false;
146 }
147
157 function initialize($param)
158 {
159 $origErr = $this->_fromFile($param);
160 if ($this->_valid) {
161 return true;
162 }
163
164 $options = $this->_downloader->getOptions();
165 if (isset($options['offline'])) {
166 if (PEAR::isError($origErr) && !isset($options['soft'])) {
167 foreach ($origErr->getUserInfo() as $userInfo) {
168 if (isset($userInfo['message'])) {
169 $this->_downloader->log(0, $userInfo['message']);
170 }
171 }
172
173 $this->_downloader->log(0, $origErr->getMessage());
174 }
175
176 return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
177 }
178
179 $err = $this->_fromUrl($param);
180 if (PEAR::isError($err) || !$this->_valid) {
181 if ($this->_type == 'url') {
182 if (PEAR::isError($err) && !isset($options['soft'])) {
183 $this->_downloader->log(0, $err->getMessage());
184 }
185
186 return PEAR::raiseError("Invalid or missing remote package file");
187 }
188
189 $err = $this->_fromString($param);
190 if (PEAR::isError($err) || !$this->_valid) {
191 if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
192 return false; // instruct the downloader to silently skip
193 }
194
195 if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
196 if (is_array($origErr->getUserInfo())) {
197 foreach ($origErr->getUserInfo() as $err) {
198 if (is_array($err)) {
199 $err = $err['message'];
200 }
201
202 if (!isset($options['soft'])) {
203 $this->_downloader->log(0, $err);
204 }
205 }
206 }
207
208 if (!isset($options['soft'])) {
209 $this->_downloader->log(0, $origErr->getMessage());
210 }
211
212 if (is_array($param)) {
213 $param = $this->_registry->parsedPackageNameToString($param, true);
214 }
215
216 if (!isset($options['soft'])) {
217 $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
218 }
219
220 // Passing no message back - already logged above
221 return PEAR::raiseError();
222 }
223
224 if (PEAR::isError($err) && !isset($options['soft'])) {
225 $this->_downloader->log(0, $err->getMessage());
226 }
227
228 if (is_array($param)) {
229 $param = $this->_registry->parsedPackageNameToString($param, true);
230 }
231
232 if (!isset($options['soft'])) {
233 $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
234 }
235
236 // Passing no message back - already logged above
237 return PEAR::raiseError();
238 }
239 }
240
241 return true;
242 }
243
248 function &download()
249 {
250 if (isset($this->_packagefile)) {
251 return $this->_packagefile;
252 }
253
254 if (isset($this->_downloadURL['url'])) {
255 $this->_isvalid = false;
256 $info = $this->getParsedPackage();
257 foreach ($info as $i => $p) {
258 $info[$i] = strtolower($p);
259 }
260
261 $err = $this->_fromUrl($this->_downloadURL['url'],
262 $this->_registry->parsedPackageNameToString($this->_parsedname, true));
263 $newinfo = $this->getParsedPackage();
264 foreach ($newinfo as $i => $p) {
265 $newinfo[$i] = strtolower($p);
266 }
267
268 if ($info != $newinfo) {
269 do {
270 if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
271 $info['channel'] = 'pear.php.net';
272 if ($info == $newinfo) {
273 // skip the channel check if a pecl package says it's a PEAR package
274 break;
275 }
276 }
277 if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
278 $info['channel'] = 'pecl.php.net';
279 if ($info == $newinfo) {
280 // skip the channel check if a pecl package says it's a PEAR package
281 break;
282 }
283 }
284
285 return PEAR::raiseError('CRITICAL ERROR: We are ' .
286 $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
287 'downloaded claims to be ' .
288 $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
289 } while (false);
290 }
291
292 if (PEAR::isError($err) || !$this->_valid) {
293 return $err;
294 }
295 }
296
297 $this->_type = 'local';
298 return $this->_packagefile;
299 }
300
301 function &getPackageFile()
302 {
303 return $this->_packagefile;
304 }
305
306 function &getDownloader()
307 {
308 return $this->_downloader;
309 }
310
311 function getType()
312 {
313 return $this->_type;
314 }
315
319 function fromDepURL($dep)
320 {
321 $this->_downloadURL = $dep;
322 if (isset($dep['uri'])) {
323 $options = $this->_downloader->getOptions();
324 if (!extension_loaded("zlib") || isset($options['nocompress'])) {
325 $ext = '.tar';
326 } else {
327 $ext = '.tgz';
328 }
329
330 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
331 $err = $this->_fromUrl($dep['uri'] . $ext);
332 PEAR::popErrorHandling();
333 if (PEAR::isError($err)) {
334 if (!isset($options['soft'])) {
335 $this->_downloader->log(0, $err->getMessage());
336 }
337
338 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
339 'cannot download');
340 }
341 } else {
342 $this->_parsedname =
343 array(
344 'package' => $dep['info']->getPackage(),
345 'channel' => $dep['info']->getChannel(),
346 'version' => $dep['version']
347 );
348 if (!isset($dep['nodefault'])) {
349 $this->_parsedname['group'] = 'default'; // download the default dependency group
350 $this->_explicitGroup = false;
351 }
352
353 $this->_rawpackagefile = $dep['raw'];
354 }
355 }
356
357 function detectDependencies($params)
358 {
359 $options = $this->_downloader->getOptions();
360 if (isset($options['downloadonly'])) {
361 return;
362 }
363
364 if (isset($options['offline'])) {
365 $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
366 return;
367 }
368
369 $pname = $this->getParsedPackage();
370 if (!$pname) {
371 return;
372 }
373
374 $deps = $this->getDeps();
375 if (!$deps) {
376 return;
377 }
378
379 if (isset($deps['required'])) { // package.xml 2.0
380 return $this->_detect2($deps, $pname, $options, $params);
381 }
382
383 return $this->_detect1($deps, $pname, $options, $params);
384 }
385
386 function setValidated()
387 {
388 $this->_validated = true;
389 }
390
392 {
393 return $this->_validated;
394 }
395
400 public static function removeInstalled(&$params)
401 {
402 if (!isset($params[0])) {
403 return;
404 }
405
406 $options = $params[0]->_downloader->getOptions();
407 if (!isset($options['downloadonly'])) {
408 foreach ($params as $i => $param) {
409 $package = $param->getPackage();
410 $channel = $param->getChannel();
411 // remove self if already installed with this version
412 // this does not need any pecl magic - we only remove exact matches
413 if ($param->_installRegistry->packageExists($package, $channel)) {
414 $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
415 if (version_compare($packageVersion, $param->getVersion(), '==')) {
416 if (!isset($options['force']) && !isset($options['packagingroot'])) {
417 $info = $param->getParsedPackage();
418 unset($info['version']);
419 unset($info['state']);
420 if (!isset($options['soft'])) {
421 $param->_downloader->log(1, 'Skipping package "' .
422 $param->getShortName() .
423 '", already installed as version ' . $packageVersion);
424 }
425 $params[$i] = false;
426 }
427 } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
428 !isset($options['soft']) && !isset($options['packagingroot'])) {
429 $info = $param->getParsedPackage();
430 $param->_downloader->log(1, 'Skipping package "' .
431 $param->getShortName() .
432 '", already installed as version ' . $packageVersion);
433 $params[$i] = false;
434 }
435 }
436 }
437 }
438
440 }
441
442 function _detect2($deps, $pname, $options, $params)
443 {
444 $this->_downloadDeps = array();
445 $groupnotfound = false;
446 foreach (array('package', 'subpackage') as $packagetype) {
447 // get required dependency group
448 if (isset($deps['required'][$packagetype])) {
449 if (isset($deps['required'][$packagetype][0])) {
450 foreach ($deps['required'][$packagetype] as $dep) {
451 if (isset($dep['conflicts'])) {
452 // skip any package that this package conflicts with
453 continue;
454 }
455 $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
456 if (is_array($ret)) {
457 $this->_downloadDeps[] = $ret;
458 } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
459 $this->_downloader->log(0, $ret->getMessage());
460 }
461 }
462 } else {
463 $dep = $deps['required'][$packagetype];
464 if (!isset($dep['conflicts'])) {
465 // skip any package that this package conflicts with
466 $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
467 if (is_array($ret)) {
468 $this->_downloadDeps[] = $ret;
469 } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
470 $this->_downloader->log(0, $ret->getMessage());
471 }
472 }
473 }
474 }
475
476 // get optional dependency group, if any
477 if (isset($deps['optional'][$packagetype])) {
478 $skipnames = array();
479 if (!isset($deps['optional'][$packagetype][0])) {
480 $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
481 }
482
483 foreach ($deps['optional'][$packagetype] as $dep) {
484 $skip = false;
485 if (!isset($options['alldeps'])) {
486 $dep['package'] = $dep['name'];
487 if (!isset($options['soft'])) {
488 $this->_downloader->log(3, 'Notice: package "' .
489 $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
490 true) . '" optional dependency "' .
491 $this->_registry->parsedPackageNameToString(array('package' =>
492 $dep['name'], 'channel' => 'pear.php.net'), true) .
493 '" will not be automatically downloaded');
494 }
495 $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
496 $skip = true;
497 unset($dep['package']);
498 }
499
500 $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
501 if (PEAR::isError($ret) && !isset($options['soft'])) {
502 $this->_downloader->log(0, $ret->getMessage());
503 }
504
505 if (!$ret) {
506 $dep['package'] = $dep['name'];
507 $skip = count($skipnames) ?
508 $skipnames[count($skipnames) - 1] : '';
509 if ($skip ==
510 $this->_registry->parsedPackageNameToString($dep, true)) {
511 array_pop($skipnames);
512 }
513 }
514
515 if (!$skip && is_array($ret)) {
516 $this->_downloadDeps[] = $ret;
517 }
518 }
519
520 if (count($skipnames)) {
521 if (!isset($options['soft'])) {
522 $this->_downloader->log(1, 'Did not download optional dependencies: ' .
523 implode(', ', $skipnames) .
524 ', use --alldeps to download automatically');
525 }
526 }
527 }
528
529 // get requested dependency group, if any
530 $groupname = $this->getGroup();
531 $explicit = $this->_explicitGroup;
532 if (!$groupname) {
533 if (!$this->canDefault()) {
534 continue;
535 }
536
537 $groupname = 'default'; // try the default dependency group
538 }
539
540 if ($groupnotfound) {
541 continue;
542 }
543
544 if (isset($deps['group'])) {
545 if (isset($deps['group']['attribs'])) {
546 if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
547 $group = $deps['group'];
548 } elseif ($explicit) {
549 if (!isset($options['soft'])) {
550 $this->_downloader->log(0, 'Warning: package "' .
551 $this->_registry->parsedPackageNameToString($pname, true) .
552 '" has no dependency ' . 'group named "' . $groupname . '"');
553 }
554
555 $groupnotfound = true;
556 continue;
557 }
558 } else {
559 $found = false;
560 foreach ($deps['group'] as $group) {
561 if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
562 $found = true;
563 break;
564 }
565 }
566
567 if (!$found) {
568 if ($explicit) {
569 if (!isset($options['soft'])) {
570 $this->_downloader->log(0, 'Warning: package "' .
571 $this->_registry->parsedPackageNameToString($pname, true) .
572 '" has no dependency ' . 'group named "' . $groupname . '"');
573 }
574 }
575
576 $groupnotfound = true;
577 continue;
578 }
579 }
580 }
581
582 if (isset($group) && isset($group[$packagetype])) {
583 if (isset($group[$packagetype][0])) {
584 foreach ($group[$packagetype] as $dep) {
585 $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
586 $group['attribs']['name'] . '"', $params);
587 if (is_array($ret)) {
588 $this->_downloadDeps[] = $ret;
589 } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
590 $this->_downloader->log(0, $ret->getMessage());
591 }
592 }
593 } else {
594 $ret = $this->_detect2Dep($group[$packagetype], $pname,
595 'dependency group "' .
596 $group['attribs']['name'] . '"', $params);
597 if (is_array($ret)) {
598 $this->_downloadDeps[] = $ret;
599 } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
600 $this->_downloader->log(0, $ret->getMessage());
601 }
602 }
603 }
604 }
605 }
606
607 function _detect2Dep($dep, $pname, $group, $params)
608 {
609 if (isset($dep['conflicts'])) {
610 return true;
611 }
612
613 $options = $this->_downloader->getOptions();
614 if (isset($dep['uri'])) {
615 return array('uri' => $dep['uri'], 'dep' => $dep);;
616 }
617
618 $testdep = $dep;
619 $testdep['package'] = $dep['name'];
620 if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
621 $dep['package'] = $dep['name'];
622 if (!isset($options['soft'])) {
623 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
624 ' dependency "' .
625 $this->_registry->parsedPackageNameToString($dep, true) .
626 '", will be installed');
627 }
628 return false;
629 }
630
631 $options = $this->_downloader->getOptions();
632 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
633 if ($this->_explicitState) {
634 $pname['state'] = $this->_explicitState;
635 }
636
637 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
638 if (PEAR::isError($url)) {
639 PEAR::popErrorHandling();
640 return $url;
641 }
642
643 $dep['package'] = $dep['name'];
644 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
645 !isset($options['alldeps']), true);
646 PEAR::popErrorHandling();
647 if (PEAR::isError($ret)) {
648 if (!isset($options['soft'])) {
649 $this->_downloader->log(0, $ret->getMessage());
650 }
651
652 return false;
653 }
654
655 // check to see if a dep is already installed and is the same or newer
656 if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
657 $oper = 'has';
658 } else {
659 $oper = 'gt';
660 }
661
662 // do not try to move this before getDepPackageDownloadURL
663 // we can't determine whether upgrade is necessary until we know what
664 // version would be downloaded
665 if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
666 $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
667 $dep['package'] = $dep['name'];
668 if (!isset($options['soft'])) {
669 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
670 ' dependency "' .
671 $this->_registry->parsedPackageNameToString($dep, true) .
672 '" version ' . $url['version'] . ', already installed as version ' .
673 $version);
674 }
675
676 return false;
677 }
678
679 if (isset($dep['nodefault'])) {
680 $ret['nodefault'] = true;
681 }
682
683 return $ret;
684 }
685
686 function _detect1($deps, $pname, $options, $params)
687 {
688 $this->_downloadDeps = array();
689 $skipnames = array();
690 foreach ($deps as $dep) {
691 $nodownload = false;
692 if (isset ($dep['type']) && $dep['type'] === 'pkg') {
693 $dep['channel'] = 'pear.php.net';
694 $dep['package'] = $dep['name'];
695 switch ($dep['rel']) {
696 case 'not' :
697 continue 2;
698 case 'ge' :
699 case 'eq' :
700 case 'gt' :
701 case 'has' :
702 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
703 'required' :
704 'optional';
705 if (PEAR_Downloader_Package::willDownload($dep, $params)) {
706 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
707 . ' dependency "' .
708 $this->_registry->parsedPackageNameToString($dep, true) .
709 '", will be installed');
710 continue 2;
711 }
712 $fakedp = new PEAR_PackageFile_v1;
713 $fakedp->setPackage($dep['name']);
714 // skip internet check if we are not upgrading (bug #5810)
715 if (!isset($options['upgrade']) && $this->isInstalled(
716 $fakedp, $dep['rel'])) {
717 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
718 . ' dependency "' .
719 $this->_registry->parsedPackageNameToString($dep, true) .
720 '", is already installed');
721 continue 2;
722 }
723 }
724
725 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
726 if ($this->_explicitState) {
727 $pname['state'] = $this->_explicitState;
728 }
729
730 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
731 $chan = 'pear.php.net';
732 if (PEAR::isError($url)) {
733 // check to see if this is a pecl package that has jumped
734 // from pear.php.net to pecl.php.net channel
735 if (!class_exists('PEAR_Dependency2')) {
736 require_once 'PEAR/Dependency2.php';
737 }
738
739 $newdep = PEAR_Dependency2::normalizeDep($dep);
740 $newdep = $newdep[0];
741 $newdep['channel'] = 'pecl.php.net';
742 $chan = 'pecl.php.net';
743 $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
744 $obj = &$this->_installRegistry->getPackage($dep['name']);
745 if (PEAR::isError($url)) {
746 PEAR::popErrorHandling();
747 if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
748 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
749 'required' :
750 'optional';
751 $dep['package'] = $dep['name'];
752 if (!isset($options['soft'])) {
753 $this->_downloader->log(3, $this->getShortName() .
754 ': Skipping ' . $group . ' dependency "' .
755 $this->_registry->parsedPackageNameToString($dep, true) .
756 '", already installed as version ' . $obj->getVersion());
757 }
758 $skip = count($skipnames) ?
759 $skipnames[count($skipnames) - 1] : '';
760 if ($skip ==
761 $this->_registry->parsedPackageNameToString($dep, true)) {
762 array_pop($skipnames);
763 }
764 continue;
765 } else {
766 if (isset($dep['optional']) && $dep['optional'] == 'yes') {
767 $this->_downloader->log(2, $this->getShortName() .
768 ': Skipping optional dependency "' .
769 $this->_registry->parsedPackageNameToString($dep, true) .
770 '", no releases exist');
771 continue;
772 } else {
773 return $url;
774 }
775 }
776 }
777 }
778
779 PEAR::popErrorHandling();
780 if (!isset($options['alldeps'])) {
781 if (isset($dep['optional']) && $dep['optional'] == 'yes') {
782 if (!isset($options['soft'])) {
783 $this->_downloader->log(3, 'Notice: package "' .
784 $this->getShortName() .
785 '" optional dependency "' .
786 $this->_registry->parsedPackageNameToString(
787 array('channel' => $chan, 'package' =>
788 $dep['name']), true) .
789 '" will not be automatically downloaded');
790 }
791 $skipnames[] = $this->_registry->parsedPackageNameToString(
792 array('channel' => $chan, 'package' =>
793 $dep['name']), true);
794 $nodownload = true;
795 }
796 }
797
798 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
799 if (!isset($dep['optional']) || $dep['optional'] == 'no') {
800 if (!isset($options['soft'])) {
801 $this->_downloader->log(3, 'Notice: package "' .
802 $this->getShortName() .
803 '" required dependency "' .
804 $this->_registry->parsedPackageNameToString(
805 array('channel' => $chan, 'package' =>
806 $dep['name']), true) .
807 '" will not be automatically downloaded');
808 }
809 $skipnames[] = $this->_registry->parsedPackageNameToString(
810 array('channel' => $chan, 'package' =>
811 $dep['name']), true);
812 $nodownload = true;
813 }
814 }
815
816 // check to see if a dep is already installed
817 // do not try to move this before getDepPackageDownloadURL
818 // we can't determine whether upgrade is necessary until we know what
819 // version would be downloaded
820 if (!isset($options['force']) && $this->isInstalled(
821 $url, $dep['rel'])) {
822 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
823 'required' :
824 'optional';
825 $dep['package'] = $dep['name'];
826 if (isset($newdep)) {
827 $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
828 } else {
829 $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
830 }
831
832 $dep['version'] = $url['version'];
833 if (!isset($options['soft'])) {
834 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
835 ' dependency "' .
836 $this->_registry->parsedPackageNameToString($dep, true) .
837 '", already installed as version ' . $version);
838 }
839
840 $skip = count($skipnames) ?
841 $skipnames[count($skipnames) - 1] : '';
842 if ($skip ==
843 $this->_registry->parsedPackageNameToString($dep, true)) {
844 array_pop($skipnames);
845 }
846
847 continue;
848 }
849
850 if ($nodownload) {
851 continue;
852 }
853
854 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
855 if (isset($newdep)) {
856 $dep = $newdep;
857 }
858
859 $dep['package'] = $dep['name'];
860 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
861 isset($dep['optional']) && $dep['optional'] == 'yes' &&
862 !isset($options['alldeps']), true);
863 PEAR::popErrorHandling();
864 if (PEAR::isError($ret)) {
865 if (!isset($options['soft'])) {
866 $this->_downloader->log(0, $ret->getMessage());
867 }
868 continue;
869 }
870
871 $this->_downloadDeps[] = $ret;
872 }
873 }
874
875 if (count($skipnames)) {
876 if (!isset($options['soft'])) {
877 $this->_downloader->log(1, 'Did not download dependencies: ' .
878 implode(', ', $skipnames) .
879 ', use --alldeps or --onlyreqdeps to download automatically');
880 }
881 }
882 }
883
884 function setDownloadURL($pkg)
885 {
886 $this->_downloadURL = $pkg;
887 }
888
894 function setPackageFile(&$pkg)
895 {
896 $this->_packagefile = &$pkg;
897 }
898
899 function getShortName()
900 {
901 return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
902 'package' => $this->getPackage()), true);
903 }
904
906 {
907 if (isset($this->_packagefile) || isset($this->_parsedname)) {
908 return array('channel' => $this->getChannel(),
909 'package' => $this->getPackage(),
910 'version' => $this->getVersion());
911 }
912
913 return false;
914 }
915
916 function getDownloadURL()
917 {
918 return $this->_downloadURL;
919 }
920
921 function canDefault()
922 {
923 if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
924 return false;
925 }
926
927 return true;
928 }
929
930 function getPackage()
931 {
932 if (isset($this->_packagefile)) {
933 return $this->_packagefile->getPackage();
934 } elseif (isset($this->_downloadURL['info'])) {
935 return $this->_downloadURL['info']->getPackage();
936 }
937
938 return false;
939 }
940
944 function isSubpackage(&$pf)
945 {
946 if (isset($this->_packagefile)) {
947 return $this->_packagefile->isSubpackage($pf);
948 } elseif (isset($this->_downloadURL['info'])) {
949 return $this->_downloadURL['info']->isSubpackage($pf);
950 }
951
952 return false;
953 }
954
955 function getPackageType()
956 {
957 if (isset($this->_packagefile)) {
958 return $this->_packagefile->getPackageType();
959 } elseif (isset($this->_downloadURL['info'])) {
960 return $this->_downloadURL['info']->getPackageType();
961 }
962
963 return false;
964 }
965
966 function isBundle()
967 {
968 if (isset($this->_packagefile)) {
969 return $this->_packagefile->getPackageType() == 'bundle';
970 }
971
972 return false;
973 }
974
976 {
977 if (isset($this->_packagefile)) {
978 return $this->_packagefile->getPackagexmlVersion();
979 } elseif (isset($this->_downloadURL['info'])) {
980 return $this->_downloadURL['info']->getPackagexmlVersion();
981 }
982
983 return '1.0';
984 }
985
986 function getChannel()
987 {
988 if (isset($this->_packagefile)) {
989 return $this->_packagefile->getChannel();
990 } elseif (isset($this->_downloadURL['info'])) {
991 return $this->_downloadURL['info']->getChannel();
992 }
993
994 return false;
995 }
996
997 function getURI()
998 {
999 if (isset($this->_packagefile)) {
1000 return $this->_packagefile->getURI();
1001 } elseif (isset($this->_downloadURL['info'])) {
1002 return $this->_downloadURL['info']->getURI();
1003 }
1004
1005 return false;
1006 }
1007
1008 function getVersion()
1009 {
1010 if (isset($this->_packagefile)) {
1011 return $this->_packagefile->getVersion();
1012 } elseif (isset($this->_downloadURL['version'])) {
1013 return $this->_downloadURL['version'];
1014 }
1015
1016 return false;
1017 }
1018
1019 function isCompatible($pf)
1020 {
1021 if (isset($this->_packagefile)) {
1022 return $this->_packagefile->isCompatible($pf);
1023 } elseif (isset($this->_downloadURL['info'])) {
1024 return $this->_downloadURL['info']->isCompatible($pf);
1025 }
1026
1027 return true;
1028 }
1029
1030 function setGroup($group)
1031 {
1032 $this->_parsedname['group'] = $group;
1033 }
1034
1035 function getGroup()
1036 {
1037 if (isset($this->_parsedname['group'])) {
1038 return $this->_parsedname['group'];
1039 }
1040
1041 return '';
1042 }
1043
1044 function isExtension($name)
1045 {
1046 if (isset($this->_packagefile)) {
1047 return $this->_packagefile->isExtension($name);
1048 } elseif (isset($this->_downloadURL['info'])) {
1049 if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
1050 return $this->_downloadURL['info']->getProvidesExtension() == $name;
1051 }
1052
1053 return false;
1054 }
1055
1056 return false;
1057 }
1058
1059 function getDeps()
1060 {
1061 if (isset($this->_packagefile)) {
1062 $ver = $this->_packagefile->getPackagexmlVersion();
1063 if (version_compare($ver, '2.0', '>=')) {
1064 return $this->_packagefile->getDeps(true);
1065 }
1066
1067 return $this->_packagefile->getDeps();
1068 } elseif (isset($this->_downloadURL['info'])) {
1069 $ver = $this->_downloadURL['info']->getPackagexmlVersion();
1070 if (version_compare($ver, '2.0', '>=')) {
1071 return $this->_downloadURL['info']->getDeps(true);
1072 }
1073
1074 return $this->_downloadURL['info']->getDeps();
1075 }
1076
1077 return array();
1078 }
1079
1084 function isEqual($param)
1085 {
1086 if (is_object($param)) {
1087 $channel = $param->getChannel();
1088 $package = $param->getPackage();
1089 if ($param->getURI()) {
1090 $param = array(
1091 'channel' => $param->getChannel(),
1092 'package' => $param->getPackage(),
1093 'version' => $param->getVersion(),
1094 'uri' => $param->getURI(),
1095 );
1096 } else {
1097 $param = array(
1098 'channel' => $param->getChannel(),
1099 'package' => $param->getPackage(),
1100 'version' => $param->getVersion(),
1101 );
1102 }
1103 } else {
1104 if (isset($param['uri'])) {
1105 if ($this->getChannel() != '__uri') {
1106 return false;
1107 }
1108 return $param['uri'] == $this->getURI();
1109 }
1110
1111 $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
1112 $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
1113 if (isset($param['rel'])) {
1114 if (!class_exists('PEAR_Dependency2')) {
1115 require_once 'PEAR/Dependency2.php';
1116 }
1117
1118 $newdep = PEAR_Dependency2::normalizeDep($param);
1119 $newdep = $newdep[0];
1120 } elseif (isset($param['min'])) {
1121 $newdep = $param;
1122 }
1123 }
1124
1125 if (isset($newdep)) {
1126 if (!isset($newdep['min'])) {
1127 $newdep['min'] = '0';
1128 }
1129
1130 if (!isset($newdep['max'])) {
1131 $newdep['max'] = '100000000000000000000';
1132 }
1133
1134 // use magic to support pecl packages suddenly jumping to the pecl channel
1135 // we need to support both dependency possibilities
1136 if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
1137 if ($package == $this->getPackage()) {
1138 $channel = 'pecl.php.net';
1139 }
1140 }
1141 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
1142 if ($package == $this->getPackage()) {
1143 $channel = 'pear.php.net';
1144 }
1145 }
1146
1147 return (strtolower($package) == strtolower($this->getPackage()) &&
1148 $channel == $this->getChannel() &&
1149 version_compare($newdep['min'], $this->getVersion(), '<=') &&
1150 version_compare($newdep['max'], $this->getVersion(), '>='));
1151 }
1152
1153 // use magic to support pecl packages suddenly jumping to the pecl channel
1154 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
1155 if (strtolower($package) == strtolower($this->getPackage())) {
1156 $channel = 'pear.php.net';
1157 }
1158 }
1159
1160 if (isset($param['version'])) {
1161 return (strtolower($package) == strtolower($this->getPackage()) &&
1162 $channel == $this->getChannel() &&
1163 $param['version'] == $this->getVersion());
1164 }
1165
1166 return strtolower($package) == strtolower($this->getPackage()) &&
1167 $channel == $this->getChannel();
1168 }
1169
1170 function isInstalled($dep, $oper = '==')
1171 {
1172 if (!$dep) {
1173 return false;
1174 }
1175
1176 if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
1177 return false;
1178 }
1179
1180 if (is_object($dep)) {
1181 $package = $dep->getPackage();
1182 $channel = $dep->getChannel();
1183 if ($dep->getURI()) {
1184 $dep = array(
1185 'uri' => $dep->getURI(),
1186 'version' => $dep->getVersion(),
1187 );
1188 } else {
1189 $dep = array(
1190 'version' => $dep->getVersion(),
1191 );
1192 }
1193 } else {
1194 if (isset($dep['uri'])) {
1195 $channel = '__uri';
1196 $package = $dep['dep']['name'];
1197 } else {
1198 $channel = $dep['info']->getChannel();
1199 $package = $dep['info']->getPackage();
1200 }
1201 }
1202
1203 $options = $this->_downloader->getOptions();
1204 $test = $this->_installRegistry->packageExists($package, $channel);
1205 if (!$test && $channel == 'pecl.php.net') {
1206 // do magic to allow upgrading from old pecl packages to new ones
1207 $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
1208 $channel = 'pear.php.net';
1209 }
1210
1211 if ($test) {
1212 if (isset($dep['uri'])) {
1213 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
1214 return true;
1215 }
1216 }
1217
1218 if (isset($options['upgrade'])) {
1219 $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
1220 if (version_compare($packageVersion, $dep['version'], '>=')) {
1221 return true;
1222 }
1223
1224 return false;
1225 }
1226
1227 return true;
1228 }
1229
1230 return false;
1231 }
1232
1244 public static function detectStupidDuplicates($params, &$errorparams)
1245 {
1246 $existing = array();
1247 foreach ($params as $i => $param) {
1248 $package = $param->getPackage();
1249 $channel = $param->getChannel();
1250 $group = $param->getGroup();
1251 if (!isset($existing[$channel . '/' . $package])) {
1252 $existing[$channel . '/' . $package] = array();
1253 }
1254
1255 if (!isset($existing[$channel . '/' . $package][$group])) {
1256 $existing[$channel . '/' . $package][$group] = array();
1257 }
1258
1259 $existing[$channel . '/' . $package][$group][] = $i;
1260 }
1261
1262 $indices = array();
1263 foreach ($existing as $package => $groups) {
1264 foreach ($groups as $group => $dupes) {
1265 if (count($dupes) > 1) {
1266 $indices = $indices + $dupes;
1267 }
1268 }
1269 }
1270
1271 $indices = array_unique($indices);
1272 foreach ($indices as $index) {
1273 $errorparams[] = $params[$index];
1274 }
1275
1276 return count($errorparams);
1277 }
1278
1283 public static function removeDuplicates(&$params, $ignoreGroups = false)
1284 {
1285 $pnames = array();
1286 foreach ($params as $i => $param) {
1287 if (!$param) {
1288 continue;
1289 }
1290
1291 if ($param->getPackage()) {
1292 $group = $ignoreGroups ? '' : $param->getGroup();
1293 $pnames[$i] = $param->getChannel() . '/' .
1294 $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
1295 }
1296 }
1297
1298 $pnames = array_unique($pnames);
1299 $unset = array_diff(array_keys($params), array_keys($pnames));
1300 $testp = array_flip($pnames);
1301 foreach ($params as $i => $param) {
1302 if (!$param) {
1303 $unset[] = $i;
1304 continue;
1305 }
1306
1307 if (!is_a($param, 'PEAR_Downloader_Package')) {
1308 $unset[] = $i;
1309 continue;
1310 }
1311
1312 $group = $ignoreGroups ? '' : $param->getGroup();
1313 if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
1314 $param->getVersion() . '#' . $group])) {
1315 $unset[] = $i;
1316 }
1317 }
1318
1319 foreach ($unset as $i) {
1320 unset($params[$i]);
1321 }
1322
1323 $ret = array();
1324 foreach ($params as $i => $param) {
1325 $ret[] = &$params[$i];
1326 }
1327
1328 $params = array();
1329 foreach ($ret as $i => $param) {
1330 $params[] = &$ret[$i];
1331 }
1332 }
1333
1334 function explicitState()
1335 {
1336 return $this->_explicitState;
1337 }
1338
1339 function setExplicitState($s)
1340 {
1341 $this->_explicitState = $s;
1342 }
1343
1346 public static function mergeDependencies(&$params)
1347 {
1348 $bundles = $newparams = array();
1349 foreach ($params as $i => $param) {
1350 if (!$param->isBundle()) {
1351 continue;
1352 }
1353
1354 $bundles[] = $i;
1355 $pf = &$param->getPackageFile();
1356 $newdeps = array();
1357 $contents = $pf->getBundledPackages();
1358 if (!is_array($contents)) {
1359 $contents = array($contents);
1360 }
1361
1362 foreach ($contents as $file) {
1363 $filecontents = $pf->getFileContents($file);
1364 $dl = &$param->getDownloader();
1365 $options = $dl->getOptions();
1366 if (PEAR::isError($dir = $dl->getDownloadDir())) {
1367 return $dir;
1368 }
1369
1370 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
1371 if (!$fp) {
1372 continue;
1373 }
1374
1375 // FIXME do symlink check
1376
1377 fwrite($fp, $filecontents, strlen($filecontents));
1378 fclose($fp);
1379 if ($s = $params[$i]->explicitState()) {
1380 $obj->setExplicitState($s);
1381 }
1382
1383 $obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
1384 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1385 if (PEAR::isError($dir = $dl->getDownloadDir())) {
1386 PEAR::popErrorHandling();
1387 return $dir;
1388 }
1389 $a = $dir . DIRECTORY_SEPARATOR . $file;
1390 $e = $obj->_fromFile($a);
1391 PEAR::popErrorHandling();
1392 if (PEAR::isError($e)) {
1393 if (!isset($options['soft'])) {
1394 $dl->log(0, $e->getMessage());
1395 }
1396 continue;
1397 }
1398
1400 array_merge($params, $newparams)) && !$param->isInstalled($obj)) {
1401 $newparams[] = $obj;
1402 }
1403 }
1404 }
1405
1406 foreach ($bundles as $i) {
1407 unset($params[$i]); // remove bundles - only their contents matter for installation
1408 }
1409
1410 PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
1411 if (count($newparams)) { // add in bundled packages for install
1412 foreach ($newparams as $i => $unused) {
1413 $params[] = &$newparams[$i];
1414 }
1415 $newparams = array();
1416 }
1417
1418 foreach ($params as $i => $param) {
1419 $newdeps = array();
1420 foreach ($param->_downloadDeps as $dep) {
1421 $merge = array_merge($params, $newparams);
1422 if (!PEAR_Downloader_Package::willDownload($dep, $merge)
1423 && !$param->isInstalled($dep)
1424 ) {
1425 $newdeps[] = $dep;
1426 } else {
1427 //var_dump($dep);
1428 // detect versioning conflicts here
1429 }
1430 }
1431
1432 // convert the dependencies into PEAR_Downloader_Package objects for the next time around
1433 $params[$i]->_downloadDeps = array();
1434 foreach ($newdeps as $dep) {
1435 $obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
1436 if ($s = $params[$i]->explicitState()) {
1437 $obj->setExplicitState($s);
1438 }
1439
1440 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1441 $e = $obj->fromDepURL($dep);
1442 PEAR::popErrorHandling();
1443 if (PEAR::isError($e)) {
1444 if (!isset($options['soft'])) {
1445 $obj->_downloader->log(0, $e->getMessage());
1446 }
1447 continue;
1448 }
1449
1450 $e = $obj->detectDependencies($params);
1451 if (PEAR::isError($e)) {
1452 if (!isset($options['soft'])) {
1453 $obj->_downloader->log(0, $e->getMessage());
1454 }
1455 }
1456
1457 $newparams[] = $obj;
1458 }
1459 }
1460
1461 if (count($newparams)) {
1462 foreach ($newparams as $i => $unused) {
1463 $params[] = &$newparams[$i];
1464 }
1465 return true;
1466 }
1467
1468 return false;
1469 }
1470
1471
1474 public static function willDownload($param, $params)
1475 {
1476 if (!is_array($params)) {
1477 return false;
1478 }
1479
1480 foreach ($params as $obj) {
1481 if ($obj->isEqual($param)) {
1482 return true;
1483 }
1484 }
1485
1486 return false;
1487 }
1488
1495 function &getPackagefileObject(&$c, $d)
1496 {
1497 $a = new PEAR_PackageFile($c, $d);
1498 return $a;
1499 }
1500
1507 function _fromFile(&$param)
1508 {
1509 $saveparam = $param;
1510 if (is_string($param) && substr($param, 0, 10) !== 'channel://') {
1511 if (!@file_exists($param)) {
1512 $test = explode('#', $param);
1513 $group = array_pop($test);
1514 if (@file_exists(implode('#', $test))) {
1515 $this->setGroup($group);
1516 $param = implode('#', $test);
1517 $this->_explicitGroup = true;
1518 }
1519 }
1520
1521 if (@is_file($param)) {
1522 $this->_type = 'local';
1523 $options = $this->_downloader->getOptions();
1524 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
1525 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1526 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
1527 PEAR::popErrorHandling();
1528 if (PEAR::isError($pf)) {
1529 $this->_valid = false;
1530 $param = $saveparam;
1531 return $pf;
1532 }
1533 $this->_packagefile = &$pf;
1534 if (!$this->getGroup()) {
1535 $this->setGroup('default'); // install the default dependency group
1536 }
1537 return $this->_valid = true;
1538 }
1539 }
1540 $param = $saveparam;
1541 return $this->_valid = false;
1542 }
1543
1544 function _fromUrl($param, $saveparam = '')
1545 {
1546 if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
1547 $options = $this->_downloader->getOptions();
1548 $this->_type = 'url';
1549 $callback = $this->_downloader->ui ?
1550 array(&$this->_downloader, '_downloadCallback') : null;
1551 $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
1552 if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
1553 $this->_downloader->popErrorHandling();
1554 return $dir;
1555 }
1556
1557 $this->_downloader->log(3, 'Downloading "' . $param . '"');
1558 $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
1559 $dir, $callback, null, false, $this->getChannel());
1560 $this->_downloader->popErrorHandling();
1561 if (PEAR::isError($file)) {
1562 if (!empty($saveparam)) {
1563 $saveparam = ", cannot download \"$saveparam\"";
1564 }
1565 $err = PEAR::raiseError('Could not download from "' . $param .
1566 '"' . $saveparam . ' (' . $file->getMessage() . ')');
1567 return $err;
1568 }
1569
1570 if ($this->_rawpackagefile) {
1571 require_once 'Archive/Tar.php';
1572 $tar = new Archive_Tar($file);
1573 $packagexml = $tar->extractInString('package2.xml');
1574 if (!$packagexml) {
1575 $packagexml = $tar->extractInString('package.xml');
1576 }
1577
1578 if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
1579 str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
1580 if ($this->getChannel() != 'pear.php.net') {
1581 return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
1582 'not match value returned from xml-rpc');
1583 }
1584
1585 // be more lax for the existing PEAR packages that have not-ok
1586 // characters in their package.xml
1587 $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
1588 $this->getPackage() . '" package has invalid characters in its ' .
1589 'package.xml. The next version of PEAR may not be able to install ' .
1590 'this package for security reasons. Please open a bug report at ' .
1591 'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
1592 }
1593 }
1594
1595 // whew, download worked!
1596 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
1597
1598 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1599 $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
1600 PEAR::popErrorHandling();
1601 if (PEAR::isError($pf)) {
1602 if (is_array($pf->getUserInfo())) {
1603 foreach ($pf->getUserInfo() as $err) {
1604 if (is_array($err)) {
1605 $err = $err['message'];
1606 }
1607
1608 if (!isset($options['soft'])) {
1609 $this->_downloader->log(0, "Validation Error: $err");
1610 }
1611 }
1612 }
1613
1614 if (!isset($options['soft'])) {
1615 $this->_downloader->log(0, $pf->getMessage());
1616 }
1617
1620 $out = $saveparam ? $saveparam : $param;
1621 $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
1622 $this->_valid = false;
1623 return $err;
1624 }
1625
1626 $this->_packagefile = &$pf;
1627 $this->setGroup('default'); // install the default dependency group
1628 return $this->_valid = true;
1629 }
1630
1631 return $this->_valid = false;
1632 }
1633
1644 function _fromString($param)
1645 {
1646 $options = $this->_downloader->getOptions();
1647 $channel = $this->_config->get('default_channel');
1648 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1649 $pname = $this->_registry->parsePackageName($param, $channel);
1650 PEAR::popErrorHandling();
1651 if (PEAR::isError($pname)) {
1652 if ($pname->getCode() == 'invalid') {
1653 $this->_valid = false;
1654 return false;
1655 }
1656
1657 if ($pname->getCode() == 'channel') {
1658 $parsed = $pname->getUserInfo();
1659 if ($this->_downloader->discover($parsed['channel'])) {
1660 if ($this->_config->get('auto_discover')) {
1661 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1662 $pname = $this->_registry->parsePackageName($param, $channel);
1663 PEAR::popErrorHandling();
1664 } else {
1665 if (!isset($options['soft'])) {
1666 $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
1667 '" is not initialized, use ' .
1668 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
1669 'or pear config-set auto_discover 1');
1670 }
1671 }
1672 }
1673
1674 if (PEAR::isError($pname)) {
1675 if (!isset($options['soft'])) {
1676 $this->_downloader->log(0, $pname->getMessage());
1677 }
1678
1679 if (is_array($param)) {
1680 $param = $this->_registry->parsedPackageNameToString($param);
1681 }
1682
1683 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
1684 $this->_valid = false;
1685 return $err;
1686 }
1687 } else {
1688 if (!isset($options['soft'])) {
1689 $this->_downloader->log(0, $pname->getMessage());
1690 }
1691
1692 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
1693 $this->_valid = false;
1694 return $err;
1695 }
1696 }
1697
1698 if (!isset($this->_type)) {
1699 $this->_type = 'rest';
1700 }
1701
1702 $this->_parsedname = $pname;
1703 $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
1704 $this->_explicitGroup = isset($pname['group']) ? true : false;
1705
1706 $info = $this->_downloader->_getPackageDownloadUrl($pname);
1707 if (PEAR::isError($info)) {
1708 if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
1709 // try pecl
1710 $pname['channel'] = 'pecl.php.net';
1711 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
1712 if (!PEAR::isError($test)) {
1713 $info = PEAR::raiseError($info->getMessage() . ' - package ' .
1714 $this->_registry->parsedPackageNameToString($pname, true) .
1715 ' can be installed with "pecl install ' . $pname['package'] .
1716 '"');
1717 } else {
1718 $pname['channel'] = 'pear.php.net';
1719 }
1720 } else {
1721 $pname['channel'] = 'pear.php.net';
1722 }
1723 }
1724
1725 return $info;
1726 }
1727
1728 $this->_rawpackagefile = $info['raw'];
1729 $ret = $this->_analyzeDownloadURL($info, $param, $pname);
1730 if (PEAR::isError($ret)) {
1731 return $ret;
1732 }
1733
1734 if ($ret) {
1735 $this->_downloadURL = $ret;
1736 return $this->_valid = (bool) $ret;
1737 }
1738 }
1739
1750 function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
1751 $isdependency = false)
1752 {
1753 if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
1754 return false;
1755 }
1756
1757 if ($info === false) {
1758 $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
1759
1760 // no releases exist
1761 return PEAR::raiseError('No releases for package "' .
1762 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
1763 }
1764
1765 if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
1766 $err = false;
1767 if ($pname['channel'] == 'pecl.php.net') {
1768 if ($info['info']->getChannel() != 'pear.php.net') {
1769 $err = true;
1770 }
1771 } elseif ($info['info']->getChannel() == 'pecl.php.net') {
1772 if ($pname['channel'] != 'pear.php.net') {
1773 $err = true;
1774 }
1775 } else {
1776 $err = true;
1777 }
1778
1779 if ($err) {
1780 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
1781 '" retrieved another channel\'s name for download! ("' .
1782 $info['info']->getChannel() . '")');
1783 }
1784 }
1785
1786 $preferred_state = $this->_config->get('preferred_state');
1787 if (!isset($info['url'])) {
1788 $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
1789 'version', $info['info']->getChannel());
1790 if ($this->isInstalled($info)) {
1791 if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
1792 // ignore bogus errors of "failed to download dependency"
1793 // if it is already installed and the one that would be
1794 // downloaded is older or the same version (Bug #7219)
1795 return false;
1796 }
1797 }
1798
1799 if ($info['version'] === $package_version) {
1800 if (!isset($options['soft'])) {
1801 $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
1802 '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
1803 ' (' . $package_version . ') is the same as the locally installed one.');
1804 }
1805
1806 return false;
1807 }
1808
1809 if (version_compare($info['version'], $package_version, '<=')) {
1810 if (!isset($options['soft'])) {
1811 $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
1812 '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
1813 ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
1814 }
1815
1816 return false;
1817 }
1818
1819 $instead = ', will instead download version ' . $info['version'] .
1820 ', stability "' . $info['info']->getState() . '"';
1821 // releases exist, but we failed to get any
1822 if (isset($this->_downloader->_options['force'])) {
1823 if (isset($pname['version'])) {
1824 $vs = ', version "' . $pname['version'] . '"';
1825 } elseif (isset($pname['state'])) {
1826 $vs = ', stability "' . $pname['state'] . '"';
1827 } elseif ($param == 'dependency') {
1828 if (!class_exists('PEAR_Common')) {
1829 require_once 'PEAR/Common.php';
1830 }
1831
1832 if (!in_array($info['info']->getState(),
1833 PEAR_Common::betterStates($preferred_state, true))) {
1834 if ($optional) {
1835 // don't spit out confusing error message
1836 return $this->_downloader->_getPackageDownloadUrl(
1837 array('package' => $pname['package'],
1838 'channel' => $pname['channel'],
1839 'version' => $info['version']));
1840 }
1841 $vs = ' within preferred state "' . $preferred_state .
1842 '"';
1843 } else {
1844 if (!class_exists('PEAR_Dependency2')) {
1845 require_once 'PEAR/Dependency2.php';
1846 }
1847
1848 if ($optional) {
1849 // don't spit out confusing error message
1850 return $this->_downloader->_getPackageDownloadUrl(
1851 array('package' => $pname['package'],
1852 'channel' => $pname['channel'],
1853 'version' => $info['version']));
1854 }
1856 $instead = '';
1857 }
1858 } else {
1859 $vs = ' within preferred state "' . $preferred_state . '"';
1860 }
1861
1862 if (!isset($options['soft'])) {
1863 $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
1864 '/' . $pname['package'] . $vs . $instead);
1865 }
1866
1867 // download the latest release
1868 return $this->_downloader->_getPackageDownloadUrl(
1869 array('package' => $pname['package'],
1870 'channel' => $pname['channel'],
1871 'version' => $info['version']));
1872 } else {
1873 if (isset($info['php']) && $info['php']) {
1874 $err = PEAR::raiseError('Failed to download ' .
1875 $this->_registry->parsedPackageNameToString(
1876 array('channel' => $pname['channel'],
1877 'package' => $pname['package']),
1878 true) .
1879 ', latest release is version ' . $info['php']['v'] .
1880 ', but it requires PHP version "' .
1881 $info['php']['m'] . '", use "' .
1882 $this->_registry->parsedPackageNameToString(
1883 array('channel' => $pname['channel'], 'package' => $pname['package'],
1884 'version' => $info['php']['v'])) . '" to install',
1886 return $err;
1887 }
1888
1889 // construct helpful error message
1890 if (isset($pname['version'])) {
1891 $vs = ', version "' . $pname['version'] . '"';
1892 } elseif (isset($pname['state'])) {
1893 $vs = ', stability "' . $pname['state'] . '"';
1894 } elseif ($param == 'dependency') {
1895 if (!class_exists('PEAR_Common')) {
1896 require_once 'PEAR/Common.php';
1897 }
1898
1899 if (!in_array($info['info']->getState(),
1900 PEAR_Common::betterStates($preferred_state, true))) {
1901 if ($optional) {
1902 // don't spit out confusing error message, and don't die on
1903 // optional dep failure!
1904 return $this->_downloader->_getPackageDownloadUrl(
1905 array('package' => $pname['package'],
1906 'channel' => $pname['channel'],
1907 'version' => $info['version']));
1908 }
1909 $vs = ' within preferred state "' . $preferred_state . '"';
1910 } else {
1911 if (!class_exists('PEAR_Dependency2')) {
1912 require_once 'PEAR/Dependency2.php';
1913 }
1914
1915 if ($optional) {
1916 // don't spit out confusing error message, and don't die on
1917 // optional dep failure!
1918 return $this->_downloader->_getPackageDownloadUrl(
1919 array('package' => $pname['package'],
1920 'channel' => $pname['channel'],
1921 'version' => $info['version']));
1922 }
1924 }
1925 } else {
1926 $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
1927 }
1928
1929 $options = $this->_downloader->getOptions();
1930 // this is only set by the "download-all" command
1931 if (isset($options['ignorepreferred_state'])) {
1932 $err = PEAR::raiseError(
1933 'Failed to download ' . $this->_registry->parsedPackageNameToString(
1934 array('channel' => $pname['channel'], 'package' => $pname['package']),
1935 true)
1936 . $vs .
1937 ', latest release is version ' . $info['version'] .
1938 ', stability "' . $info['info']->getState() . '", use "' .
1939 $this->_registry->parsedPackageNameToString(
1940 array('channel' => $pname['channel'], 'package' => $pname['package'],
1941 'version' => $info['version'])) . '" to install',
1943 return $err;
1944 }
1945
1946 // Checks if the user has a package installed already and checks the release against
1947 // the state against the installed package, this allows upgrades for packages
1948 // with lower stability than the preferred_state
1949 $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
1950 if (!$this->isInstalled($info)
1951 || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
1952 ) {
1953 $err = PEAR::raiseError(
1954 'Failed to download ' . $this->_registry->parsedPackageNameToString(
1955 array('channel' => $pname['channel'], 'package' => $pname['package']),
1956 true)
1957 . $vs .
1958 ', latest release is version ' . $info['version'] .
1959 ', stability "' . $info['info']->getState() . '", use "' .
1960 $this->_registry->parsedPackageNameToString(
1961 array('channel' => $pname['channel'], 'package' => $pname['package'],
1962 'version' => $info['version'])) . '" to install');
1963 return $err;
1964 }
1965 }
1966 }
1967
1968 if (isset($info['deprecated']) && $info['deprecated']) {
1969 $this->_downloader->log(0,
1970 'WARNING: "' .
1971 $this->_registry->parsedPackageNameToString(
1972 array('channel' => $info['info']->getChannel(),
1973 'package' => $info['info']->getPackage()), true) .
1974 '" is deprecated in favor of "' .
1975 $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
1976 '"');
1977 }
1978
1979 return $info;
1980 }
1981}
const PEAR_DOWNLOADER_PACKAGE_STATE
Definition Package.php:20
const PEAR_DOWNLOADER_PACKAGE_PHPVERSION
Definition Package.php:25
const PEAR_ERROR_RETURN
Definition PEAR.php:24
const PEAR_VALIDATE_INSTALLING
Definition Validate.php:18
static betterStates($state, $include=false)
Definition Common.php:307
static normalizeDep($dep)
static _getExtraString($dep)
_fromUrl($param, $saveparam='')
Definition Package.php:1544
_detect2($deps, $pname, $options, $params)
Definition Package.php:442
isInstalled($dep, $oper='==')
Definition Package.php:1170
static willDownload($param, $params)
Definition Package.php:1474
detectDependencies($params)
Definition Package.php:357
_detect2Dep($dep, $pname, $group, $params)
Definition Package.php:607
_analyzeDownloadURL($info, $param, $pname, $params=null, $optional=false, $isdependency=false)
Definition Package.php:1750
static removeInstalled(&$params)
Definition Package.php:400
static mergeDependencies(&$params)
Definition Package.php:1346
static removeDuplicates(&$params, $ignoreGroups=false)
Definition Package.php:1283
static detectStupidDuplicates($params, &$errorparams)
Definition Package.php:1244
& getPackagefileObject(&$c, $d)
Definition Package.php:1495
_detect1($deps, $pname, $options, $params)
Definition Package.php:686
__construct(&$downloader)
Definition Package.php:132
setPackage($package)
Definition v1.php:543
$options
Definition pearcmd.php:145