19        'attributeauthority-remote' 
   33        $this->metadata = array();
 
   36        $this->changed = 
false;
 
   43        $this->state = array();
 
   81        if (preg_match(
'@^https?://@i', 
$source[
'src'])) {
 
   88            } 
catch(Exception $e) {
 
   93            if (!isset($responseHeaders)) {
 
   98            } elseif (preg_match(
'@^HTTP/1\.[01]\s304\s@', $responseHeaders[0])) {
 
  103            } elseif (!preg_match(
'@^HTTP/1\.[01]\s200\s@', $responseHeaders[0])) {
 
  112            $responseHeaders = 
null;
 
  116        if (isset(
$source[
'conditionalGET']) && 
$source[
'conditionalGET']) {
 
  123        } 
catch(Exception $e) {
 
  130        foreach ($entities as $entity) {
 
  132            if (isset(
$source[
'blacklist'])) {
 
  133                if (!empty(
$source[
'blacklist']) && in_array($entity->getEntityID(), 
$source[
'blacklist'], 
true)) {
 
  139            if (isset(
$source[
'whitelist'])) {
 
  140                if (!empty(
$source[
'whitelist']) && !in_array($entity->getEntityID(), 
$source[
'whitelist'], 
true)) {
 
  146            if (array_key_exists(
'certificates', 
$source) && 
$source[
'certificates'] !== 
null) {
 
  147                if (!$entity->validateSignature(
$source[
'certificates'])) {
 
  148                    SimpleSAML\Logger::info(
'Skipping "' . $entity->getEntityId() . 
'" - could not verify signature using certificate.' . 
"\n");
 
  153            if (array_key_exists(
'validateFingerprint', 
$source) && 
$source[
'validateFingerprint'] !== 
null) {
 
  154                if (!array_key_exists(
'certificates', 
$source) || 
$source[
'certificates'] == 
null) {
 
  155                    if (!$entity->validateFingerprint(
$source[
'validateFingerprint'])) {
 
  156                        SimpleSAML\Logger::info(
'Skipping "' . $entity->getEntityId() . 
'" - could not verify signature using fingerprint.' . 
"\n");
 
  165            if (array_key_exists(
'template', 
$source)) {
 
  169            if (in_array(
'shib13-sp-remote', $this->types, 
true)) {
 
  172            if (in_array(
'shib13-idp-remote', $this->types, 
true)) {
 
  175            if (in_array(
'saml20-sp-remote', $this->types, 
true)) {
 
  178            if (in_array(
'saml20-idp-remote', $this->types, 
true)) {
 
  181            if (in_array(
'attributeauthority-remote', $this->types, 
true)) {
 
  182                $attributeAuthorities = $entity->getAttributeAuthorities();
 
  183                if (!empty($attributeAuthorities)) {
 
  198        $name = 
$config->getString(
'technicalcontact_name', 
null);
 
  199        $mail = 
$config->getString(
'technicalcontact_email', 
null);
 
  201        $rawheader = 
"User-Agent: SimpleSAMLphp metarefresh, run by $name <$mail>\r\n";
 
  203        if (isset(
$source[
'conditionalGET']) && 
$source[
'conditionalGET']) {
 
  204            if (array_key_exists(
$source[
'src'], $this->state)) {
 
  205                $sourceState = $this->state[
$source[
'src']];
 
  207                if (isset($sourceState[
'last-modified'])) {
 
  208                    $rawheader .= 
'If-Modified-Since: ' . $sourceState[
'last-modified'] . 
"\r\n";
 
  211                if (isset($sourceState[
'etag'])) {
 
  212                    $rawheader .= 
'If-None-Match: ' . $sourceState[
'etag'] . 
"\r\n";
 
  217        return array(
'http' => array(
'header' => $rawheader));
 
  223        if (isset($this->oldMetadataSrc)) {
 
  224            foreach ($this->types as 
$type) {
 
  225                foreach ($this->oldMetadataSrc->getMetadataSet(
$type) as $entity) {
 
  226                    if (array_key_exists(
'metarefresh:src', $entity)) {
 
  227                        if ($entity[
'metarefresh:src'] == 
$source[
'src']) {
 
  242        if (isset(
$source[
'conditionalGET']) && 
$source[
'conditionalGET']) {
 
  244            if ($responseHeaders !== 
null) {
 
  245                $candidates = array(
'last-modified', 
'etag');
 
  247                foreach ($candidates as $candidate) {
 
  248                    if (array_key_exists($candidate, $responseHeaders)) {
 
  249                        $this->state[
$source[
'src']][$candidate] = $responseHeaders[$candidate];
 
  254            if (!empty($this->state[
$source[
'src']])) {
 
  257                $this->changed = 
true;
 
  269        } 
catch (Exception $e) {
 
  270            throw new Exception(
'Failed to read XML from ' . 
$source[
'src']);
 
  272        if ($doc->documentElement === 
null) {
 
  273            throw new Exception(
'Opened file is not an XML document: ' . 
$source[
'src']);
 
  284        if ($this->changed) {
 
  288                "<?php\n/* This file was generated by the metarefresh module at ".$this->
getTime() . 
".\n".
 
  289                " Do not update it manually as it will get overwritten. */\n".
 
  290                '$state = ' . var_export($this->state, 
true) . 
";\n?>\n",
 
  302        foreach ($this->metadata as $category => $elements) {
 
  304            echo 
'/* The following data should be added to metadata/' . $category . 
'.php. */' . 
"\n";
 
  306            foreach ($elements as 
$m) {
 
  308                $entityID = 
$m[
'metadata'][
'entityid'];
 
  311                echo 
'/* The following metadata was generated from ' . 
$filename . 
' on ' . $this->
getTime() . 
'. */' . 
"\n";
 
  312                echo 
'$metadata[\'' . addslashes($entityID) . 
'\'] = 
' . var_export($m['metadata
'], true) . ';
' . "\n"; 
  330    private function addMetadata($filename, $metadata, $type, $template = null) 
  332        if ($metadata === null) { 
  336        if (isset($template)) { 
  337            $metadata = array_merge($metadata, $template); 
  340        $metadata['metarefresh:src
'] = $filename; 
  341        if (!array_key_exists($type, $this->metadata)) { 
  342            $this->metadata[$type] = array(); 
  345        // If expire is defined in constructor... 
  346        if (!empty($this->expire)) { 
  347            // If expire is already in metadata 
  348            if (array_key_exists('expire
', $metadata)) { 
  349                // Override metadata expire with more restrictive global config- 
  350                if ($this->expire < $metadata['expire
']) { 
  351                    $metadata['expire
'] = $this->expire; 
  354                // If expire is not already in metadata use global config 
  356                $metadata['expire
'] = $this->expire; 
  359        $this->metadata[$type][] = array('filename
' => $filename, 'metadata
' => $metadata); 
  366    public function writeARPfile($config) 
  368        assert($config instanceof SimpleSAML_Configuration); 
  370        $arpfile = $config->getValue('arpfile
'); 
  371        $types = array('saml20-sp-remote
'); 
  374        foreach ($this->metadata as $category => $elements) { 
  375            if (!in_array($category, $types, true)) { 
  378            $md = array_merge($md, $elements); 
  381        // $metadata, $attributemap, $prefix, $suffix 
  382        $arp = new sspmod_metarefresh_ARP($md, 
  383            $config->getValue('attributemap
', ''), 
  384            $config->getValue('prefix
', ''), 
  385            $config->getValue('suffix
', '') 
  389        $arpxml = $arp->getXML(); 
  391        SimpleSAML\Logger::info('Writing ARP file: 
' . $arpfile . "\n"); 
  392        file_put_contents($arpfile, $arpxml); 
  399    public function writeMetadataFiles($outputDir) 
  401        while (strlen($outputDir) > 0 && $outputDir[strlen($outputDir) - 1] === '/
') { 
  402            $outputDir = substr($outputDir, 0, strlen($outputDir) - 1); 
  405        if (!file_exists($outputDir)) { 
  406            SimpleSAML\Logger::info('Creating directory: 
' . $outputDir . "\n"); 
  407            $res = @mkdir($outputDir, 0777, true); 
  408            if ($res === false) { 
  409                throw new Exception('Error creating directory: 
' . $outputDir); 
  413        foreach ($this->types as $type) { 
  414            $filename = $outputDir . '/
' . $type . '.php
'; 
  416            if (array_key_exists($type, $this->metadata)) { 
  417                $elements = $this->metadata[$type]; 
  418                SimpleSAML\Logger::debug('Writing: 
' . $filename); 
  420                $content  = '<?
php' . "\n" . ' 
  423                foreach ($elements as $m) { 
  424                    $entityID = $m['metadata
']['entityid
']; 
  426                    $content .= '$metadata[\
'' . addslashes($entityID) . 
'\'] = 
' . var_export($m['metadata
'], true) . ';
' . "\n"; 
  429                $content .= "\n" . '?>
'; 
  431                SimpleSAML\Utils\System::writeFile($filename, $content, 0644); 
  432            } elseif (is_file($filename)) { 
  433                if (unlink($filename)) { 
  434                    SimpleSAML\Logger::debug('Deleting stale metadata file: 
' . $filename); 
  436                    SimpleSAML\Logger::warning('Could not 
delete stale metadata file: 
' . $filename); 
  448    public function writeMetadataSerialize($outputDir) 
  450        assert(is_string($outputDir)); 
  452        $metaHandler = new SimpleSAML_Metadata_MetaDataStorageHandlerSerialize(array('directory
' => $outputDir)); 
  454        /* First we add all the metadata entries to the metadata handler. */ 
  455        foreach ($this->metadata as $set => $elements) { 
  456            foreach ($elements as $m) { 
  457                $entityId = $m['metadata
']['entityid
']; 
  459                SimpleSAML\Logger::debug( 
  460                    'metarefresh: Add metadata entry 
' . 
  461                    var_export($entityId, true) . ' in 
set ' . var_export($set, true) . '.
' 
  463                $metaHandler->saveMetadata($entityId, $set, $m['metadata
']); 
  467        /* Then we delete old entries which should no longer exist. */ 
  469        foreach ($metaHandler->getMetadataSets() as $set) { 
  470            foreach ($metaHandler->getMetadataSet($set) as $entityId => $metadata) { 
  471                if (!array_key_exists('expire
', $metadata)) { 
  472                    SimpleSAML\Logger::warning( 
  473                        'metarefresh: Metadata entry without expire timestamp: 
' . var_export($entityId, true) . 
  474                        ' in 
set ' . var_export($set, true) . '.
' 
  478                if ($metadata['expire
'] > $ct) { 
  481                SimpleSAML\Logger::debug('metarefresh: 
' . $entityId . ' expired 
' . date('l jS \of 
F Y h:i:s A
', $metadata['expire
'])); 
  482                SimpleSAML\Logger::debug( 
  483                    'metarefresh: Delete expired metadata entry 
' . 
  484                    var_export($entityId, true) . ' in 
set ' . var_export($set, true) . '. (
' . ($ct - $metadata['expire
']) . ' sec)
' 
  486                $metaHandler->deleteMetadata($entityId, $set); 
  492    private function getTime() 
  494        /* The current date, as a string. */ 
  495        date_default_timezone_set('UTC
'); 
  496        return date('Y-m-d\\TH:i:s\\Z
'); 
An exception for terminatinating execution or to throw for unit testing.
static fetch($url, $context=array(), $getHeaders=false)
Helper function to retrieve a file or URL with proxy support, also supporting proxy basic authorizati...
static writeFile($filename, $data, $mode=0600)
Atomically write a file.
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.