public function createDocumentLoader() { $base = 'http://json-ld.org/test-suite'; $test = $this; $load_locally = function ($url) use($test, $base) { $doc = (object) array('contextUrl' => null, 'documentUrl' => $url, 'document' => null); $options = property_exists($test->data, 'option') ? $test->data->option : null; if ($options and $url === $test->base) { if (property_exists($options, 'redirectTo') && property_exists($options, 'httpStatus') && $options->httpStatus >= '300') { $doc->documentUrl = $test->manifest->data->baseIri . $options->redirectTo; } else { if (property_exists($options, 'httpLink')) { $content_type = property_exists($options, 'contentType') ? $options->contentType : null; $extension = pathinfo($url, PATHINFO_EXTENSION); if (!$content_type && $extension === 'jsonld') { $content_type = 'application/ld+json'; } $link_header = $options->httpLink; if (is_array($link_header)) { $link_header = join(',', $link_header); } $link_header = jsonld_parse_link_header($link_header); if (isset($link_header['http://www.w3.org/ns/json-ld#context'])) { $link_header = $link_header['http://www.w3.org/ns/json-ld#context']; } else { $link_header = null; } if ($link_header && $content_type !== 'application/ld+json') { if (is_array($link_header)) { throw new Exception('multiple context link headers'); } $doc->contextUrl = $link_header->target; } } } } global $ROOT_MANIFEST_DIR; if (strpos($doc->documentUrl, ':') === false) { $filename = join(DIRECTORY_SEPARATOR, array($ROOT_MANIFEST_DIR, $doc->documentUrl)); $doc->documentUrl = 'file://' . $filename; } else { $filename = join(DIRECTORY_SEPARATOR, array($ROOT_MANIFEST_DIR, substr($doc->documentUrl, strlen($base)))); } try { $doc->document = Util::readJson($filename); } catch (Exception $e) { throw new Exception('loading document failed'); } return $doc; }; $local_loader = function ($url) use($test, $base, $load_locally) { // always load remote-doc and non-base tests remotely if (strpos($url, $base) !== 0 && strpos($url, ':') !== false || $test->manifest->data->name === 'Remote document') { return call_user_func('jsonld_default_document_loader', $url); } // attempt to load locally return call_user_func($load_locally, $url); }; return $local_loader; }
/** * The default implementation to retrieve JSON-LD at the given secure URL. * * @param string $url the secure URL to to retrieve. * * @return stdClass the RemoteDocument object. */ function jsonld_default_secure_document_loader($url) { if (strpos($url, 'https') !== 0) { throw new JsonLdException("Could not GET url: '{$url}'; 'https' is required.", 'jsonld.LoadDocumentError', 'loading document failed'); } $doc = (object) array('contextUrl' => null, 'document' => null, 'documentUrl' => $url); $redirects = array(); // default JSON-LD https GET implementation $opts = array('http' => array('method' => 'GET', 'header' => "Accept: application/ld+json\r\n"), 'ssl' => array('verify_peer' => true, 'allow_self_signed' => false, 'cafile' => '/etc/ssl/certs/ca-certificates.crt')); $context = stream_context_create($opts); $content_type = null; stream_context_set_params($context, array('notification' => function ($notification_code, $severity, $message) use(&$redirects, &$content_type) { switch ($notification_code) { case STREAM_NOTIFY_REDIRECTED: $redirects[] = $message; break; case STREAM_NOTIFY_MIME_TYPE_IS: $content_type = $message; break; } })); $result = @file_get_contents($url, false, $context); if ($result === false) { throw new JsonLdException('Could not retrieve a JSON-LD document from the URL: ' + $url, 'jsonld.LoadDocumentError', 'loading document failed'); } $link_header = array(); foreach ($http_response_header as $header) { if (strpos($header, 'link') === 0) { $value = explode(': ', $header); if (count($value) > 1) { $link_header[] = $value[1]; } } } $link_header = jsonld_parse_link_header(join(',', $link_header)); if (isset($link_header['http://www.w3.org/ns/json-ld#context'])) { $link_header = $link_header['http://www.w3.org/ns/json-ld#context']; } else { $link_header = null; } if ($link_header && $content_type !== 'application/ld+json') { // only 1 related link header permitted if (is_array($link_header)) { throw new JsonLdException('URL could not be dereferenced, it has more than one ' . 'associated HTTP Link Header.', 'jsonld.LoadDocumentError', 'multiple context link headers', array('url' => $url)); } $doc->{'contextUrl'} = $link_header->target; } // update document url based on redirects foreach ($redirects as $redirect) { if (strpos($redirect, 'https') !== 0) { throw new JsonLdException("Could not GET redirected url: '{$redirect}'; 'https' is required.", 'jsonld.LoadDocumentError', 'loading document failed'); } $url = $redirect; } $doc->document = $result; $doc->documentUrl = $url; return $doc; }