Newer
Older
$eps = $this->configuration[$endpointType];
if (is_string($eps)) {
throw new \Exception($loc . ': Expected array or string.');
}
foreach ($eps as $i => &$ep) {
$iloc = $loc . '[' . var_export($i, true) . ']';
'Location' => $ep,
'Binding' => $this->getDefaultBinding($endpointType),
$responseLocation = $this->getString($endpointType . 'Response', null);
if ($responseLocation !== null) {
$ep['ResponseLocation'] = $responseLocation;
}
} elseif (!is_array($ep)) {
throw new \Exception($iloc . ': Expected a string or an array.');
}
if (!array_key_exists('Location', $ep)) {
throw new \Exception($iloc . ': Missing Location.');
}
if (!is_string($ep['Location'])) {
throw new \Exception($iloc . ': Location must be a string.');
}
if (!array_key_exists('Binding', $ep)) {
throw new \Exception($iloc . ': Missing Binding.');
}
if (!is_string($ep['Binding'])) {
throw new \Exception($iloc . ': Binding must be a string.');
}
if (array_key_exists('ResponseLocation', $ep)) {
if (!is_string($ep['ResponseLocation'])) {
throw new \Exception($iloc . ': ResponseLocation must be a string.');
}
}
if (array_key_exists('index', $ep)) {
if (!is_int($ep['index'])) {
throw new \Exception($iloc . ': index must be an integer.');
}
}
}
return $eps;
}
/**
* Find an endpoint of the given type, using a list of supported bindings as a way to prioritize.
*
* @param string $endpointType The endpoint type.
* @param array $bindings Sorted array of acceptable bindings.
* @param mixed $default The default value to return if no matching endpoint is found. If no default is provided,
* an exception will be thrown.
*
* @return array|null The default endpoint, or null if no acceptable endpoints are used.
*
* @throws \Exception If no supported endpoint is found.
*/
public function getEndpointPrioritizedByBinding($endpointType, array $bindings, $default = self::REQUIRED_OPTION)
{
$endpoints = $this->getEndpoints($endpointType);
foreach ($bindings as $binding) {
foreach ($endpoints as $ep) {
if ($ep['Binding'] === $binding) {
return $ep;
}
}
}
if ($default === self::REQUIRED_OPTION) {
$loc = $this->location . '[' . var_export($endpointType, true) . ']:';
throw new \Exception($loc . 'Could not find a supported ' . $endpointType . ' endpoint.');
}
return $default;
}
/**
* Find the default endpoint of the given type.
*
* @param string $endpointType The endpoint type.
* @param array $bindings Array with acceptable bindings. Can be null if any binding is allowed.
* @param mixed $default The default value to return if no matching endpoint is found. If no default is provided,
* an exception will be thrown.
*
* @return mixed The default endpoint, or the $default parameter if no acceptable endpoints are used.
* @throws \Exception If no supported endpoint is found and no $default parameter is specified.
*/
public function getDefaultEndpoint($endpointType, array $bindings = null, $default = self::REQUIRED_OPTION)
{
$endpoints = $this->getEndpoints($endpointType);
$defaultEndpoint = Utils\Config\Metadata::getDefaultEndpoint($endpoints, $bindings);
if ($defaultEndpoint !== null) {
return $defaultEndpoint;
}
if ($default === self::REQUIRED_OPTION) {
$loc = $this->location . '[' . var_export($endpointType, true) . ']:';
throw new \Exception($loc . 'Could not find a supported ' . $endpointType . ' endpoint.');
}
return $default;
}
/**
* Retrieve a string which may be localized into many languages.
*
* The default language returned is always 'en'.
*
* @param string $name The name of the option.
* @param mixed $default The default value. If no default is given, and the option isn't found, an exception will
* be thrown.
*
* @return mixed Associative array with language => string pairs, or the provided default value.
* @throws \Exception If the translation is not an array or a string, or its index or value are not strings.
*/
public function getLocalizedString($name, $default = self::REQUIRED_OPTION)
{
$ret = $this->getValue($name, $default);
if ($ret === $default) {
// the option wasn't found, or it matches the default value. In any case, return this value
$loc = $this->location . '[' . var_export($name, true) . ']';
}
if (!is_array($ret)) {
throw new \Exception($loc . ': Must be an array or a string.');
}
foreach ($ret as $k => $v) {
if (!is_string($k)) {
throw new \Exception($loc . ': Invalid language code: ' . var_export($k, true));
throw new \Exception($loc . '[' . var_export($v, true) . ']: Must be a string.');
}
}
return $ret;
}
/**
* Get public key from metadata.
*
* @param string|null $use The purpose this key can be used for. (encryption or signing).
* @param bool $required Whether the public key is required. If this is true, a
* missing key will cause an exception. Default is false.
* @param string $prefix The prefix which should be used when reading from the metadata
* array. Defaults to ''.
*
* @return array Public key data, or empty array if no public key or was found.
* @throws \Exception If the certificate or public key cannot be loaded from a file.
* @throws \SimpleSAML\Error\Exception If the file does not contain a valid PEM-encoded certificate, or there is no
* certificate in the metadata.
*/
public function getPublicKeys($use = null, $required = false, $prefix = '')
{
Assert::boolean($required);
Assert::string($prefix);
foreach ($this->getArray($prefix . 'keys') as $key) {
if ($use !== null && isset($key[$use]) && !$key[$use]) {
continue;
}
if (isset($key['X509Certificate'])) {
$key['X509Certificate'] = preg_replace('/\s+/', '', $key['X509Certificate']);
}
$ret[] = $key;
}
} elseif ($this->hasValue($prefix . 'certData')) {
$certData = $this->getString($prefix . 'certData');
$certData = preg_replace('/\s+/', '', $certData);
'encryption' => true,
'signing' => true,
'type' => 'X509Certificate',
'X509Certificate' => $certData,
} elseif ($this->hasValue($prefix . 'certificate')) {
$file = $this->getString($prefix . 'certificate');
$file = Utils\Config::getCertPath($file);
$data = @file_get_contents($file);
if ($data === false) {
throw new \Exception(
$this->location . ': Unable to load certificate/public key from file "' . $file . '".'
);
// extract certificate data (if this is a certificate)
$pattern = '/^-----BEGIN CERTIFICATE-----([^-]*)^-----END CERTIFICATE-----/m';
if (!preg_match($pattern, $data, $matches)) {
throw new \SimpleSAML\Error\Exception(
$this->location . ': Could not find PEM encoded certificate in "' . $file . '".'
);
}
$certData = preg_replace('/\s+/', '', $matches[1]);
'encryption' => true,
'signing' => true,
'type' => 'X509Certificate',
'X509Certificate' => $certData,
} elseif ($required === true) {
throw new \SimpleSAML\Error\Exception($this->location . ': Missing certificate in metadata.');
/**
* Clear any configuration information cached.
* Allows for configuration files to be changed and reloaded during a given request. Most useful
* when running phpunit tests and needing to alter config.php between test cases
*/
public static function clearInternalState()
{
self::$configDirs = [];
self::$instance = [];
self::$loadedConfigs = [];