-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\XML\saml; | ||
|
||
use DOMElement; | ||
use SimpleSAML\Assert\Assert; | ||
use SimpleSAML\SAML11\Constants as C; | ||
use SimpleSAML\SAML11\Utils; | ||
use SimpleSAML\SAML11\XML\ExtensionPointInterface; | ||
use SimpleSAML\SAML11\XML\ExtensionPointTrait; | ||
use SimpleSAML\XML\Attribute as XMLAttribute; | ||
use SimpleSAML\XML\Chunk; | ||
use SimpleSAML\XML\Exception\InvalidDOMElementException; | ||
use SimpleSAML\XML\Exception\SchemaViolationException; | ||
|
||
use function count; | ||
use function explode; | ||
|
||
/** | ||
* SAML Condition data type. | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
abstract class AbstractCondition extends AbstractConditionType implements ExtensionPointInterface | ||
{ | ||
use ExtensionPointTrait; | ||
|
||
/** @var string */ | ||
public const LOCALNAME = 'Condition'; | ||
|
||
|
||
/** | ||
* Initialize a custom saml:Condition element. | ||
* | ||
* @param string $type | ||
*/ | ||
protected function __construct( | ||
protected string $type, | ||
) { | ||
} | ||
|
||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public function getXsiType(): string | ||
{ | ||
return $this->type; | ||
} | ||
|
||
|
||
/** | ||
* Convert an XML element into a Condition. | ||
* | ||
* @param \DOMElement $xml The root XML element | ||
* @return static | ||
* | ||
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException | ||
* if the qualified name of the supplied element is wrong | ||
*/ | ||
public static function fromXML(DOMElement $xml): static | ||
{ | ||
Assert::same($xml->localName, 'Condition', InvalidDOMElementException::class); | ||
Assert::same($xml->namespaceURI, C::NS_SAML, InvalidDOMElementException::class); | ||
Assert::true( | ||
$xml->hasAttributeNS(C::NS_XSI, 'type'), | ||
'Missing required xsi:type in <saml:Condition> element.', | ||
SchemaViolationException::class, | ||
); | ||
|
||
$type = $xml->getAttributeNS(C::NS_XSI, 'type'); | ||
Assert::validQName($type, SchemaViolationException::class); | ||
|
||
// first, try to resolve the type to a full namespaced version | ||
$qname = explode(':', $type, 2); | ||
if (count($qname) === 2) { | ||
list($prefix, $element) = $qname; | ||
} else { | ||
$prefix = null; | ||
list($element) = $qname; | ||
} | ||
$ns = $xml->lookupNamespaceUri($prefix); | ||
$type = ($ns === null) ? $element : implode(':', [$ns, $element]); | ||
|
||
// now check if we have a handler registered for it | ||
$handler = Utils::getContainer()->getExtensionHandler($type); | ||
if ($handler === null) { | ||
// we don't have a handler, proceed with unknown condition | ||
return new UnknownCondition(new Chunk($xml), $type); | ||
} | ||
|
||
Assert::subclassOf( | ||
$handler, | ||
AbstractCondition::class, | ||
'Elements implementing Condition must extend \SimpleSAML\SAML11\XML\saml\AbstractCondition.', | ||
); | ||
return $handler::fromXML($xml); | ||
} | ||
|
||
|
||
/** | ||
* Convert this Condition to XML. | ||
* | ||
* @param \DOMElement $parent The element we are converting to XML. | ||
* @return \DOMElement The XML element after adding the data corresponding to this Condition. | ||
*/ | ||
public function toXML(DOMElement $parent = null): DOMElement | ||
{ | ||
$e = $this->instantiateParentElement($parent); | ||
$e->setAttributeNS( | ||
'http://www.w3.org/2000/xmlns/', | ||
'xmlns:' . static::getXsiTypePrefix(), | ||
static::getXsiTypeNamespaceURI(), | ||
); | ||
|
||
$type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType()); | ||
$type->toXML($e); | ||
|
||
return $e; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\XML\saml; | ||
|
||
/** | ||
* Abstract class to be implemented by all the conditions in this namespace | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
abstract class AbstractConditionType extends AbstractSamlElement | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\XML\saml; | ||
|
||
use DOMElement; | ||
use SimpleSAML\XML\Chunk; | ||
|
||
/** | ||
* Class for unknown conditions. | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
final class UnknownCondition extends AbstractCondition | ||
{ | ||
/** | ||
* @param \SimpleSAML\XML\Chunk $chunk The whole Condition element as a chunk object. | ||
* @param string $type The xsi:type of this condition. | ||
*/ | ||
public function __construct( | ||
protected Chunk $chunk, | ||
string $type, | ||
) { | ||
parent::__construct($type); | ||
} | ||
|
||
|
||
/** | ||
* Get the raw version of this condition as a Chunk. | ||
* | ||
* @return \SimpleSAML\XML\Chunk | ||
*/ | ||
public function getRawCondition(): Chunk | ||
{ | ||
return $this->chunk; | ||
} | ||
|
||
|
||
/** | ||
* Convert this unknown condition to XML. | ||
* | ||
* @param \DOMElement|null $parent The element we are converting to XML. | ||
* @return \DOMElement The XML element after adding the data corresponding to this unknown condition. | ||
*/ | ||
public function toXML(DOMElement $parent = null): DOMElement | ||
{ | ||
return $this->getRawCondition()->toXML($parent); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<saml:Condition xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ssp="urn:x-simplesamlphp:namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ssp:CustomConditionType"> | ||
<saml:Audience>urn:some:audience</saml:Audience> | ||
</saml:Condition> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\Test\SAML11; | ||
|
||
use DOMElement; | ||
use SimpleSAML\Assert\Assert; | ||
use SimpleSAML\SAML11\Constants as C; | ||
use SimpleSAML\SAML11\XML\saml\AbstractCondition; | ||
use SimpleSAML\SAML11\XML\saml\Audience; | ||
use SimpleSAML\XML\Exception\InvalidDOMElementException; | ||
|
||
/** | ||
* Example class to demonstrate how Condition can be extended. | ||
* | ||
* @package simplesamlphp\saml11 | ||
*/ | ||
final class CustomCondition extends AbstractCondition | ||
{ | ||
/** @var string */ | ||
protected const XSI_TYPE_NAME = 'CustomConditionType'; | ||
|
||
/** @var string */ | ||
protected const XSI_TYPE_NAMESPACE = 'urn:x-simplesamlphp:namespace'; | ||
|
||
/** @var string */ | ||
protected const XSI_TYPE_PREFIX = 'ssp'; | ||
|
||
|
||
/** | ||
* CustomCondition constructor. | ||
* | ||
* @param \SimpleSAML\SAML11\XML\saml\Audience[] $audience | ||
*/ | ||
public function __construct( | ||
protected array $audience, | ||
) { | ||
Assert::allIsInstanceOf($audience, Audience::class); | ||
|
||
parent::__construct(self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); | ||
} | ||
|
||
|
||
/** | ||
* Get the value of the audience-attribute. | ||
* | ||
* @return \SimpleSAML\SAML11\XML\saml\Audience[] | ||
*/ | ||
public function getAudience(): array | ||
{ | ||
return $this->audience; | ||
} | ||
|
||
|
||
/** | ||
* Convert XML into a Condition | ||
* | ||
* @param \DOMElement $xml The XML element we should load | ||
* @return \SimpleSAML\SAML11\XML\saml\AbstractCondition | ||
* | ||
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException | ||
* if the qualified name of the supplied element is wrong | ||
*/ | ||
public static function fromXML(DOMElement $xml): static | ||
{ | ||
Assert::same($xml->localName, 'Condition', InvalidDOMElementException::class); | ||
Assert::notNull($xml->namespaceURI, InvalidDOMElementException::class); | ||
Assert::same($xml->namespaceURI, AbstractCondition::NS, InvalidDOMElementException::class); | ||
Assert::true( | ||
$xml->hasAttributeNS(C::NS_XSI, 'type'), | ||
'Missing required xsi:type in <saml:Condition> element.', | ||
InvalidDOMElementException::class, | ||
); | ||
|
||
$type = $xml->getAttributeNS(C::NS_XSI, 'type'); | ||
Assert::same($type, self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); | ||
|
||
$audience = Audience::getChildrenOfClass($xml); | ||
|
||
return new static($audience); | ||
} | ||
|
||
|
||
/** | ||
* Convert this Condition to XML. | ||
* | ||
* @param \DOMElement $parent The element we are converting to XML. | ||
* @return \DOMElement The XML element after adding the data corresponding to this Condition. | ||
*/ | ||
public function toXML(DOMElement $parent = null): DOMElement | ||
{ | ||
$e = parent::toXML($parent); | ||
|
||
foreach ($this->audience as $audience) { | ||
$audience->toXML($e); | ||
} | ||
|
||
return $e; | ||
} | ||
} |
Oops, something went wrong.