Allow external web links in market rich text
This commit is contained in:
1 parent
c25d3f1b3c
commit
9f10344fa7
4 files changed
+20
-12
No files matched your search
@@ -47,8 +47,9 @@ Link: <a href="https://erpnaurua.imhochrain.ch/files.php?path=Marktmanagement%2F
|
|||||||
Leerzeichen, Umlaute und sonstige Sonderzeichen im URL-Parameter müssen
|
Leerzeichen, Umlaute und sonstige Sonderzeichen im URL-Parameter müssen
|
||||||
vollständig URL-encodiert werden. Im Feld `notes` sind ausschließlich `<a>`
|
vollständig URL-encodiert werden. Im Feld `notes` sind ausschließlich `<a>`
|
||||||
für solche internen Dokumentlinks sowie `<br>` und `<strong>` erlaubt. Andere
|
für solche internen Dokumentlinks sowie `<br>` und `<strong>` erlaubt. Andere
|
||||||
HTML-Tags, externe Links und nicht erlaubte URL-Schemata werden entfernt. Der
|
HTML-Tags und nicht erlaubte URL-Schemata werden entfernt. Externe `http://`-
|
||||||
Link ist schreibgeschützt und erfordert eine aktive ERP-Anmeldung.
|
und `https://`-Links sind erlaubt und öffnen in einem neuen Tab. Der Link ist
|
||||||
|
schreibgeschützt und erfordert bei internen Dokumenten eine aktive ERP-Anmeldung.
|
||||||
|
|
||||||
Die Route benötigt auf dem ERP-Webserver die Konfiguration
|
Die Route benötigt auf dem ERP-Webserver die Konfiguration
|
||||||
`HERMES_DOCUMENT_ROOT=/volume1/Hermes/Hermes Naurua`. Dieser lokale Pfad ist
|
`HERMES_DOCUMENT_ROOT=/volume1/Hermes/Hermes Naurua`. Dieser lokale Pfad ist
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ Modulberechtigung.
|
|||||||
Marktdurchführung speichert, muss die Quelldatei als interner `<a>`-Link im
|
Marktdurchführung speichert, muss die Quelldatei als interner `<a>`-Link im
|
||||||
Feld `notes` referenziert werden. Zusätzlich sind in mehrzeiligen Feldern
|
Feld `notes` referenziert werden. Zusätzlich sind in mehrzeiligen Feldern
|
||||||
`<br>` und `<strong>` erlaubt. Die Position im bestehenden Freitext ist frei
|
`<br>` und `<strong>` erlaubt. Die Position im bestehenden Freitext ist frei
|
||||||
wählbar; andere HTML-Tags und externe Links sind nicht zulässig.
|
wählbar. Externe `http://`- und `https://`-Links sind zulässig und öffnen in
|
||||||
|
einem neuen Tab; andere HTML-Tags und URL-Schemata sind nicht zulässig.
|
||||||
- Unsichere Erkennung wird nicht durch eine zusätzliche App-Freigabelogik
|
- Unsichere Erkennung wird nicht durch eine zusätzliche App-Freigabelogik
|
||||||
behandelt; die fachliche Qualitätssicherung liegt im Hermes-Training.
|
behandelt; die fachliche Qualitätssicherung liegt im Hermes-Training.
|
||||||
|
|
||||||
|
|||||||
@@ -26,15 +26,21 @@ const MARKET_MANAGEMENT_MULTILINE_FIELDS = [
|
|||||||
'description',
|
'description',
|
||||||
];
|
];
|
||||||
|
|
||||||
function market_management_is_allowed_document_url(string $url): bool
|
function market_management_is_allowed_link_url(string $url): bool
|
||||||
{
|
{
|
||||||
$parts = parse_url($url);
|
$parts = parse_url($url);
|
||||||
if (!is_array($parts)
|
if (!is_array($parts)
|
||||||
|| ($parts['scheme'] ?? '') !== 'https'
|
|| !in_array(($parts['scheme'] ?? ''), ['http', 'https'], true)
|
||||||
|| ($parts['host'] ?? '') !== 'erpnaurua.imhochrain.ch'
|
|| ($parts['host'] ?? '') === ''
|
||||||
|| ($parts['path'] ?? '') !== '/files.php'
|
|| isset($parts['user'], $parts['pass'])) {
|
||||||
|| isset($parts['port'], $parts['user'], $parts['pass'], $parts['fragment'])
|
return false;
|
||||||
|| !preg_match('/^path=([^&]+)$/', (string) ($parts['query'] ?? ''), $matches)) {
|
}
|
||||||
|
|
||||||
|
if (($parts['host'] ?? '') !== 'erpnaurua.imhochrain.ch' || ($parts['path'] ?? '') !== '/files.php') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($parts['port'], $parts['fragment']) || !preg_match('/^path=([^&]+)$/', (string) ($parts['query'] ?? ''), $matches)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,12 +94,12 @@ function market_management_sanitize_multiline_html(?string $value): ?string
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (preg_match('/^<a\b[^>]*\bhref\s*=\s*(["\'])(.*?)\1[^>]*>$/isu', $token, $matches)
|
if (preg_match('/^<a\b[^>]*\bhref\s*=\s*(["\'])(.*?)\1[^>]*>$/isu', $token, $matches)
|
||||||
&& market_management_is_allowed_document_url($matches[2])) {
|
&& market_management_is_allowed_link_url($matches[2])) {
|
||||||
if ($anchorOpen) {
|
if ($anchorOpen) {
|
||||||
$result .= '</a>';
|
$result .= '</a>';
|
||||||
}
|
}
|
||||||
$href = htmlspecialchars($matches[2], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
$href = htmlspecialchars($matches[2], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||||
$result .= '<a class="sg-hyperlink" href="' . $href . '" target="_blank" rel="noopener">';
|
$result .= '<a class="sg-hyperlink" href="' . $href . '" target="_blank" rel="noopener noreferrer">';
|
||||||
$anchorOpen = true;
|
$anchorOpen = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1152,7 +1152,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $otcM
|
|||||||
echo " const getCurrentLimit = () => parseInt(getTable()?.dataset.marketsLimit || '20', 10);";
|
echo " const getCurrentLimit = () => parseInt(getTable()?.dataset.marketsLimit || '20', 10);";
|
||||||
echo " const getPageSize = () => parseInt(getTable()?.dataset.marketsPageSize || '20', 10);";
|
echo " const getPageSize = () => parseInt(getTable()?.dataset.marketsPageSize || '20', 10);";
|
||||||
echo " const marketEscape = (value) => String(value ?? '').replace(/[&<>\"']/g, (character) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[character] || character));";
|
echo " const marketEscape = (value) => String(value ?? '').replace(/[&<>\"']/g, (character) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[character] || character));";
|
||||||
echo " const marketDisplay = (value) => { if (value === null || value === undefined || value === '') { return 'Nicht hinterlegt'; } const escaped = marketEscape(value); const safeMarkup = escaped.replace(/<br>/g, '<br>').replace(/<strong>/g, '<strong>').replace(/<\\/strong>/g, '</strong>').replace(/<a class="sg-hyperlink" href="(https:\\/\\/erpnaurua\\.imhochrain\\.ch\\/files\\.php\\?path=[^"]+)" target="_blank" rel="noopener">/g, '<a class=\"sg-hyperlink\" href=\"$1\" target=\"_blank\" rel=\"noopener\">').replace(/<\\/a>/g, '</a>'); return safeMarkup.replace(/\\r?\\n/g, '<br>'); };";
|
echo " const marketDisplay = (value) => { if (value === null || value === undefined || value === '') { return 'Nicht hinterlegt'; } const escaped = marketEscape(value); const safeMarkup = escaped.replace(/<br>/g, '<br>').replace(/<strong>/g, '<strong>').replace(/<\\/strong>/g, '</strong>').replace(/<a class="sg-hyperlink" href="(https?:\\/\\/.*?)" target="_blank" rel="noopener noreferrer">/g, '<a class=\"sg-hyperlink\" href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">').replace(/<\\/a>/g, '</a>'); return safeMarkup.replace(/\\r?\\n/g, '<br>'); };";
|
||||||
echo " const marketBoolean = (value) => value === true || value === 'true' || value === 1 || value === '1' ? 'Ja' : value === false || value === 'false' || value === 0 || value === '0' ? 'Nein' : 'Nicht hinterlegt';";
|
echo " const marketBoolean = (value) => value === true || value === 'true' || value === 1 || value === '1' ? 'Ja' : value === false || value === 'false' || value === 0 || value === '0' ? 'Nein' : 'Nicht hinterlegt';";
|
||||||
echo " const marketMoney = (value) => value === null || value === undefined || value === '' ? 'Nicht hinterlegt' : 'CHF ' + Number(value).toFixed(2);";
|
echo " const marketMoney = (value) => value === null || value === undefined || value === '' ? 'Nicht hinterlegt' : 'CHF ' + Number(value).toFixed(2);";
|
||||||
echo " const marketContactName = (contact) => { if (!contact) { return 'Nicht hinterlegt'; } return marketDisplay([contact.first_name, contact.last_name].filter(Boolean).join(' ')); };";
|
echo " const marketContactName = (contact) => { if (!contact) { return 'Nicht hinterlegt'; } return marketDisplay([contact.first_name, contact.last_name].filter(Boolean).join(' ')); };";
|
||||||
|
|||||||
Reference in new issue
Block a user