From d356e780aa10866d76b784d76611907fb4c0d336 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Sun, 24 Feb 2019 20:55:35 -0100 Subject: [PATCH] add default context object, in case cache is empty and website is down Signed-off-by: Maxence Lange --- context/w3id.org.identity.v1.json | 1 + context/w3id.org.security.v1.json | 1 + context/www.w3.org.ns.activitystreams.json | 1 + lib/Service/SignatureService.php | 62 +++++++++++++++++++--- 4 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 context/w3id.org.identity.v1.json create mode 100644 context/w3id.org.security.v1.json create mode 100644 context/www.w3.org.ns.activitystreams.json diff --git a/context/w3id.org.identity.v1.json b/context/w3id.org.identity.v1.json new file mode 100644 index 00000000..fcb38e57 --- /dev/null +++ b/context/w3id.org.identity.v1.json @@ -0,0 +1 @@ +{"contextUrl":null,"document":"{\n \"@context\": {\n \"id\": \"@id\",\n \"type\": \"@type\",\n\n \"cred\": \"https:\/\/w3id.org\/credentials#\",\n \"dc\": \"http:\/\/purl.org\/dc\/terms\/\",\n \"identity\": \"https:\/\/w3id.org\/identity#\",\n \"perm\": \"https:\/\/w3id.org\/permissions#\",\n \"ps\": \"https:\/\/w3id.org\/payswarm#\",\n \"rdf\": \"http:\/\/www.w3.org\/1999\/02\/22-rdf-syntax-ns#\",\n \"rdfs\": \"http:\/\/www.w3.org\/2000\/01\/rdf-schema#\",\n \"sec\": \"https:\/\/w3id.org\/security#\",\n \"schema\": \"http:\/\/schema.org\/\",\n \"xsd\": \"http:\/\/www.w3.org\/2001\/XMLSchema#\",\n\n \"Group\": \"https:\/\/www.w3.org\/ns\/activitystreams#Group\",\n\n \"claim\": {\"@id\": \"cred:claim\", \"@type\": \"@id\"},\n \"credential\": {\"@id\": \"cred:credential\", \"@type\": \"@id\"},\n \"issued\": {\"@id\": \"cred:issued\", \"@type\": \"xsd:dateTime\"},\n \"issuer\": {\"@id\": \"cred:issuer\", \"@type\": \"@id\"},\n \"recipient\": {\"@id\": \"cred:recipient\", \"@type\": \"@id\"},\n \"Credential\": \"cred:Credential\",\n \"CryptographicKeyCredential\": \"cred:CryptographicKeyCredential\",\n\n \"about\": {\"@id\": \"schema:about\", \"@type\": \"@id\"},\n \"address\": {\"@id\": \"schema:address\", \"@type\": \"@id\"},\n \"addressCountry\": \"schema:addressCountry\",\n \"addressLocality\": \"schema:addressLocality\",\n \"addressRegion\": \"schema:addressRegion\",\n \"comment\": \"rdfs:comment\",\n \"created\": {\"@id\": \"dc:created\", \"@type\": \"xsd:dateTime\"},\n \"creator\": {\"@id\": \"dc:creator\", \"@type\": \"@id\"},\n \"description\": \"schema:description\",\n \"email\": \"schema:email\",\n \"familyName\": \"schema:familyName\",\n \"givenName\": \"schema:givenName\",\n \"image\": {\"@id\": \"schema:image\", \"@type\": \"@id\"},\n \"label\": \"rdfs:label\",\n \"name\": \"schema:name\",\n \"postalCode\": \"schema:postalCode\",\n \"streetAddress\": \"schema:streetAddress\",\n \"title\": \"dc:title\",\n \"url\": {\"@id\": \"schema:url\", \"@type\": \"@id\"},\n \"Person\": \"schema:Person\",\n \"PostalAddress\": \"schema:PostalAddress\",\n \"Organization\": \"schema:Organization\",\n\n \"identityService\": {\"@id\": \"identity:identityService\", \"@type\": \"@id\"},\n \"idp\": {\"@id\": \"identity:idp\", \"@type\": \"@id\"},\n \"Identity\": \"identity:Identity\",\n\n \"paymentProcessor\": \"ps:processor\",\n \"preferences\": {\"@id\": \"ps:preferences\", \"@type\": \"@vocab\"},\n\n \"cipherAlgorithm\": \"sec:cipherAlgorithm\",\n \"cipherData\": \"sec:cipherData\",\n \"cipherKey\": \"sec:cipherKey\",\n \"digestAlgorithm\": \"sec:digestAlgorithm\",\n \"digestValue\": \"sec:digestValue\",\n \"domain\": \"sec:domain\",\n \"expires\": {\"@id\": \"sec:expiration\", \"@type\": \"xsd:dateTime\"},\n \"initializationVector\": \"sec:initializationVector\",\n \"member\": {\"@id\": \"schema:member\", \"@type\": \"@id\"},\n \"memberOf\": {\"@id\": \"schema:memberOf\", \"@type\": \"@id\"},\n \"nonce\": \"sec:nonce\",\n \"normalizationAlgorithm\": \"sec:normalizationAlgorithm\",\n \"owner\": {\"@id\": \"sec:owner\", \"@type\": \"@id\"},\n \"password\": \"sec:password\",\n \"privateKey\": {\"@id\": \"sec:privateKey\", \"@type\": \"@id\"},\n \"privateKeyPem\": \"sec:privateKeyPem\",\n \"publicKey\": {\"@id\": \"sec:publicKey\", \"@type\": \"@id\"},\n \"publicKeyPem\": \"sec:publicKeyPem\",\n \"publicKeyService\": {\"@id\": \"sec:publicKeyService\", \"@type\": \"@id\"},\n \"revoked\": {\"@id\": \"sec:revoked\", \"@type\": \"xsd:dateTime\"},\n \"signature\": \"sec:signature\",\n \"signatureAlgorithm\": \"sec:signatureAlgorithm\",\n \"signatureValue\": \"sec:signatureValue\",\n \"CryptographicKey\": \"sec:Key\",\n \"EncryptedMessage\": \"sec:EncryptedMessage\",\n \"GraphSignature2012\": \"sec:GraphSignature2012\",\n \"LinkedDataSignature2015\": \"sec:LinkedDataSignature2015\",\n\n \"accessControl\": {\"@id\": \"perm:accessControl\", \"@type\": \"@id\"},\n \"writePermission\": {\"@id\": \"perm:writePermission\", \"@type\": \"@id\"}\n }\n}\n","documentUrl":"https:\/\/web-payments.org\/contexts\/identity-v1.jsonld"} \ No newline at end of file diff --git a/context/w3id.org.security.v1.json b/context/w3id.org.security.v1.json new file mode 100644 index 00000000..e3a0825b --- /dev/null +++ b/context/w3id.org.security.v1.json @@ -0,0 +1 @@ +{"contextUrl":null,"document":"{\n \"@context\": {\n \"id\": \"@id\",\n \"type\": \"@type\",\n\n \"dc\": \"http:\/\/purl.org\/dc\/terms\/\",\n \"sec\": \"https:\/\/w3id.org\/security#\",\n \"xsd\": \"http:\/\/www.w3.org\/2001\/XMLSchema#\",\n\n \"EcdsaKoblitzSignature2016\": \"sec:EcdsaKoblitzSignature2016\",\n \"Ed25519Signature2018\": \"sec:Ed25519Signature2018\",\n \"EncryptedMessage\": \"sec:EncryptedMessage\",\n \"GraphSignature2012\": \"sec:GraphSignature2012\",\n \"LinkedDataSignature2015\": \"sec:LinkedDataSignature2015\",\n \"LinkedDataSignature2016\": \"sec:LinkedDataSignature2016\",\n \"CryptographicKey\": \"sec:Key\",\n\n \"authenticationTag\": \"sec:authenticationTag\",\n \"canonicalizationAlgorithm\": \"sec:canonicalizationAlgorithm\",\n \"cipherAlgorithm\": \"sec:cipherAlgorithm\",\n \"cipherData\": \"sec:cipherData\",\n \"cipherKey\": \"sec:cipherKey\",\n \"created\": {\"@id\": \"dc:created\", \"@type\": \"xsd:dateTime\"},\n \"creator\": {\"@id\": \"dc:creator\", \"@type\": \"@id\"},\n \"digestAlgorithm\": \"sec:digestAlgorithm\",\n \"digestValue\": \"sec:digestValue\",\n \"domain\": \"sec:domain\",\n \"encryptionKey\": \"sec:encryptionKey\",\n \"expiration\": {\"@id\": \"sec:expiration\", \"@type\": \"xsd:dateTime\"},\n \"expires\": {\"@id\": \"sec:expiration\", \"@type\": \"xsd:dateTime\"},\n \"initializationVector\": \"sec:initializationVector\",\n \"iterationCount\": \"sec:iterationCount\",\n \"nonce\": \"sec:nonce\",\n \"normalizationAlgorithm\": \"sec:normalizationAlgorithm\",\n \"owner\": {\"@id\": \"sec:owner\", \"@type\": \"@id\"},\n \"password\": \"sec:password\",\n \"privateKey\": {\"@id\": \"sec:privateKey\", \"@type\": \"@id\"},\n \"privateKeyPem\": \"sec:privateKeyPem\",\n \"publicKey\": {\"@id\": \"sec:publicKey\", \"@type\": \"@id\"},\n \"publicKeyBase58\": \"sec:publicKeyBase58\",\n \"publicKeyPem\": \"sec:publicKeyPem\",\n \"publicKeyWif\": \"sec:publicKeyWif\",\n \"publicKeyService\": {\"@id\": \"sec:publicKeyService\", \"@type\": \"@id\"},\n \"revoked\": {\"@id\": \"sec:revoked\", \"@type\": \"xsd:dateTime\"},\n \"salt\": \"sec:salt\",\n \"signature\": \"sec:signature\",\n \"signatureAlgorithm\": \"sec:signingAlgorithm\",\n \"signatureValue\": \"sec:signatureValue\"\n }\n}\n","documentUrl":"https:\/\/web-payments.org\/contexts\/security-v1.jsonld"} \ No newline at end of file diff --git a/context/www.w3.org.ns.activitystreams.json b/context/www.w3.org.ns.activitystreams.json new file mode 100644 index 00000000..659708ff --- /dev/null +++ b/context/www.w3.org.ns.activitystreams.json @@ -0,0 +1 @@ +{"contextUrl":null,"document":"{\n \"@context\": {\n \"@vocab\": \"_:\",\n \"xsd\": \"http:\/\/www.w3.org\/2001\/XMLSchema#\",\n \"as\": \"https:\/\/www.w3.org\/ns\/activitystreams#\",\n \"ldp\": \"http:\/\/www.w3.org\/ns\/ldp#\",\n \"id\": \"@id\",\n \"type\": \"@type\",\n \"Accept\": \"as:Accept\",\n \"Activity\": \"as:Activity\",\n \"IntransitiveActivity\": \"as:IntransitiveActivity\",\n \"Add\": \"as:Add\",\n \"Announce\": \"as:Announce\",\n \"Application\": \"as:Application\",\n \"Arrive\": \"as:Arrive\",\n \"Article\": \"as:Article\",\n \"Audio\": \"as:Audio\",\n \"Block\": \"as:Block\",\n \"Collection\": \"as:Collection\",\n \"CollectionPage\": \"as:CollectionPage\",\n \"Relationship\": \"as:Relationship\",\n \"Create\": \"as:Create\",\n \"Delete\": \"as:Delete\",\n \"Dislike\": \"as:Dislike\",\n \"Document\": \"as:Document\",\n \"Event\": \"as:Event\",\n \"Follow\": \"as:Follow\",\n \"Flag\": \"as:Flag\",\n \"Group\": \"as:Group\",\n \"Ignore\": \"as:Ignore\",\n \"Image\": \"as:Image\",\n \"Invite\": \"as:Invite\",\n \"Join\": \"as:Join\",\n \"Leave\": \"as:Leave\",\n \"Like\": \"as:Like\",\n \"Link\": \"as:Link\",\n \"Mention\": \"as:Mention\",\n \"Note\": \"as:Note\",\n \"Object\": \"as:Object\",\n \"Offer\": \"as:Offer\",\n \"OrderedCollection\": \"as:OrderedCollection\",\n \"OrderedCollectionPage\": \"as:OrderedCollectionPage\",\n \"Organization\": \"as:Organization\",\n \"Page\": \"as:Page\",\n \"Person\": \"as:Person\",\n \"Place\": \"as:Place\",\n \"Profile\": \"as:Profile\",\n \"Question\": \"as:Question\",\n \"Reject\": \"as:Reject\",\n \"Remove\": \"as:Remove\",\n \"Service\": \"as:Service\",\n \"TentativeAccept\": \"as:TentativeAccept\",\n \"TentativeReject\": \"as:TentativeReject\",\n \"Tombstone\": \"as:Tombstone\",\n \"Undo\": \"as:Undo\",\n \"Update\": \"as:Update\",\n \"Video\": \"as:Video\",\n \"View\": \"as:View\",\n \"Listen\": \"as:Listen\",\n \"Read\": \"as:Read\",\n \"Move\": \"as:Move\",\n \"Travel\": \"as:Travel\",\n \"IsFollowing\": \"as:IsFollowing\",\n \"IsFollowedBy\": \"as:IsFollowedBy\",\n \"IsContact\": \"as:IsContact\",\n \"IsMember\": \"as:IsMember\",\n \"subject\": {\n \"@id\": \"as:subject\",\n \"@type\": \"@id\"\n },\n \"relationship\": {\n \"@id\": \"as:relationship\",\n \"@type\": \"@id\"\n },\n \"actor\": {\n \"@id\": \"as:actor\",\n \"@type\": \"@id\"\n },\n \"attributedTo\": {\n \"@id\": \"as:attributedTo\",\n \"@type\": \"@id\"\n },\n \"attachment\": {\n \"@id\": \"as:attachment\",\n \"@type\": \"@id\"\n },\n \"bcc\": {\n \"@id\": \"as:bcc\",\n \"@type\": \"@id\"\n },\n \"bto\": {\n \"@id\": \"as:bto\",\n \"@type\": \"@id\"\n },\n \"cc\": {\n \"@id\": \"as:cc\",\n \"@type\": \"@id\"\n },\n \"context\": {\n \"@id\": \"as:context\",\n \"@type\": \"@id\"\n },\n \"current\": {\n \"@id\": \"as:current\",\n \"@type\": \"@id\"\n },\n \"first\": {\n \"@id\": \"as:first\",\n \"@type\": \"@id\"\n },\n \"generator\": {\n \"@id\": \"as:generator\",\n \"@type\": \"@id\"\n },\n \"icon\": {\n \"@id\": \"as:icon\",\n \"@type\": \"@id\"\n },\n \"image\": {\n \"@id\": \"as:image\",\n \"@type\": \"@id\"\n },\n \"inReplyTo\": {\n \"@id\": \"as:inReplyTo\",\n \"@type\": \"@id\"\n },\n \"items\": {\n \"@id\": \"as:items\",\n \"@type\": \"@id\"\n },\n \"instrument\": {\n \"@id\": \"as:instrument\",\n \"@type\": \"@id\"\n },\n \"orderedItems\": {\n \"@id\": \"as:items\",\n \"@type\": \"@id\",\n \"@container\": \"@list\"\n },\n \"last\": {\n \"@id\": \"as:last\",\n \"@type\": \"@id\"\n },\n \"location\": {\n \"@id\": \"as:location\",\n \"@type\": \"@id\"\n },\n \"next\": {\n \"@id\": \"as:next\",\n \"@type\": \"@id\"\n },\n \"object\": {\n \"@id\": \"as:object\",\n \"@type\": \"@id\"\n },\n \"oneOf\": {\n \"@id\": \"as:oneOf\",\n \"@type\": \"@id\"\n },\n \"anyOf\": {\n \"@id\": \"as:anyOf\",\n \"@type\": \"@id\"\n },\n \"closed\": {\n \"@id\": \"as:closed\",\n \"@type\": \"xsd:dateTime\"\n },\n \"origin\": {\n \"@id\": \"as:origin\",\n \"@type\": \"@id\"\n },\n \"accuracy\": {\n \"@id\": \"as:accuracy\",\n \"@type\": \"xsd:float\"\n },\n \"prev\": {\n \"@id\": \"as:prev\",\n \"@type\": \"@id\"\n },\n \"preview\": {\n \"@id\": \"as:preview\",\n \"@type\": \"@id\"\n },\n \"replies\": {\n \"@id\": \"as:replies\",\n \"@type\": \"@id\"\n },\n \"result\": {\n \"@id\": \"as:result\",\n \"@type\": \"@id\"\n },\n \"audience\": {\n \"@id\": \"as:audience\",\n \"@type\": \"@id\"\n },\n \"partOf\": {\n \"@id\": \"as:partOf\",\n \"@type\": \"@id\"\n },\n \"tag\": {\n \"@id\": \"as:tag\",\n \"@type\": \"@id\"\n },\n \"target\": {\n \"@id\": \"as:target\",\n \"@type\": \"@id\"\n },\n \"to\": {\n \"@id\": \"as:to\",\n \"@type\": \"@id\"\n },\n \"url\": {\n \"@id\": \"as:url\",\n \"@type\": \"@id\"\n },\n \"altitude\": {\n \"@id\": \"as:altitude\",\n \"@type\": \"xsd:float\"\n },\n \"content\": \"as:content\",\n \"contentMap\": {\n \"@id\": \"as:content\",\n \"@container\": \"@language\"\n },\n \"name\": \"as:name\",\n \"nameMap\": {\n \"@id\": \"as:name\",\n \"@container\": \"@language\"\n },\n \"duration\": {\n \"@id\": \"as:duration\",\n \"@type\": \"xsd:duration\"\n },\n \"endTime\": {\n \"@id\": \"as:endTime\",\n \"@type\": \"xsd:dateTime\"\n },\n \"height\": {\n \"@id\": \"as:height\",\n \"@type\": \"xsd:nonNegativeInteger\"\n },\n \"href\": {\n \"@id\": \"as:href\",\n \"@type\": \"@id\"\n },\n \"hreflang\": \"as:hreflang\",\n \"latitude\": {\n \"@id\": \"as:latitude\",\n \"@type\": \"xsd:float\"\n },\n \"longitude\": {\n \"@id\": \"as:longitude\",\n \"@type\": \"xsd:float\"\n },\n \"mediaType\": \"as:mediaType\",\n \"published\": {\n \"@id\": \"as:published\",\n \"@type\": \"xsd:dateTime\"\n },\n \"radius\": {\n \"@id\": \"as:radius\",\n \"@type\": \"xsd:float\"\n },\n \"rel\": \"as:rel\",\n \"startIndex\": {\n \"@id\": \"as:startIndex\",\n \"@type\": \"xsd:nonNegativeInteger\"\n },\n \"startTime\": {\n \"@id\": \"as:startTime\",\n \"@type\": \"xsd:dateTime\"\n },\n \"summary\": \"as:summary\",\n \"summaryMap\": {\n \"@id\": \"as:summary\",\n \"@container\": \"@language\"\n },\n \"totalItems\": {\n \"@id\": \"as:totalItems\",\n \"@type\": \"xsd:nonNegativeInteger\"\n },\n \"units\": \"as:units\",\n \"updated\": {\n \"@id\": \"as:updated\",\n \"@type\": \"xsd:dateTime\"\n },\n \"width\": {\n \"@id\": \"as:width\",\n \"@type\": \"xsd:nonNegativeInteger\"\n },\n \"describes\": {\n \"@id\": \"as:describes\",\n \"@type\": \"@id\"\n },\n \"formerType\": {\n \"@id\": \"as:formerType\",\n \"@type\": \"@id\"\n },\n \"deleted\": {\n \"@id\": \"as:deleted\",\n \"@type\": \"xsd:dateTime\"\n },\n \"inbox\": {\n \"@id\": \"ldp:inbox\",\n \"@type\": \"@id\"\n },\n \"outbox\": {\n \"@id\": \"as:outbox\",\n \"@type\": \"@id\"\n },\n \"following\": {\n \"@id\": \"as:following\",\n \"@type\": \"@id\"\n },\n \"followers\": {\n \"@id\": \"as:followers\",\n \"@type\": \"@id\"\n },\n \"streams\": {\n \"@id\": \"as:streams\",\n \"@type\": \"@id\"\n },\n \"preferredUsername\": \"as:preferredUsername\",\n \"endpoints\": {\n \"@id\": \"as:endpoints\",\n \"@type\": \"@id\"\n },\n \"uploadMedia\": {\n \"@id\": \"as:uploadMedia\",\n \"@type\": \"@id\"\n },\n \"proxyUrl\": {\n \"@id\": \"as:proxyUrl\",\n \"@type\": \"@id\"\n },\n \"liked\": {\n \"@id\": \"as:liked\",\n \"@type\": \"@id\"\n },\n \"oauthAuthorizationEndpoint\": {\n \"@id\": \"as:oauthAuthorizationEndpoint\",\n \"@type\": \"@id\"\n },\n \"oauthTokenEndpoint\": {\n \"@id\": \"as:oauthTokenEndpoint\",\n \"@type\": \"@id\"\n },\n \"provideClientKey\": {\n \"@id\": \"as:provideClientKey\",\n \"@type\": \"@id\"\n },\n \"signClientKey\": {\n \"@id\": \"as:signClientKey\",\n \"@type\": \"@id\"\n },\n \"sharedInbox\": {\n \"@id\": \"as:sharedInbox\",\n \"@type\": \"@id\"\n },\n \"Public\": {\n \"@id\": \"as:Public\",\n \"@type\": \"@id\"\n },\n \"source\": \"as:source\",\n \"likes\": {\n \"@id\": \"as:likes\",\n \"@type\": \"@id\"\n },\n \"shares\": {\n \"@id\": \"as:shares\",\n \"@type\": \"@id\"\n }\n }\n}\n","documentUrl":"https:\/\/www.w3.org\/ns\/activitystreams"} \ No newline at end of file diff --git a/lib/Service/SignatureService.php b/lib/Service/SignatureService.php index 71f31ba0..a389cf69 100644 --- a/lib/Service/SignatureService.php +++ b/lib/Service/SignatureService.php @@ -41,6 +41,7 @@ use OCA\Social\Db\ActorsRequest; use OCA\Social\Exceptions\ActorDoesNotExistException; use OCA\Social\Exceptions\InvalidOriginException; use OCA\Social\Exceptions\InvalidResourceException; +use OCA\Social\Exceptions\ItemUnknownException; use OCA\Social\Exceptions\LinkedDataSignatureMissingException; use OCA\Social\Exceptions\RedundancyLimitException; use OCA\Social\Exceptions\RequestContentException; @@ -51,14 +52,13 @@ use OCA\Social\Exceptions\RequestServerException; use OCA\Social\Exceptions\SignatureException; use OCA\Social\Exceptions\SignatureIsGoneException; use OCA\Social\Exceptions\SocialAppConfigException; -use OCA\Social\Exceptions\ItemUnknownException; use OCA\Social\Model\ActivityPub\ACore; use OCA\Social\Model\ActivityPub\Actor\Person; use OCA\Social\Model\LinkedDataSignature; use OCA\Social\Model\RequestQueue; -use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IRequest; use stdClass; @@ -429,8 +429,8 @@ class SignatureService { * @param string $url * * @return stdClass - * @throws JsonLdException * @throws NotPermittedException + * @throws JsonLdException */ public static function documentLoader($url): stdClass { $recursion = 0; @@ -453,11 +453,11 @@ class SignatureService { try { $cache = $folder->getFile($filename); + self::updateContextCacheDocument($cache, $url); + $data = json_decode($cache->getContent()); } catch (NotFoundException $e) { - $cache = $folder->newFile($filename); - $data = jsonld_default_document_loader($url); - $cache->putContent(json_encode($data)); + $data = self::generateContextCacheDocument($folder, $filename, $url); } return $data; @@ -482,5 +482,55 @@ class SignatureService { } + /** + * @param ISimpleFolder $folder + * @param string $filename + * + * @param string $url + * + * @return stdClass + * @throws JsonLdException + * @throws NotPermittedException + */ + private static function generateContextCacheDocument( + ISimpleFolder $folder, string $filename, string $url + ): stdClass { + + try { + $data = jsonld_default_document_loader($url); + $content = json_encode($data); + } catch (JsonLdException $e) { + $context = file_get_contents(__DIR__ . '/../../context/' . $filename); + if (is_bool($context)) { + throw $e; + } + + $content = $context; + $data = json_decode($context); + } + + $cache = $folder->newFile($filename); + $cache->putContent($content); + + return $data; + } + + + /** + * @param ISimpleFile $cache + * @param string $url + * + * @throws NotPermittedException + */ + private static function updateContextCacheDocument(ISimpleFile $cache, string $url) { + if ($cache->getMTime() < (time() - 98765)) { + try { + $data = jsonld_default_document_loader($url); + $cache->putContent(json_encode($data)); + } catch (JsonLdException $e) { + } + } + } + }