19declare(strict_types=1);
33 private const XPATH =
'/wopi-discovery/net-zone/app';
52 $this->crawl_actions = [
53 ActionTarget::VIEW->value,
54 ActionTarget::EMBED_VIEW->value,
55 ActionTarget::EDIT->value,
56 ActionTarget::EMBED_EDIT->value,
57 ActionTarget::EDIT_NEW->value,
58 ActionTarget::CONVERT->value,
64 return in_array(strtolower($url->
getSchema()), self::ALLOWED_SCHEMES,
true);
69 if (!self::isWebUrl($discovery_url)) {
73 return $this->
load($this->
fetch($discovery_url));
74 }
catch (\Throwable) {
79 private function fetch(
URI $discovery_url): ?string
81 $context = stream_context_create([
83 'timeout' => self::TIMEOUT_SECONDS,
84 'max_redirects' => self::MAX_REDIRECTS,
88 $content = @file_get_contents((
string) $discovery_url,
false, $context, 0, self::MAX_SIZE_BYTES + 1);
100 if ($this->content ===
null) {
105 $use_internal_errors = libxml_use_internal_errors(
true);
106 $this->discovery = simplexml_load_string($this->content) ?:
null;
107 libxml_clear_errors();
108 libxml_use_internal_errors($use_internal_errors);
109 if ($this->discovery ===
null) {
112 $this->xml_app_elements = $this->discovery->xpath(self::XPATH);
114 return is_array($this->xml_app_elements);
115 }
catch (\Throwable) {
122 if (!$this->
validate($discovery_url)) {
126 return $this->
parse();
134 if (!$this->
load($content)) {
138 return $this->
parse();
146 $element = $this->discovery?->xpath(
'/wopi-discovery/proof-key')[0] ??
null;
147 if (!$element instanceof \SimpleXMLElement) {
150 $modulus = (string) ($element[
'modulus'] ??
'');
151 $exponent = (string) ($element[
'exponent'] ??
'');
152 if ($modulus ===
'' || $exponent ===
'') {
155 $old_modulus = (string) ($element[
'oldmodulus'] ??
'');
156 $old_exponent = (string) ($element[
'oldexponent'] ??
'');
160 $old_modulus ===
'' || $old_exponent ===
'' ?
null :
new ProofKey($old_modulus, $old_exponent)
168 foreach ($this->xml_app_elements as $app) {
170 foreach ($app->action as $action) {
171 $action_name = $action[
'name'] ??
null;
172 $action_ext = $action[
'ext'] ??
null;
173 $action_urlsrc = $action[
'urlsrc'] ??
null;
175 $target_text = isset($action[
'targetext'])
176 ? (string) $action[
'targetext']
177 : (isset($action[
'newext']) ? (string) $action[
'newext'] :
null);
178 if (!$action_name instanceof \SimpleXMLElement) {
181 if (!$action_ext instanceof \SimpleXMLElement) {
184 if (!$action_urlsrc instanceof \SimpleXMLElement) {
192 $uri_string = rtrim((
string) $action_urlsrc,
'?');
194 $uri = explode(
'?', $uri_string);
195 $uri_string = $uri[0];
197 $launcher_url =
new URI($uri_string);
198 }
catch (\Throwable) {
201 if (!self::isWebUrl($launcher_url)) {
206 (
string) $action_name,
207 (
string) $action_ext,
213 if ($actions === []) {
217 $app_name = $app[
'name'] ??
null;
218 if ($app_name ===
null) {
228 return new Apps($apps);
233 $value = $app[
'favIconUrl'] ??
null;
234 if ($value ===
null) {
238 $url =
new URI((
string) $value);
239 }
catch (\Throwable) {
The scope of this class is split ilias-conform URI's into components.
favIconUrl(\SimpleXMLElement $app)
crawl(URI $discovery_url)
static isWebUrl(URI $url)
crawlContent(string $content)
Parses discovery XML that has already been fetched.
getProofKeys()
The proof keys of the discovery read last, null if it publishes none.
SimpleXMLElement $discovery
const ALLOWED_SCHEMES
the discovery and the URLs it publishes must be web URLs, anything else (file, php,...
validate(URI $discovery_url)
fetch(URI $discovery_url)
A public RSA key of a WOPI client, as published in its discovery with base64 encoded modulus and expo...
The current and the previous proof key of a WOPI client.