Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Validator.php
Go to the documentation of this file.
1<?php
29{
37 var $_pf;
45 var $_isValid = 0;
49 var $_filesValid = 0;
53 var $_curState = 0;
58 function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
59 {
60 $this->_pf = &$pf;
61 $this->_curState = $state;
62 $this->_packageInfo = $this->_pf->getArray();
63 $this->_isValid = $this->_pf->_isValid;
64 $this->_filesValid = $this->_pf->_filesValid;
65 $this->_stack = &$pf->_stack;
66 $this->_stack->getErrors(true);
67 if (($this->_isValid & $state) == $state) {
68 return true;
69 }
70 if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
71 return false;
72 }
73 if (!isset($this->_packageInfo['attribs']['version']) ||
74 ($this->_packageInfo['attribs']['version'] != '2.0' &&
75 $this->_packageInfo['attribs']['version'] != '2.1')
76 ) {
77 $this->_noPackageVersion();
78 }
79 $structure =
80 array(
81 'name',
82 'channel|uri',
83 '*extends', // can't be multiple, but this works fine
84 'summary',
85 'description',
86 '+lead', // these all need content checks
87 '*developer',
88 '*contributor',
89 '*helper',
90 'date',
91 '*time',
92 'version',
93 'stability',
94 'license->?uri->?filesource',
95 'notes',
96 'contents', //special validation needed
97 '*compatible',
98 'dependencies', //special validation needed
99 '*usesrole',
100 '*usestask', // reserve these for 1.4.0a1 to implement
101 // this will allow a package.xml to gracefully say it
102 // needs a certain package installed in order to implement a role or task
103 '*providesextension',
104 '*srcpackage|*srcuri',
105 '+phprelease|+extsrcrelease|+extbinrelease|' .
106 '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
107 '*changelog',
108 );
109 $test = $this->_packageInfo;
110 if (isset($test['dependencies']) &&
111 isset($test['dependencies']['required']) &&
112 isset($test['dependencies']['required']['pearinstaller']) &&
113 isset($test['dependencies']['required']['pearinstaller']['min']) &&
114 '1.10.18' != '@package' . '_version@' &&
115 version_compare('1.10.18',
116 $test['dependencies']['required']['pearinstaller']['min'], '<')
117 ) {
118 $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
119 return false;
120 }
121 // ignore post-installation array fields
122 if (array_key_exists('filelist', $test)) {
123 unset($test['filelist']);
124 }
125 if (array_key_exists('_lastmodified', $test)) {
126 unset($test['_lastmodified']);
127 }
128 if (array_key_exists('#binarypackage', $test)) {
129 unset($test['#binarypackage']);
130 }
131 if (array_key_exists('old', $test)) {
132 unset($test['old']);
133 }
134 if (array_key_exists('_lastversion', $test)) {
135 unset($test['_lastversion']);
136 }
137 if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
138 return false;
139 }
140 if (empty($this->_packageInfo['name'])) {
141 $this->_tagCannotBeEmpty('name');
142 }
143 $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
144 if (empty($this->_packageInfo[$test])) {
145 $this->_tagCannotBeEmpty($test);
146 }
147 if (is_array($this->_packageInfo['license']) &&
148 (!isset($this->_packageInfo['license']['_content']) ||
149 empty($this->_packageInfo['license']['_content']))) {
150 $this->_tagCannotBeEmpty('license');
151 } elseif (empty($this->_packageInfo['license'])) {
152 $this->_tagCannotBeEmpty('license');
153 }
154 if (empty($this->_packageInfo['summary'])) {
155 $this->_tagCannotBeEmpty('summary');
156 }
157 if (empty($this->_packageInfo['description'])) {
158 $this->_tagCannotBeEmpty('description');
159 }
160 if (empty($this->_packageInfo['date'])) {
161 $this->_tagCannotBeEmpty('date');
162 }
163 if (empty($this->_packageInfo['notes'])) {
164 $this->_tagCannotBeEmpty('notes');
165 }
166 if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
167 $this->_tagCannotBeEmpty('time');
168 }
169 if (isset($this->_packageInfo['dependencies'])) {
170 $this->_validateDependencies();
171 }
172 if (isset($this->_packageInfo['compatible'])) {
173 $this->_validateCompatible();
174 }
175 if (!isset($this->_packageInfo['bundle'])) {
176 if (empty($this->_packageInfo['contents'])) {
177 $this->_tagCannotBeEmpty('contents');
178 }
179 if (!isset($this->_packageInfo['contents']['dir'])) {
180 $this->_filelistMustContainDir('contents');
181 return false;
182 }
183 if (isset($this->_packageInfo['contents']['file'])) {
184 $this->_filelistCannotContainFile('contents');
185 return false;
186 }
187 }
188 $this->_validateMaintainers();
190 $fail = false;
191 if (array_key_exists('usesrole', $this->_packageInfo)) {
192 $roles = $this->_packageInfo['usesrole'];
193 if (!is_array($roles) || !isset($roles[0])) {
194 $roles = array($roles);
195 }
196 foreach ($roles as $role) {
197 if (!isset($role['role'])) {
198 $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
199 $fail = true;
200 } else {
201 if (!isset($role['channel'])) {
202 if (!isset($role['uri'])) {
203 $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
204 $fail = true;
205 }
206 } elseif (!isset($role['package'])) {
207 $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
208 $fail = true;
209 }
210 }
211 }
212 }
213 if (array_key_exists('usestask', $this->_packageInfo)) {
214 $roles = $this->_packageInfo['usestask'];
215 if (!is_array($roles) || !isset($roles[0])) {
216 $roles = array($roles);
217 }
218 foreach ($roles as $role) {
219 if (!isset($role['task'])) {
220 $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
221 $fail = true;
222 } else {
223 if (!isset($role['channel'])) {
224 if (!isset($role['uri'])) {
225 $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
226 $fail = true;
227 }
228 } elseif (!isset($role['package'])) {
229 $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
230 $fail = true;
231 }
232 }
233 }
234 }
235
236 if ($fail) {
237 return false;
238 }
239
240 $list = $this->_packageInfo['contents'];
241 if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
243 return $this->_isValid = 0;
244 }
245
246 $this->_validateFilelist();
247 $this->_validateRelease();
248 if (!$this->_stack->hasErrors()) {
249 $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
250 if (PEAR::isError($chan)) {
251 $this->_unknownChannel($this->_pf->getChannel());
252 } else {
253 $valpack = $chan->getValidationPackage();
254 // for channel validator packages, always use the default PEAR validator.
255 // otherwise, they can't be installed or packaged
256 $validator = $chan->getValidationObject($this->_pf->getPackage());
257 if (!$validator) {
258 $this->_stack->push(__FUNCTION__, 'error',
259 array('channel' => $chan->getName(),
260 'package' => $this->_pf->getPackage(),
261 'name' => $valpack['_content'],
262 'version' => $valpack['attribs']['version']),
263 'package "%channel%/%package%" cannot be properly validated without ' .
264 'validation package "%channel%/%name%-%version%"');
265 return $this->_isValid = 0;
266 }
267 $validator->setPackageFile($this->_pf);
268 $validator->validate($state);
269 $failures = $validator->getFailures();
270 foreach ($failures['errors'] as $error) {
271 $this->_stack->push(__FUNCTION__, 'error', $error,
272 'Channel validator error: field "%field%" - %reason%');
273 }
274 foreach ($failures['warnings'] as $warning) {
275 $this->_stack->push(__FUNCTION__, 'warning', $warning,
276 'Channel validator warning: field "%field%" - %reason%');
277 }
278 }
279 }
280
281 $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
282 if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
283 if ($this->_pf->getPackageType() == 'bundle') {
284 if ($this->_analyzeBundledPackages()) {
285 $this->_filesValid = $this->_pf->_filesValid = true;
286 } else {
287 $this->_pf->_isValid = $this->_isValid = 0;
288 }
289 } else {
290 if (!$this->_analyzePhpFiles()) {
291 $this->_pf->_isValid = $this->_isValid = 0;
292 } else {
293 $this->_filesValid = $this->_pf->_filesValid = true;
294 }
295 }
296 }
297
298 if ($this->_isValid) {
299 return $this->_pf->_isValid = $this->_isValid = $state;
300 }
301
302 return $this->_pf->_isValid = $this->_isValid = 0;
303 }
304
305 function _stupidSchemaValidate($structure, $xml, $root)
306 {
307 if (!is_array($xml)) {
308 $xml = array();
309 }
310 $keys = array_keys($xml);
311 reset($keys);
312 $key = current($keys);
313 while ($key == 'attribs' || $key == '_contents') {
314 $key = next($keys);
315 }
316 $unfoundtags = $optionaltags = array();
317 $ret = true;
318 $mismatch = false;
319 foreach ($structure as $struc) {
320 if ($key) {
321 $tag = $xml[$key];
322 }
323 $test = $this->_processStructure($struc);
324 if (isset($test['choices'])) {
325 $loose = true;
326 foreach ($test['choices'] as $choice) {
327 if ($key == $choice['tag']) {
328 $key = next($keys);
329 while ($key == 'attribs' || $key == '_contents') {
330 $key = next($keys);
331 }
332 $unfoundtags = $optionaltags = array();
333 $mismatch = false;
334 if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
335 $unfoundtags[] = $choice['tag'];
336 $optionaltags[] = $choice['tag'];
337 if ($key) {
338 $mismatch = true;
339 }
340 }
341 $ret &= $this->_processAttribs($choice, $tag, $root);
342 continue 2;
343 } else {
344 $unfoundtags[] = $choice['tag'];
345 $mismatch = true;
346 }
347 if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
348 $loose = false;
349 } else {
350 $optionaltags[] = $choice['tag'];
351 }
352 }
353 if (!$loose) {
354 $this->_invalidTagOrder($unfoundtags, $key, $root);
355 return false;
356 }
357 } else {
358 if ($key != $test['tag']) {
359 if (isset($test['multiple']) && $test['multiple'] != '*') {
360 $unfoundtags[] = $test['tag'];
361 $this->_invalidTagOrder($unfoundtags, $key, $root);
362 return false;
363 } else {
364 if ($key) {
365 $mismatch = true;
366 }
367 $unfoundtags[] = $test['tag'];
368 $optionaltags[] = $test['tag'];
369 }
370 if (!isset($test['multiple'])) {
371 $this->_invalidTagOrder($unfoundtags, $key, $root);
372 return false;
373 }
374 continue;
375 } else {
376 $unfoundtags = $optionaltags = array();
377 $mismatch = false;
378 }
379 $key = next($keys);
380 while ($key == 'attribs' || $key == '_contents') {
381 $key = next($keys);
382 }
383 if ($key && $key != $test['tag'] && isset($test['multiple'])) {
384 $unfoundtags[] = $test['tag'];
385 $optionaltags[] = $test['tag'];
386 $mismatch = true;
387 }
388 $ret &= $this->_processAttribs($test, $tag, $root);
389 continue;
390 }
391 }
392 if (!$mismatch && count($optionaltags)) {
393 // don't error out on any optional tags
394 $unfoundtags = array_diff($unfoundtags, $optionaltags);
395 }
396 if (count($unfoundtags)) {
397 $this->_invalidTagOrder($unfoundtags, $key, $root);
398 } elseif ($key) {
399 // unknown tags
400 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
401 while ($key = next($keys)) {
402 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
403 }
404 }
405 return $ret;
406 }
407
408 function _processAttribs($choice, $tag, $context)
409 {
410 if (isset($choice['attribs'])) {
411 if (!is_array($tag)) {
412 $tag = array($tag);
413 }
414 $tags = $tag;
415 if (!isset($tags[0])) {
416 $tags = array($tags);
417 }
418 $ret = true;
419 foreach ($tags as $i => $tag) {
420 if (!is_array($tag) || !isset($tag['attribs'])) {
421 foreach ($choice['attribs'] as $attrib) {
422 if ($attrib[0] != '?') {
423 $ret &= $this->_tagHasNoAttribs($choice['tag'],
424 $context);
425 continue 2;
426 }
427 }
428 }
429 foreach ($choice['attribs'] as $attrib) {
430 if ($attrib[0] != '?') {
431 if (!isset($tag['attribs'][$attrib])) {
432 $ret &= $this->_tagMissingAttribute($choice['tag'],
433 $attrib, $context);
434 }
435 }
436 }
437 }
438 return $ret;
439 }
440 return true;
441 }
442
443 function _processStructure($key)
444 {
445 $ret = array();
446 if (count($pieces = explode('|', $key)) > 1) {
447 $ret['choices'] = array();
448 foreach ($pieces as $piece) {
449 $ret['choices'][] = $this->_processStructure($piece);
450 }
451 return $ret;
452 }
453 $multi = $key[0];
454 if ($multi == '+' || $multi == '*') {
455 $ret['multiple'] = $key[0];
456 $key = substr($key, 1);
457 }
458 if (count($attrs = explode('->', $key)) > 1) {
459 $ret['tag'] = array_shift($attrs);
460 $ret['attribs'] = $attrs;
461 } else {
462 $ret['tag'] = $key;
463 }
464 return $ret;
465 }
466
468 {
469 $structure = array('release', 'api');
470 $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
471 $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
472 if ($a) {
473 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
474 $this->_packageInfo['version']['release'])) {
475 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
476 }
477 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
478 $this->_packageInfo['version']['api'])) {
479 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
480 }
481 if (!in_array($this->_packageInfo['stability']['release'],
482 array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
483 $this->_invalidState('release', $this->_packageInfo['stability']['release']);
484 }
485 if (!in_array($this->_packageInfo['stability']['api'],
486 array('devel', 'alpha', 'beta', 'stable'))) {
487 $this->_invalidState('api', $this->_packageInfo['stability']['api']);
488 }
489 }
490 }
491
493 {
494 $structure =
495 array(
496 'name',
497 'user',
498 'email',
499 'active',
500 );
501 foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
502 if (!isset($this->_packageInfo[$type])) {
503 continue;
504 }
505 if (isset($this->_packageInfo[$type][0])) {
506 foreach ($this->_packageInfo[$type] as $lead) {
507 $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
508 }
509 } else {
510 $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
511 '<' . $type . '>');
512 }
513 }
514 }
515
516 function _validatePhpDep($dep, $installcondition = false)
517 {
518 $structure = array(
519 'min',
520 '*max',
521 '*exclude',
522 );
523 $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
524 $this->_stupidSchemaValidate($structure, $dep, $type);
525 if (isset($dep['min'])) {
526 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
527 $dep['min'])) {
528 $this->_invalidVersion($type . '<min>', $dep['min']);
529 }
530 }
531 if (isset($dep['max'])) {
532 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
533 $dep['max'])) {
534 $this->_invalidVersion($type . '<max>', $dep['max']);
535 }
536 }
537 if (isset($dep['exclude'])) {
538 if (!is_array($dep['exclude'])) {
539 $dep['exclude'] = array($dep['exclude']);
540 }
541 foreach ($dep['exclude'] as $exclude) {
542 if (!preg_match(
543 '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
544 $exclude)) {
545 $this->_invalidVersion($type . '<exclude>', $exclude);
546 }
547 }
548 }
549 }
550
552 {
553 $structure = array(
554 'min',
555 '*max',
556 '*recommended',
557 '*exclude',
558 );
559 $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
560 if (isset($dep['min'])) {
561 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
562 $dep['min'])) {
563 $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
564 $dep['min']);
565 }
566 }
567 if (isset($dep['max'])) {
568 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
569 $dep['max'])) {
570 $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
571 $dep['max']);
572 }
573 }
574 if (isset($dep['recommended'])) {
575 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
576 $dep['recommended'])) {
577 $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
578 $dep['recommended']);
579 }
580 }
581 if (isset($dep['exclude'])) {
582 if (!is_array($dep['exclude'])) {
583 $dep['exclude'] = array($dep['exclude']);
584 }
585 foreach ($dep['exclude'] as $exclude) {
586 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
587 $exclude)) {
588 $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
589 $exclude);
590 }
591 }
592 }
593 }
594
595 function _validatePackageDep($dep, $group, $type = '<package>')
596 {
597 if (isset($dep['uri'])) {
598 if (isset($dep['conflicts'])) {
599 $structure = array(
600 'name',
601 'uri',
602 'conflicts',
603 '*providesextension',
604 );
605 } else {
606 $structure = array(
607 'name',
608 'uri',
609 '*providesextension',
610 );
611 }
612 } else {
613 if (isset($dep['conflicts'])) {
614 $structure = array(
615 'name',
616 'channel',
617 '*min',
618 '*max',
619 '*exclude',
620 'conflicts',
621 '*providesextension',
622 );
623 } else {
624 $structure = array(
625 'name',
626 'channel',
627 '*min',
628 '*max',
629 '*recommended',
630 '*exclude',
631 '*nodefault',
632 '*providesextension',
633 );
634 }
635 }
636 if (isset($dep['name'])) {
637 $type .= '<name>' . $dep['name'] . '</name>';
638 }
639 $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
640 if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
641 isset($dep['recommended']) || isset($dep['exclude']))) {
642 $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
643 }
644 if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
645 $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
646 }
647 if (isset($dep['min'])) {
648 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
649 $dep['min'])) {
650 $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
651 }
652 }
653 if (isset($dep['max'])) {
654 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
655 $dep['max'])) {
656 $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
657 }
658 }
659 if (isset($dep['recommended'])) {
660 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
661 $dep['recommended'])) {
662 $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
663 $dep['recommended']);
664 }
665 }
666 if (isset($dep['exclude'])) {
667 if (!is_array($dep['exclude'])) {
668 $dep['exclude'] = array($dep['exclude']);
669 }
670 foreach ($dep['exclude'] as $exclude) {
671 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
672 $exclude)) {
673 $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
674 $exclude);
675 }
676 }
677 }
678 }
679
680 function _validateSubpackageDep($dep, $group)
681 {
682 $this->_validatePackageDep($dep, $group, '<subpackage>');
683 if (isset($dep['providesextension'])) {
684 $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
685 }
686 if (isset($dep['conflicts'])) {
687 $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
688 }
689 }
690
691 function _validateExtensionDep($dep, $group = false, $installcondition = false)
692 {
693 if (isset($dep['conflicts'])) {
694 $structure = array(
695 'name',
696 '*min',
697 '*max',
698 '*exclude',
699 'conflicts',
700 );
701 } else {
702 $structure = array(
703 'name',
704 '*min',
705 '*max',
706 '*recommended',
707 '*exclude',
708 );
709 }
710 if ($installcondition) {
711 $type = '<installcondition><extension>';
712 } else {
713 $type = '<dependencies>' . $group . '<extension>';
714 }
715 if (isset($dep['name'])) {
716 $type .= '<name>' . $dep['name'] . '</name>';
717 }
718 $this->_stupidSchemaValidate($structure, $dep, $type);
719 if (isset($dep['min'])) {
720 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
721 $dep['min'])) {
722 $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
723 }
724 }
725 if (isset($dep['max'])) {
726 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
727 $dep['max'])) {
728 $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
729 }
730 }
731 if (isset($dep['recommended'])) {
732 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
733 $dep['recommended'])) {
734 $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
735 }
736 }
737 if (isset($dep['exclude'])) {
738 if (!is_array($dep['exclude'])) {
739 $dep['exclude'] = array($dep['exclude']);
740 }
741 foreach ($dep['exclude'] as $exclude) {
742 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
743 $exclude)) {
744 $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
745 }
746 }
747 }
748 }
749
750 function _validateOsDep($dep, $installcondition = false)
751 {
752 $structure = array(
753 'name',
754 '*conflicts',
755 );
756 $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
757 if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
758 if ($dep['name'] == '*') {
759 if (array_key_exists('conflicts', $dep)) {
760 $this->_cannotConflictWithAllOs($type);
761 }
762 }
763 }
764 }
765
766 function _validateArchDep($dep, $installcondition = false)
767 {
768 $structure = array(
769 'pattern',
770 '*conflicts',
771 );
772 $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
773 $this->_stupidSchemaValidate($structure, $dep, $type);
774 }
775
776 function _validateInstallConditions($cond, $release)
777 {
778 $structure = array(
779 '*php',
780 '*extension',
781 '*os',
782 '*arch',
783 );
784 if (!$this->_stupidSchemaValidate($structure,
785 $cond, $release)) {
786 return false;
787 }
788 foreach (array('php', 'extension', 'os', 'arch') as $type) {
789 if (isset($cond[$type])) {
790 $iter = $cond[$type];
791 if (!is_array($iter) || !isset($iter[0])) {
792 $iter = array($iter);
793 }
794 foreach ($iter as $package) {
795 if ($type == 'extension') {
796 $this->{"_validate{$type}Dep"}($package, false, true);
797 } else {
798 $this->{"_validate{$type}Dep"}($package, true);
799 }
800 }
801 }
802 }
803 }
804
806 {
807 $structure = array(
808 'required',
809 '*optional',
810 '*group->name->hint'
811 );
812 if (!$this->_stupidSchemaValidate($structure,
813 $this->_packageInfo['dependencies'], '<dependencies>')) {
814 return false;
815 }
816 foreach (array('required', 'optional') as $simpledep) {
817 if (isset($this->_packageInfo['dependencies'][$simpledep])) {
818 if ($simpledep == 'optional') {
819 $structure = array(
820 '*package',
821 '*subpackage',
822 '*extension',
823 );
824 } else {
825 $structure = array(
826 'php',
827 'pearinstaller',
828 '*package',
829 '*subpackage',
830 '*extension',
831 '*os',
832 '*arch',
833 );
834 }
835 if ($this->_stupidSchemaValidate($structure,
836 $this->_packageInfo['dependencies'][$simpledep],
837 "<dependencies><$simpledep>")) {
838 foreach (array('package', 'subpackage', 'extension') as $type) {
839 if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
840 $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
841 if (!isset($iter[0])) {
842 $iter = array($iter);
843 }
844 foreach ($iter as $package) {
845 if ($type != 'extension') {
846 if (isset($package['uri'])) {
847 if (isset($package['channel'])) {
848 $this->_UrlOrChannel($type,
849 $package['name']);
850 }
851 } else {
852 if (!isset($package['channel'])) {
853 $this->_NoChannel($type, $package['name']);
854 }
855 }
856 }
857 $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
858 }
859 }
860 }
861 if ($simpledep == 'optional') {
862 continue;
863 }
864 foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
865 if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
866 $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
867 if (!isset($iter[0])) {
868 $iter = array($iter);
869 }
870 foreach ($iter as $package) {
871 $this->{"_validate{$type}Dep"}($package);
872 }
873 }
874 }
875 }
876 }
877 }
878 if (isset($this->_packageInfo['dependencies']['group'])) {
879 $groups = $this->_packageInfo['dependencies']['group'];
880 if (!isset($groups[0])) {
881 $groups = array($groups);
882 }
883 $structure = array(
884 '*package',
885 '*subpackage',
886 '*extension',
887 );
888 foreach ($groups as $group) {
889 if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
890 if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
891 $this->_invalidDepGroupName($group['attribs']['name']);
892 }
893 foreach (array('package', 'subpackage', 'extension') as $type) {
894 if (isset($group[$type])) {
895 $iter = $group[$type];
896 if (!isset($iter[0])) {
897 $iter = array($iter);
898 }
899 foreach ($iter as $package) {
900 if ($type != 'extension') {
901 if (isset($package['uri'])) {
902 if (isset($package['channel'])) {
903 $this->_UrlOrChannelGroup($type,
904 $package['name'],
905 $group['name']);
906 }
907 } else {
908 if (!isset($package['channel'])) {
909 $this->_NoChannelGroup($type,
910 $package['name'],
911 $group['name']);
912 }
913 }
914 }
915 $this->{"_validate{$type}Dep"}($package, '<group name="' .
916 $group['attribs']['name'] . '">');
917 }
918 }
919 }
920 }
921 }
922 }
923 }
924
926 {
927 $compat = $this->_packageInfo['compatible'];
928 if (!isset($compat[0])) {
929 $compat = array($compat);
930 }
931 $required = array('name', 'channel', 'min', 'max', '*exclude');
932 foreach ($compat as $package) {
933 $type = '<compatible>';
934 if (is_array($package) && array_key_exists('name', $package)) {
935 $type .= '<name>' . $package['name'] . '</name>';
936 }
937 $this->_stupidSchemaValidate($required, $package, $type);
938 if (is_array($package) && array_key_exists('min', $package)) {
939 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
940 $package['min'])) {
941 $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
942 }
943 }
944 if (is_array($package) && array_key_exists('max', $package)) {
945 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
946 $package['max'])) {
947 $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
948 }
949 }
950 if (is_array($package) && array_key_exists('exclude', $package)) {
951 if (!is_array($package['exclude'])) {
952 $package['exclude'] = array($package['exclude']);
953 }
954 foreach ($package['exclude'] as $exclude) {
955 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
956 $exclude)) {
957 $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
958 }
959 }
960 }
961 }
962 }
963
964 function _validateBundle($list)
965 {
966 if (!is_array($list) || !isset($list['bundledpackage'])) {
967 return $this->_NoBundledPackages();
968 }
969 if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
970 return $this->_AtLeast2BundledPackages();
971 }
972 foreach ($list['bundledpackage'] as $package) {
973 if (!is_string($package)) {
975 }
976 }
977 }
978
979 function _validateFilelist($list = false, $allowignore = false, $dirs = '')
980 {
981 $iscontents = false;
982 if (!$list) {
983 $iscontents = true;
984 $list = $this->_packageInfo['contents'];
985 if (isset($this->_packageInfo['bundle'])) {
986 return $this->_validateBundle($list);
987 }
988 }
989 if ($allowignore) {
990 $struc = array(
991 '*install->name->as',
992 '*ignore->name'
993 );
994 } else {
995 $struc = array(
996 '*dir->name->?baseinstalldir',
997 '*file->name->role->?baseinstalldir->?md5sum'
998 );
999 if (isset($list['dir']) && isset($list['file'])) {
1000 // stave off validation errors without requiring a set order.
1001 $_old = $list;
1002 if (isset($list['attribs'])) {
1003 $list = array('attribs' => $_old['attribs']);
1004 }
1005 $list['dir'] = $_old['dir'];
1006 $list['file'] = $_old['file'];
1007 }
1008 }
1009 if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
1010 $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
1011 $dirname = $iscontents ? '<contents>' : $unknown;
1012 } else {
1013 $dirname = '<dir name="' . $list['attribs']['name'] . '">';
1014 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
1015 str_replace('\\', '/', $list['attribs']['name']))) {
1016 // file contains .. parent directory or . cur directory
1017 $this->_invalidDirName($list['attribs']['name']);
1018 }
1019 }
1020 $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
1021 if ($allowignore && $res) {
1022 $ignored_or_installed = array();
1023 $this->_pf->getFilelist();
1024 $fcontents = $this->_pf->getContents();
1025 $filelist = array();
1026 if (!isset($fcontents['dir']['file'][0])) {
1027 $fcontents['dir']['file'] = array($fcontents['dir']['file']);
1028 }
1029 foreach ($fcontents['dir']['file'] as $file) {
1030 $filelist[$file['attribs']['name']] = true;
1031 }
1032 if (isset($list['install'])) {
1033 if (!isset($list['install'][0])) {
1034 $list['install'] = array($list['install']);
1035 }
1036 foreach ($list['install'] as $file) {
1037 if (!isset($filelist[$file['attribs']['name']])) {
1038 $this->_notInContents($file['attribs']['name'], 'install');
1039 continue;
1040 }
1041 if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1042 $this->_multipleInstallAs($file['attribs']['name']);
1043 }
1044 if (!isset($ignored_or_installed[$file['attribs']['name']])) {
1045 $ignored_or_installed[$file['attribs']['name']] = array();
1046 }
1047 $ignored_or_installed[$file['attribs']['name']][] = 1;
1048 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
1049 str_replace('\\', '/', $file['attribs']['as']))) {
1050 // file contains .. parent directory or . cur directory references
1051 $this->_invalidFileInstallAs($file['attribs']['name'],
1052 $file['attribs']['as']);
1053 }
1054 }
1055 }
1056 if (isset($list['ignore'])) {
1057 if (!isset($list['ignore'][0])) {
1058 $list['ignore'] = array($list['ignore']);
1059 }
1060 foreach ($list['ignore'] as $file) {
1061 if (!isset($filelist[$file['attribs']['name']])) {
1062 $this->_notInContents($file['attribs']['name'], 'ignore');
1063 continue;
1064 }
1065 if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
1066 $this->_ignoreAndInstallAs($file['attribs']['name']);
1067 }
1068 }
1069 }
1070 }
1071 if (!$allowignore && isset($list['file'])) {
1072 if (is_string($list['file'])) {
1073 $this->_oldStyleFileNotAllowed();
1074 return false;
1075 }
1076 if (!isset($list['file'][0])) {
1077 // single file
1078 $list['file'] = array($list['file']);
1079 }
1080 foreach ($list['file'] as $i => $file)
1081 {
1082 if (isset($file['attribs']) && isset($file['attribs']['name'])) {
1083 if ($file['attribs']['name'][0] == '.' &&
1084 $file['attribs']['name'][1] == '/') {
1085 // name is something like "./doc/whatever.txt"
1086 $this->_invalidFileName($file['attribs']['name'], $dirname);
1087 }
1088 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
1089 str_replace('\\', '/', $file['attribs']['name']))) {
1090 // file contains .. parent directory or . cur directory
1091 $this->_invalidFileName($file['attribs']['name'], $dirname);
1092 }
1093 }
1094 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
1095 if (!$this->_validateRole($file['attribs']['role'])) {
1096 if (isset($this->_packageInfo['usesrole'])) {
1097 $roles = $this->_packageInfo['usesrole'];
1098 if (!isset($roles[0])) {
1099 $roles = array($roles);
1100 }
1101 foreach ($roles as $role) {
1102 if ($role['role'] = $file['attribs']['role']) {
1103 $msg = 'This package contains role "%role%" and requires ' .
1104 'package "%package%" to be used';
1105 if (isset($role['uri'])) {
1106 $params = array('role' => $role['role'],
1107 'package' => $role['uri']);
1108 } else {
1109 $params = array('role' => $role['role'],
1110 'package' => $this->_pf->_registry->
1111 parsedPackageNameToString(array('package' =>
1112 $role['package'], 'channel' => $role['channel']),
1113 true));
1114 }
1115 $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
1116 }
1117 }
1118 }
1119 $this->_invalidFileRole($file['attribs']['name'],
1120 $dirname, $file['attribs']['role']);
1121 }
1122 }
1123 if (!isset($file['attribs'])) {
1124 continue;
1125 }
1126 $save = $file['attribs'];
1127 if ($dirs) {
1128 $save['name'] = $dirs . '/' . $save['name'];
1129 }
1130 unset($file['attribs']);
1131 if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
1132 foreach ($file as $task => $value) {
1133 if ($tagClass = $this->_pf->getTask($task)) {
1134 if (!is_array($value) || !isset($value[0])) {
1135 $value = array($value);
1136 }
1137 foreach ($value as $v) {
1138 $ret = call_user_func(array($tagClass, 'validateXml'),
1139 $this->_pf, $v, $this->_pf->_config, $save);
1140 if (is_array($ret)) {
1141 $this->_invalidTask($task, $ret, isset($save['name']) ?
1142 $save['name'] : '');
1143 }
1144 }
1145 } else {
1146 if (isset($this->_packageInfo['usestask'])) {
1147 $roles = $this->_packageInfo['usestask'];
1148 if (!isset($roles[0])) {
1149 $roles = array($roles);
1150 }
1151 foreach ($roles as $role) {
1152 if ($role['task'] = $task) {
1153 $msg = 'This package contains task "%task%" and requires ' .
1154 'package "%package%" to be used';
1155 if (isset($role['uri'])) {
1156 $params = array('task' => $role['task'],
1157 'package' => $role['uri']);
1158 } else {
1159 $params = array('task' => $role['task'],
1160 'package' => $this->_pf->_registry->
1161 parsedPackageNameToString(array('package' =>
1162 $role['package'], 'channel' => $role['channel']),
1163 true));
1164 }
1165 $this->_stack->push('_mustInstallTask', 'error',
1166 $params, $msg);
1167 }
1168 }
1169 }
1170 $this->_unknownTask($task, $save['name']);
1171 }
1172 }
1173 }
1174 }
1175 }
1176 if (isset($list['ignore'])) {
1177 if (!$allowignore) {
1178 $this->_ignoreNotAllowed('ignore');
1179 }
1180 }
1181 if (isset($list['install'])) {
1182 if (!$allowignore) {
1183 $this->_ignoreNotAllowed('install');
1184 }
1185 }
1186 if (isset($list['file'])) {
1187 if ($allowignore) {
1188 $this->_fileNotAllowed('file');
1189 }
1190 }
1191 if (isset($list['dir'])) {
1192 if ($allowignore) {
1193 $this->_fileNotAllowed('dir');
1194 } else {
1195 if (!isset($list['dir'][0])) {
1196 $list['dir'] = array($list['dir']);
1197 }
1198 foreach ($list['dir'] as $dir) {
1199 if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
1200 if ($dir['attribs']['name'] == '/' ||
1201 !isset($this->_packageInfo['contents']['dir']['dir'])) {
1202 // always use nothing if the filelist has already been flattened
1203 $newdirs = '';
1204 } elseif ($dirs == '') {
1205 $newdirs = $dir['attribs']['name'];
1206 } else {
1207 $newdirs = $dirs . '/' . $dir['attribs']['name'];
1208 }
1209 } else {
1210 $newdirs = $dirs;
1211 }
1212 $this->_validateFilelist($dir, $allowignore, $newdirs);
1213 }
1214 }
1215 }
1216 }
1217
1219 {
1220 if (isset($this->_packageInfo['phprelease'])) {
1221 $release = 'phprelease';
1222 if (isset($this->_packageInfo['providesextension'])) {
1223 $this->_cannotProvideExtension($release);
1224 }
1225 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1226 $this->_cannotHaveSrcpackage($release);
1227 }
1228 $releases = $this->_packageInfo['phprelease'];
1229 if (!is_array($releases)) {
1230 return true;
1231 }
1232 if (!isset($releases[0])) {
1233 $releases = array($releases);
1234 }
1235 foreach ($releases as $rel) {
1236 $this->_stupidSchemaValidate(array(
1237 '*installconditions',
1238 '*filelist',
1239 ), $rel, '<phprelease>');
1240 }
1241 }
1242 foreach (array('', 'zend') as $prefix) {
1243 $releasetype = $prefix . 'extsrcrelease';
1244 if (isset($this->_packageInfo[$releasetype])) {
1245 $release = $releasetype;
1246 if (!isset($this->_packageInfo['providesextension'])) {
1247 $this->_mustProvideExtension($release);
1248 }
1249 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1250 $this->_cannotHaveSrcpackage($release);
1251 }
1252 $releases = $this->_packageInfo[$releasetype];
1253 if (!is_array($releases)) {
1254 return true;
1255 }
1256 if (!isset($releases[0])) {
1257 $releases = array($releases);
1258 }
1259 foreach ($releases as $rel) {
1260 $this->_stupidSchemaValidate(array(
1261 '*installconditions',
1262 '*configureoption->name->prompt->?default',
1263 '*binarypackage',
1264 '*filelist',
1265 ), $rel, '<' . $releasetype . '>');
1266 if (isset($rel['binarypackage'])) {
1267 if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
1268 $rel['binarypackage'] = array($rel['binarypackage']);
1269 }
1270 foreach ($rel['binarypackage'] as $bin) {
1271 if (!is_string($bin)) {
1273 }
1274 }
1275 }
1276 }
1277 }
1278 $releasetype = 'extbinrelease';
1279 if (isset($this->_packageInfo[$releasetype])) {
1280 $release = $releasetype;
1281 if (!isset($this->_packageInfo['providesextension'])) {
1282 $this->_mustProvideExtension($release);
1283 }
1284 if (isset($this->_packageInfo['channel']) &&
1285 !isset($this->_packageInfo['srcpackage'])) {
1286 $this->_mustSrcPackage($release);
1287 }
1288 if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
1289 $this->_mustSrcuri($release);
1290 }
1291 $releases = $this->_packageInfo[$releasetype];
1292 if (!is_array($releases)) {
1293 return true;
1294 }
1295 if (!isset($releases[0])) {
1296 $releases = array($releases);
1297 }
1298 foreach ($releases as $rel) {
1299 $this->_stupidSchemaValidate(array(
1300 '*installconditions',
1301 '*filelist',
1302 ), $rel, '<' . $releasetype . '>');
1303 }
1304 }
1305 }
1306 if (isset($this->_packageInfo['bundle'])) {
1307 $release = 'bundle';
1308 if (isset($this->_packageInfo['providesextension'])) {
1309 $this->_cannotProvideExtension($release);
1310 }
1311 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
1312 $this->_cannotHaveSrcpackage($release);
1313 }
1314 $releases = $this->_packageInfo['bundle'];
1315 if (!is_array($releases) || !isset($releases[0])) {
1316 $releases = array($releases);
1317 }
1318 foreach ($releases as $rel) {
1319 $this->_stupidSchemaValidate(array(
1320 '*installconditions',
1321 '*filelist',
1322 ), $rel, '<bundle>');
1323 }
1324 }
1325 foreach ($releases as $rel) {
1326 if (is_array($rel) && array_key_exists('installconditions', $rel)) {
1327 $this->_validateInstallConditions($rel['installconditions'],
1328 "<$release><installconditions>");
1329 }
1330 if (is_array($rel) && array_key_exists('filelist', $rel)) {
1331 if ($rel['filelist']) {
1332
1333 $this->_validateFilelist($rel['filelist'], true);
1334 }
1335 }
1336 }
1337 }
1338
1343 function _validateRole($role)
1344 {
1345 return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
1346 }
1347
1348 function _pearVersionTooLow($version)
1349 {
1350 $this->_stack->push(__FUNCTION__, 'error',
1351 array('version' => $version),
1352 'This package.xml requires PEAR version %version% to parse properly, we are ' .
1353 'version 1.10.18');
1354 }
1355
1356 function _invalidTagOrder($oktags, $actual, $root)
1357 {
1358 $this->_stack->push(__FUNCTION__, 'error',
1359 array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
1360 'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
1361 }
1362
1363 function _ignoreNotAllowed($type)
1364 {
1365 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1366 '<%type%> is not allowed inside global <contents>, only inside ' .
1367 '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
1368 }
1369
1370 function _fileNotAllowed($type)
1371 {
1372 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1373 '<%type%> is not allowed inside release <filelist>, only inside ' .
1374 '<contents>, use <ignore> and <install> only');
1375 }
1376
1378 {
1379 $this->_stack->push(__FUNCTION__, 'error', array(),
1380 'Old-style <file>name</file> is not allowed. Use' .
1381 '<file name="name" role="role"/>');
1382 }
1383
1384 function _tagMissingAttribute($tag, $attr, $context)
1385 {
1386 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1387 'attribute' => $attr, 'context' => $context),
1388 'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
1389 }
1390
1391 function _tagHasNoAttribs($tag, $context)
1392 {
1393 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
1394 'context' => $context),
1395 'tag <%tag%> has no attributes in context "%context%"');
1396 }
1397
1399 {
1400 $this->_stack->push(__FUNCTION__, 'exception', array(),
1401 'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
1402 }
1403
1404 function _invalidFileRole($file, $dir, $role)
1405 {
1406 $this->_stack->push(__FUNCTION__, 'error', array(
1407 'file' => $file, 'dir' => $dir, 'role' => $role,
1408 'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
1409 'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
1410 }
1411
1412 function _invalidFileName($file, $dir)
1413 {
1414 $this->_stack->push(__FUNCTION__, 'error', array(
1415 'file' => $file),
1416 'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
1417 }
1418
1419 function _invalidFileInstallAs($file, $as)
1420 {
1421 $this->_stack->push(__FUNCTION__, 'error', array(
1422 'file' => $file, 'as' => $as),
1423 'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
1424 }
1425
1426 function _invalidDirName($dir)
1427 {
1428 $this->_stack->push(__FUNCTION__, 'error', array(
1429 'dir' => $file),
1430 'Directory "%dir%" cannot begin with "./" or contain ".."');
1431 }
1432
1433 function _filelistCannotContainFile($filelist)
1434 {
1435 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1436 '<%tag%> can only contain <dir>, contains <file>. Use ' .
1437 '<dir name="/"> as the first dir element');
1438 }
1439
1440 function _filelistMustContainDir($filelist)
1441 {
1442 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
1443 '<%tag%> must contain <dir>. Use <dir name="/"> as the ' .
1444 'first dir element');
1445 }
1446
1447 function _tagCannotBeEmpty($tag)
1448 {
1449 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1450 '<%tag%> cannot be empty (<%tag%/>)');
1451 }
1452
1453 function _UrlOrChannel($type, $name)
1454 {
1455 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1456 'name' => $name),
1457 'Required dependency <%type%> "%name%" can have either url OR ' .
1458 'channel attributes, and not both');
1459 }
1460
1461 function _NoChannel($type, $name)
1462 {
1463 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1464 'name' => $name),
1465 'Required dependency <%type%> "%name%" must have either url OR ' .
1466 'channel attributes');
1467 }
1468
1469 function _UrlOrChannelGroup($type, $name, $group)
1470 {
1471 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1472 'name' => $name, 'group' => $group),
1473 'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
1474 'channel attributes, and not both');
1475 }
1476
1477 function _NoChannelGroup($type, $name, $group)
1478 {
1479 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
1480 'name' => $name, 'group' => $group),
1481 'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
1482 'channel attributes');
1483 }
1484
1485 function _unknownChannel($channel)
1486 {
1487 $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
1488 'Unknown channel "%channel%"');
1489 }
1490
1492 {
1493 $this->_stack->push(__FUNCTION__, 'error', array(),
1494 'package.xml <package> tag has no version attribute, or version is not 2.0');
1495 }
1496
1498 {
1499 $this->_stack->push(__FUNCTION__, 'error', array(),
1500 'No <bundledpackage> tag was found in <contents>, required for bundle packages');
1501 }
1502
1504 {
1505 $this->_stack->push(__FUNCTION__, 'error', array(),
1506 'At least 2 packages must be bundled in a bundle package');
1507 }
1508
1509 function _ChannelOrUri($name)
1510 {
1511 $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1512 'Bundled package "%name%" can have either a uri or a channel, not both');
1513 }
1514
1515 function _noChildTag($child, $tag)
1516 {
1517 $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
1518 'Tag <%tag%> is missing child tag <%child%>');
1519 }
1520
1521 function _invalidVersion($type, $value)
1522 {
1523 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
1524 'Version type <%type%> is not a valid version (%value%)');
1525 }
1526
1527 function _invalidState($type, $value)
1528 {
1529 $states = array('stable', 'beta', 'alpha', 'devel');
1530 if ($type != 'api') {
1531 $states[] = 'snapshot';
1532 }
1533 if (strtolower($value) == 'rc') {
1534 $this->_stack->push(__FUNCTION__, 'error',
1535 array('version' => $this->_packageInfo['version']['release']),
1536 'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
1537 }
1538 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
1539 'types' => $states),
1540 'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
1541 '%types%');
1542 }
1543
1544 function _invalidTask($task, $ret, $file)
1545 {
1546 switch ($ret[0]) {
1548 $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
1549 $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
1550 break;
1552 $info = array('task' => $task, 'file' => $file);
1553 $msg = 'task <%task%> has no attributes in file %file%';
1554 break;
1556 $info = array('attrib' => $ret[1], 'values' => $ret[3],
1557 'was' => $ret[2], 'task' => $task, 'file' => $file);
1558 $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
1559 'in file %file%, expecting one of "%values%"';
1560 break;
1562 $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
1563 $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
1564 break;
1565 }
1566 $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
1567 }
1568
1569 function _unknownTask($task, $file)
1570 {
1571 $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
1572 'Unknown task "%task%" passed in file <file name="%file%">');
1573 }
1574
1576 {
1577 $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1578 'Subpackage dependency "%name%" cannot use <providesextension>, ' .
1579 'only package dependencies can use this tag');
1580 }
1581
1583 {
1584 $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1585 'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
1586 'only package dependencies can use this tag');
1587 }
1588
1589 function _cannotProvideExtension($release)
1590 {
1591 $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1592 '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
1593 }
1594
1595 function _mustProvideExtension($release)
1596 {
1597 $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1598 '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
1599 }
1600
1601 function _cannotHaveSrcpackage($release)
1602 {
1603 $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1604 '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
1605 }
1606
1607 function _mustSrcPackage($release)
1608 {
1609 $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1610 '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
1611 }
1612
1613 function _mustSrcuri($release)
1614 {
1615 $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
1616 '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
1617 }
1618
1620 {
1621 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1622 '%type%: dependencies with a <uri> tag cannot have any versioning information');
1623 }
1624
1626 {
1627 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1628 '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
1629 'exclude specific versions of a dependency');
1630 }
1631
1633 {
1634 $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
1635 '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
1636 'dependencies only');
1637 }
1638
1640 {
1641 $this->_stack->push(__FUNCTION__, 'error', array(),
1642 '<bundledpackage> tags must contain only the filename of a package release ' .
1643 'in the bundle');
1644 }
1645
1647 {
1648 $this->_stack->push(__FUNCTION__, 'error', array(),
1649 '<binarypackage> tags must contain the name of a package that is ' .
1650 'a compiled version of this extsrc/zendextsrc package');
1651 }
1652
1653 function _fileNotFound($file)
1654 {
1655 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1656 'File "%file%" in package.xml does not exist');
1657 }
1658
1659 function _notInContents($file, $tag)
1660 {
1661 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
1662 '<%tag% name="%file%"> is invalid, file is not in <contents>');
1663 }
1664
1666 {
1667 $this->_stack->push(__FUNCTION__, 'error', array(),
1668 'Cannot validate files, no path to package file is set (use setPackageFile())');
1669 }
1670
1672 {
1673 $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1674 '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
1675 }
1676
1677 function _usesroletaskMustHavePackage($role, $tag)
1678 {
1679 $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
1680 '<%tag%> for role "%role%" must contain <package>');
1681 }
1682
1683 function _usesroletaskMustHaveRoleTask($tag, $type)
1684 {
1685 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
1686 '<%tag%> must contain <%type%> defining the %type% to be used');
1687 }
1688
1690 {
1691 $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
1692 '%tag% cannot conflict with all OSes');
1693 }
1694
1695 function _invalidDepGroupName($name)
1696 {
1697 $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
1698 'Invalid dependency group name "%name%"');
1699 }
1700
1702 {
1703 $this->_stack->push(__FUNCTION__, 'error', array(),
1704 'Multiple top-level <dir> tags are not allowed. Enclose them ' .
1705 'in a <dir name="/">');
1706 }
1707
1708 function _multipleInstallAs($file)
1709 {
1710 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1711 'Only one <install> tag is allowed for file "%file%"');
1712 }
1713
1714 function _ignoreAndInstallAs($file)
1715 {
1716 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1717 'Cannot have both <ignore> and <install> tags for file "%file%"');
1718 }
1719
1721 {
1722 if (!$this->_isValid) {
1723 return false;
1724 }
1725 if (!$this->_pf->getPackageType() == 'bundle') {
1726 return false;
1727 }
1728 if (!isset($this->_pf->_packageFile)) {
1729 return false;
1730 }
1731 $dir_prefix = dirname($this->_pf->_packageFile);
1732 $common = new PEAR_Common;
1733 $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1734 array($common, 'log');
1735 $info = $this->_pf->getContents();
1736 $info = $info['bundledpackage'];
1737 if (!is_array($info)) {
1738 $info = array($info);
1739 }
1740 $pkg = new PEAR_PackageFile($this->_pf->_config);
1741 foreach ($info as $package) {
1742 if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
1743 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
1744 $this->_isValid = 0;
1745 continue;
1746 }
1747 call_user_func_array($log, array(1, "Analyzing bundled package $package"));
1748 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1749 $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
1751 PEAR::popErrorHandling();
1752 if (PEAR::isError($ret)) {
1753 call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
1754 'package'));
1755 $inf = $ret->getUserInfo();
1756 if (is_array($inf)) {
1757 foreach ($inf as $err) {
1758 call_user_func_array($log, array(1, $err['message']));
1759 }
1760 }
1761 return false;
1762 }
1763 }
1764 return true;
1765 }
1766
1768 {
1769 if (!$this->_isValid) {
1770 return false;
1771 }
1772 if (!isset($this->_pf->_packageFile)) {
1773 $this->_cannotValidateNoPathSet();
1774 return false;
1775 }
1776 $dir_prefix = dirname($this->_pf->_packageFile);
1777 $common = new PEAR_Common;
1778 $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
1779 array(&$common, 'log');
1780 $info = $this->_pf->getContents();
1781 if (!$info || !isset($info['dir']['file'])) {
1782 $this->_tagCannotBeEmpty('contents><dir');
1783 return false;
1784 }
1785 $info = $info['dir']['file'];
1786 if (isset($info['attribs'])) {
1787 $info = array($info);
1788 }
1789 $provides = array();
1790 foreach ($info as $fa) {
1791 $fa = $fa['attribs'];
1792 $file = $fa['name'];
1793 if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
1794 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
1795 $this->_isValid = 0;
1796 continue;
1797 }
1798 if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
1799 call_user_func_array($log, array(1, "Analyzing $file"));
1800 $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
1801 if ($srcinfo) {
1802 $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
1803 }
1804 }
1805 }
1806 $this->_packageName = $pn = $this->_pf->getPackage();
1807 $pnl = strlen($pn);
1808 foreach ($provides as $key => $what) {
1809 if (isset($what['explicit']) || !$what) {
1810 // skip conformance checks if the provides entry is
1811 // specified in the package.xml file
1812 continue;
1813 }
1814 extract($what);
1815 if ($type == 'class') {
1816 if (!strncasecmp($name, $pn, $pnl)) {
1817 continue;
1818 }
1819 $this->_stack->push(__FUNCTION__, 'warning',
1820 array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1821 'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1822 } elseif ($type == 'function') {
1823 if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
1824 continue;
1825 }
1826 $this->_stack->push(__FUNCTION__, 'warning',
1827 array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
1828 'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1829 }
1830 }
1831 return $this->_isValid;
1832 }
1833
1841 function analyzeSourceCode($file, $string = false)
1842 {
1843 if (!function_exists("token_get_all")) {
1844 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1845 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
1846 return false;
1847 }
1848
1849 if (!defined('T_DOC_COMMENT')) {
1850 define('T_DOC_COMMENT', T_COMMENT);
1851 }
1852
1853 if (!defined('T_INTERFACE')) {
1854 define('T_INTERFACE', -1);
1855 }
1856
1857 if (!defined('T_IMPLEMENTS')) {
1858 define('T_IMPLEMENTS', -1);
1859 }
1860
1861 if ($string) {
1862 $contents = $file;
1863 } else {
1864 if (!$fp = @fopen($file, "r")) {
1865 return false;
1866 }
1867 fclose($fp);
1868 $contents = file_get_contents($file);
1869 }
1870
1871 // Silence this function so we can catch PHP Warnings and show our own custom message
1872 $tokens = @token_get_all($contents);
1873 if (isset($php_errormsg)) {
1874 if (isset($this->_stack)) {
1875 $pn = $this->_pf->getPackage();
1876 $this->_stack->push(__FUNCTION__, 'warning',
1877 array('file' => $file, 'package' => $pn),
1878 'in %file%: Could not process file for unknown reasons,' .
1879 ' possibly a PHP parse error in %file% from %package%');
1880 }
1881 }
1882/*
1883 for ($i = 0; $i < sizeof($tokens); $i++) {
1884 @list($token, $data) = $tokens[$i];
1885 if (is_string($token)) {
1886 var_dump($token);
1887 } else {
1888 print token_name($token) . ' ';
1889 var_dump(rtrim($data));
1890 }
1891 }
1892*/
1893 $look_for = 0;
1894 $paren_level = 0;
1895 $bracket_level = 0;
1896 $brace_level = 0;
1897 $lastphpdoc = '';
1898 $current_class = '';
1899 $current_interface = '';
1900 $current_class_level = -1;
1901 $current_function = '';
1902 $current_function_level = -1;
1903 $declared_classes = array();
1904 $declared_interfaces = array();
1905 $declared_functions = array();
1906 $declared_methods = array();
1907 $used_classes = array();
1908 $used_functions = array();
1909 $extends = array();
1910 $implements = array();
1911 $nodeps = array();
1912 $inquote = false;
1913 $interface = false;
1914 for ($i = 0; $i < sizeof($tokens); $i++) {
1915 if (is_array($tokens[$i])) {
1916 list($token, $data) = $tokens[$i];
1917 } else {
1918 $token = $tokens[$i];
1919 $data = '';
1920 }
1921
1922 if ($inquote) {
1923 if ($token != '"' && $token != T_END_HEREDOC) {
1924 continue;
1925 } else {
1926 $inquote = false;
1927 continue;
1928 }
1929 }
1930
1931 switch ($token) {
1932 case T_WHITESPACE :
1933 continue 2;
1934 case ';':
1935 if ($interface) {
1936 $current_function = '';
1937 $current_function_level = -1;
1938 }
1939 break;
1940 case '"':
1941 case T_START_HEREDOC:
1942 $inquote = true;
1943 break;
1944 case T_CURLY_OPEN:
1945 case T_DOLLAR_OPEN_CURLY_BRACES:
1946 case '{': $brace_level++; continue 2;
1947 case '}':
1948 $brace_level--;
1949 if ($current_class_level == $brace_level) {
1950 $current_class = '';
1951 $current_class_level = -1;
1952 }
1953 if ($current_function_level == $brace_level) {
1954 $current_function = '';
1955 $current_function_level = -1;
1956 }
1957 continue 2;
1958 case '[': $bracket_level++; continue 2;
1959 case ']': $bracket_level--; continue 2;
1960 case '(': $paren_level++; continue 2;
1961 case ')': $paren_level--; continue 2;
1962 case T_INTERFACE:
1963 $interface = true;
1964 case T_CLASS:
1965 if (($current_class_level != -1) || ($current_function_level != -1)) {
1966 if (isset($this->_stack)) {
1967 $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
1968 'Parser error: invalid PHP found in file "%file%"');
1969 } else {
1970 PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
1972 }
1973
1974 return false;
1975 }
1976 case T_FUNCTION:
1977 case T_NEW:
1978 case T_EXTENDS:
1979 case T_IMPLEMENTS:
1980 $look_for = $token;
1981 continue 2;
1982 case T_STRING:
1983 if ($look_for == T_CLASS) {
1984 $current_class = $data;
1985 $current_class_level = $brace_level;
1986 $declared_classes[] = $current_class;
1987 } elseif ($look_for == T_INTERFACE) {
1988 $current_interface = $data;
1989 $current_class_level = $brace_level;
1990 $declared_interfaces[] = $current_interface;
1991 } elseif ($look_for == T_IMPLEMENTS) {
1992 $implements[$current_class] = $data;
1993 } elseif ($look_for == T_EXTENDS) {
1994 $extends[$current_class] = $data;
1995 } elseif ($look_for == T_FUNCTION) {
1996 if ($current_class) {
1997 $current_function = "$current_class::$data";
1998 $declared_methods[$current_class][] = $data;
1999 } elseif ($current_interface) {
2000 $current_function = "$current_interface::$data";
2001 $declared_methods[$current_interface][] = $data;
2002 } else {
2003 $current_function = $data;
2004 $declared_functions[] = $current_function;
2005 }
2006
2007 $current_function_level = $brace_level;
2008 $m = array();
2009 } elseif ($look_for == T_NEW) {
2010 $used_classes[$data] = true;
2011 }
2012
2013 $look_for = 0;
2014 continue 2;
2015 case T_VARIABLE:
2016 $look_for = 0;
2017 continue 2;
2018 case T_DOC_COMMENT:
2019 case T_COMMENT:
2020 if (preg_match('!^/\*\*\s!', $data)) {
2021 $lastphpdoc = $data;
2022 if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
2023 $nodeps = array_merge($nodeps, $m[1]);
2024 }
2025 }
2026 continue 2;
2027 case T_DOUBLE_COLON:
2028 $token = $tokens[$i - 1][0];
2029 if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) {
2030 if (isset($this->_stack)) {
2031 $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
2032 'Parser error: invalid PHP found in file "%file%"');
2033 } else {
2034 PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
2036 }
2037
2038 return false;
2039 }
2040
2041 $class = $tokens[$i - 1][1];
2042 if (strtolower($class) != 'parent') {
2043 $used_classes[$class] = true;
2044 }
2045
2046 continue 2;
2047 }
2048 }
2049
2050 return array(
2051 "source_file" => $file,
2052 "declared_classes" => $declared_classes,
2053 "declared_interfaces" => $declared_interfaces,
2054 "declared_methods" => $declared_methods,
2055 "declared_functions" => $declared_functions,
2056 "used_classes" => array_diff(array_keys($used_classes), $nodeps),
2057 "inheritance" => $extends,
2058 "implements" => $implements,
2059 );
2060 }
2061
2081 function _buildProvidesArray($srcinfo)
2082 {
2083 if (!$this->_isValid) {
2084 return array();
2085 }
2086
2087 $providesret = array();
2088 $file = basename($srcinfo['source_file']);
2089 $pn = isset($this->_pf) ? $this->_pf->getPackage() : '';
2090 $pnl = strlen($pn);
2091 foreach ($srcinfo['declared_classes'] as $class) {
2092 $key = "class;$class";
2093 if (isset($providesret[$key])) {
2094 continue;
2095 }
2096
2097 $providesret[$key] =
2098 array('file'=> $file, 'type' => 'class', 'name' => $class);
2099 if (isset($srcinfo['inheritance'][$class])) {
2100 $providesret[$key]['extends'] =
2101 $srcinfo['inheritance'][$class];
2102 }
2103 }
2104
2105 foreach ($srcinfo['declared_methods'] as $class => $methods) {
2106 foreach ($methods as $method) {
2107 $function = "$class::$method";
2108 $key = "function;$function";
2109 if ($method[0] == '_' || !strcasecmp($method, $class) ||
2110 isset($providesret[$key])) {
2111 continue;
2112 }
2113
2114 $providesret[$key] =
2115 array('file'=> $file, 'type' => 'function', 'name' => $function);
2116 }
2117 }
2118
2119 foreach ($srcinfo['declared_functions'] as $function) {
2120 $key = "function;$function";
2121 if ($function[0] == '_' || isset($providesret[$key])) {
2122 continue;
2123 }
2124
2125 if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
2126 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
2127 }
2128
2129 $providesret[$key] =
2130 array('file'=> $file, 'type' => 'function', 'name' => $function);
2131 }
2132
2133 return $providesret;
2134 }
2135}
const PEAR_COMMON_ERROR_INVALIDPHP
Definition Common.php:27
const PEAR_ERROR_RETURN
Definition PEAR.php:24
const PEAR_TASK_ERROR_NOATTRIBS
Definition Common.php:18
const PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE
Definition Common.php:20
const PEAR_TASK_ERROR_MISSING_ATTRIB
Definition Common.php:19
const PEAR_TASK_ERROR_INVALID
Definition Common.php:21
const PEAR_VALIDATE_PACKAGING
Definition Validate.php:22
const PEAR_VALIDATE_DOWNLOADING
Definition Validate.php:21
const PEAR_VALIDATE_NORMAL
Definition Validate.php:20
static getValidRoles($release, $clear=false)
Definition Role.php:88
static getPhpRoles($clear=false)
Definition Role.php:187
_validatePhpDep($dep, $installcondition=false)
_validateArchDep($dep, $installcondition=false)
_invalidTask($task, $ret, $file)
_validateFilelist($list=false, $allowignore=false, $dirs='')
analyzeSourceCode($file, $string=false)
_tagHasNoAttribs($tag, $context)
_usesroletaskMustHaveRoleTask($tag, $type)
_UrlOrChannelGroup($type, $name, $group)
_invalidFileRole($file, $dir, $role)
validate(&$pf, $state=PEAR_VALIDATE_NORMAL)
Definition Validator.php:58
_invalidTagOrder($oktags, $actual, $root)
_validateOsDep($dep, $installcondition=false)
_usesroletaskMustHavePackage($role, $tag)
_tagMissingAttribute($tag, $attr, $context)
_validateSubpackageDep($dep, $group)
_NoChannelGroup($type, $name, $group)
_validateExtensionDep($dep, $group=false, $installcondition=false)
_usesroletaskMustHaveChannelOrUri($role, $tag)
_stupidSchemaValidate($structure, $xml, $root)
_processAttribs($choice, $tag, $context)
_validateInstallConditions($cond, $release)
_validatePackageDep($dep, $group, $type='< package >')
static validGroupName($name)
Definition Validate.php:88