From 15a3ceb01c503610803b6fd2b3e554ae62aca5c1 Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Wed, 19 Aug 2026 13:44:26 +0200 Subject: [PATCH 1/6] 0.9.6.10 complete legacy edit credentials and migration readiness --- include/nc_connector_edit.inc.php | 169 +++++++++++++++++++++++++++--- 1 file changed, 156 insertions(+), 13 deletions(-) diff --git a/include/nc_connector_edit.inc.php b/include/nc_connector_edit.inc.php index 673bb09..4bacb04 100644 --- a/include/nc_connector_edit.inc.php +++ b/include/nc_connector_edit.inc.php @@ -4,6 +4,93 @@ if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!'); } +function bratonien_tools_nc_connector_migration_state(array $connection) +{ + $config = isset($connection['config']) && is_array($connection['config']) ? $connection['config'] : array(); + $credentials = bratonien_tools_nc_connector_scoped_secret($connection); + $missing = array(); + + if (trim((string)($config['nextcloud_url'] ?? '')) === '') $missing[] = 'Nextcloud-Adresse'; + if (trim((string)($credentials['nextcloud_user'] ?? '')) === '') $missing[] = 'Nextcloud-Benutzer'; + if ((string)($credentials['nextcloud_password'] ?? '') === '') $missing[] = 'Nextcloud-Passwort'; + if (trim((string)($credentials['api_key_id'] ?? '')) === '') $missing[] = 'Piwigo-API-Schluessel-ID'; + if (trim((string)($credentials['api_key_secret'] ?? '')) === '') $missing[] = 'Piwigo-API-Geheimnis'; + + return array( + 'ready'=>!$missing, + 'missing'=>$missing, + ); +} + +function bratonien_tools_nc_connector_validate_nextcloud_access($base_url, $username, $password) +{ + $base_url = bratonien_tools_nc_wizard_normalize_url($base_url); + $username = trim((string)$username); + $password = (string)$password; + if ($username === '' || $password === '') throw new RuntimeException('Nextcloud-Benutzer und Passwort werden benoetigt.'); + + $status_response = bratonien_tools_nc_wizard_http($base_url.'/status.php'); + if ($status_response['status'] < 200 || $status_response['status'] >= 300) + { + throw new RuntimeException('Die Nextcloud-Adresse konnte nicht bestaetigt werden.'); + } + $status = json_decode((string)$status_response['body'], true); + if (!is_array($status) || empty($status['installed'])) + { + throw new RuntimeException('Unter dieser Adresse wurde keine installierte Nextcloud erkannt.'); + } + + $user_response = bratonien_tools_nc_wizard_http( + $base_url.'/ocs/v2.php/cloud/user?format=json', + $username, + $password, + array('OCS-APIRequest: true') + ); + if ($user_response['status'] === 401 || $user_response['status'] === 403) + { + throw new RuntimeException('Nextcloud hat Benutzername oder Passwort abgelehnt.'); + } + if ($user_response['status'] < 200 || $user_response['status'] >= 300) + { + throw new RuntimeException('Nextcloud ist erreichbar, aber der Benutzerzugang konnte nicht geprueft werden.'); + } + $user_data = bratonien_tools_nc_wizard_ocs_data($user_response['body']); + $resolved = trim((string)($user_data['id'] ?? $username)); + + return array( + 'base_url'=>$base_url, + 'username'=>$resolved !== '' ? $resolved : $username, + ); +} + +function bratonien_tools_nc_connector_validate_scoped_api($api_key_id, $api_key_secret) +{ + $api_key_id = trim((string)$api_key_id); + $api_key_secret = trim((string)$api_key_secret); + if ($api_key_id === '' || $api_key_secret === '') + { + throw new RuntimeException('Piwigo-API-Schluessel-ID und API-Geheimnis werden benoetigt.'); + } + + $status = bratonien_tools_nc_connector_piwigo_api_request($api_key_id, $api_key_secret, 'pwg.session.getStatus'); + if (!is_array($status)) throw new RuntimeException('Piwigo hat keinen auswertbaren API-Benutzerstatus geliefert.'); + $role = strtolower(trim((string)($status['status'] ?? ''))); + if (!in_array($role, array('admin','webmaster'), true)) + { + throw new RuntimeException('Der API-Key funktioniert, gehoert aber keinem Piwigo-Administrator/Webmaster.'); + } + + $method_result = bratonien_tools_nc_connector_piwigo_api_request($api_key_id, $api_key_secret, 'reflection.getMethodList'); + $method_map = array(); + bratonien_tools_nc_connector_collect_method_names($method_result, $method_map); + $required = array('bratonien.nc.syncProductive', 'bratonien.nc.syncOrphans'); + $missing = array_values(array_diff($required, array_keys($method_map))); + if ($missing) + { + throw new RuntimeException('Der API-Key ist gueltig, aber benoetigte Bratonien-Sync-Methoden fehlen: '.implode(', ', $missing).'.'); + } +} + function bratonien_tools_nc_connector_prepare_webdav_wizard_from_connection(array $connection, $mode) { $id = (int)$connection['id']; @@ -101,7 +188,7 @@ function bratonien_tools_nc_connector_edit_start() } bratonien_tools_nc_connector_prepare_webdav_wizard_from_connection($connection, 'update'); - return array('message'=>'Verbindung #'.$id.' wurde zum Bearbeiten geöffnet.'); + return array('message'=>'Verbindung #'.$id.' wurde zum Bearbeiten geoeffnet.'); } function bratonien_tools_nc_connector_migrate_start() @@ -114,8 +201,14 @@ function bratonien_tools_nc_connector_migrate_start() throw new RuntimeException('Nur eine Legacy-Verbindung kann auf WebDAV migriert werden.'); } + $migration = bratonien_tools_nc_connector_migration_state($connection); + if (empty($migration['ready'])) + { + throw new RuntimeException('Die WebDAV-Migration ist noch nicht bereit. Unter Bearbeiten fehlen: '.implode(', ', $migration['missing']).'.'); + } + bratonien_tools_nc_connector_prepare_webdav_wizard_from_connection($connection, 'migrate'); - return array('message'=>'Die WebDAV-Migration für Verbindung #'.$id.' wurde geöffnet. Die bestehende Legacy-Verbindung bleibt bis zum erfolgreichen Umstieg unverändert.'); + return array('message'=>'Die WebDAV-Migration fuer Verbindung #'.$id.' wurde geoeffnet. Die bestehende Legacy-Verbindung bleibt bis zum erfolgreichen Umstieg unveraendert.'); } function bratonien_tools_nc_connector_update_local_friendly() @@ -123,10 +216,10 @@ function bratonien_tools_nc_connector_update_local_friendly() $id = (int)($_POST['connection_id'] ?? 0); $connection = bratonien_tools_nc_connector_connection($id, true); if (!$connection) throw new RuntimeException('Connector-Verbindung wurde nicht gefunden.'); - if ((string)$connection['adapter'] !== 'local') throw new RuntimeException('Diese Bearbeitung ist nur für Legacy-Verbindungen vorgesehen.'); + if ((string)$connection['adapter'] !== 'local') throw new RuntimeException('Diese Bearbeitung ist nur fuer Legacy-Verbindungen vorgesehen.'); $name = trim((string)($_POST['connection_name'] ?? '')); - if ($name === '') throw new RuntimeException('Bitte einen Namen für die Verbindung angeben.'); + if ($name === '') throw new RuntimeException('Bitte einen Namen fuer die Verbindung angeben.'); $config = isset($connection['config']) && is_array($connection['config']) ? $connection['config'] : array(); $host = trim((string)($_POST['nc_host'] ?? '')); @@ -138,11 +231,11 @@ function bratonien_tools_nc_connector_update_local_friendly() $activity_view = trim((string)($_POST['nc_activity_view'] ?? '')); if ($host === '') throw new RuntimeException('Datenbank-Server fehlt.'); - if ($port < 1 || $port > 65535) throw new RuntimeException('Der Datenbank-Port ist ungültig.'); + if ($port < 1 || $port > 65535) throw new RuntimeException('Der Datenbank-Port ist ungueltig.'); if ($database === '') throw new RuntimeException('Datenbankname fehlt.'); if ($user === '') throw new RuntimeException('Reader-Benutzer fehlt.'); if ($gallery_root === '' || $gallery_root[0] !== '/') throw new RuntimeException('Der Piwigo-Galerieordner muss ein absoluter Pfad sein.'); - if ($source_view === '' || $activity_view === '') throw new RuntimeException('Die gespeicherten Datenbankansichten dürfen nicht leer sein.'); + if ($source_view === '' || $activity_view === '') throw new RuntimeException('Die gespeicherten Datenbankansichten duerfen nicht leer sein.'); bratonien_tools_nc_connector_view_name($source_view); bratonien_tools_nc_connector_view_name($activity_view); @@ -158,11 +251,54 @@ function bratonien_tools_nc_connector_update_local_friendly() $mount = rtrim(trim((string)($storage_mounts[$index] ?? '')), '/'); if ($storage_id === '' && $prefix === '' && $mount === '') continue; if ($storage_id === '') throw new RuntimeException('Bei einem Speicherort fehlt die Storage-ID.'); - if ($mount === '' || $mount[0] !== '/') throw new RuntimeException('Bei einem Speicherort fehlt ein gültiger lokaler Pfad.'); + if ($mount === '' || $mount[0] !== '/') throw new RuntimeException('Bei einem Speicherort fehlt ein gueltiger lokaler Pfad.'); $storages[] = array('storage_id'=>$storage_id, 'source_prefix'=>$prefix, 'local_mount'=>$mount); } if (!$storages) throw new RuntimeException('Mindestens ein Speicherort muss vorhanden sein.'); + $credentials = bratonien_tools_nc_connector_scoped_secret($connection); + $new_db_password = (string)($_POST['nc_db_password'] ?? ''); + if ($new_db_password !== '') $credentials['db_password'] = $new_db_password; + if (trim((string)($credentials['db_password'] ?? '')) === '') throw new RuntimeException('Fuer die Legacy-Verbindung ist kein Datenbankpasswort gespeichert.'); + + $nextcloud_url = trim((string)($_POST['nc_nextcloud_url'] ?? ($config['nextcloud_url'] ?? ''))); + $nextcloud_user = trim((string)($_POST['nc_nextcloud_user'] ?? ($credentials['nextcloud_user'] ?? ''))); + $new_nextcloud_password = (string)($_POST['nc_nextcloud_password'] ?? ''); + if ($new_nextcloud_password !== '') $credentials['nextcloud_password'] = $new_nextcloud_password; + $nextcloud_password = (string)($credentials['nextcloud_password'] ?? ''); + + $api_key_id = trim((string)($_POST['nc_connection_api_key_id'] ?? ($credentials['api_key_id'] ?? ''))); + $new_api_secret = trim((string)($_POST['nc_connection_api_key_secret'] ?? '')); + $old_api_id = trim((string)($credentials['api_key_id'] ?? '')); + if ($api_key_id !== $old_api_id && $new_api_secret === '') + { + throw new RuntimeException('Wenn die API-Schluessel-ID geaendert wird, muss auch das API-Geheimnis neu eingegeben werden.'); + } + if ($new_api_secret !== '') $credentials['api_key_secret'] = $new_api_secret; + $api_key_secret = trim((string)($credentials['api_key_secret'] ?? '')); + + if (($nextcloud_url === '' || $nextcloud_user === '' || $nextcloud_password === '') && ($nextcloud_url !== '' || $nextcloud_user !== '' || $nextcloud_password !== '')) + { + throw new RuntimeException('Nextcloud-Adresse, Nextcloud-Benutzer und Nextcloud-Passwort muessen fuer WebDAV gemeinsam vollstaendig sein.'); + } + if (($api_key_id === '') !== ($api_key_secret === '')) + { + throw new RuntimeException('Piwigo-API-Schluessel-ID und API-Geheimnis muessen gemeinsam vollstaendig sein.'); + } + + if ($nextcloud_url !== '') + { + $validated_nc = bratonien_tools_nc_connector_validate_nextcloud_access($nextcloud_url, $nextcloud_user, $nextcloud_password); + $nextcloud_url = $validated_nc['base_url']; + $nextcloud_user = $validated_nc['username']; + $credentials['nextcloud_user'] = $nextcloud_user; + } + if ($api_key_id !== '') + { + bratonien_tools_nc_connector_validate_scoped_api($api_key_id, $api_key_secret); + $credentials['api_key_id'] = $api_key_id; + } + $config['host'] = $host; $config['port'] = (string)$port; $config['database'] = $database; @@ -174,13 +310,16 @@ function bratonien_tools_nc_connector_update_local_friendly() $config['max_wait_seconds'] = max(60, (int)($_POST['nc_max_wait_seconds'] ?? ($config['max_wait_seconds'] ?? 900))); $config['full_sync_seconds'] = max(300, (int)($_POST['nc_full_sync_seconds'] ?? ($config['full_sync_seconds'] ?? 86400))); $config['storages'] = $storages; + if ($nextcloud_url !== '') + { + $config['nextcloud_url'] = $nextcloud_url; + $config['access_user'] = $nextcloud_user; + $config['nextcloud_access_user'] = $nextcloud_user; + } + $config['piwigo_auth'] = 'connection-scoped'; + $config['api_enabled'] = $api_key_id !== '' && $api_key_secret !== ''; unset($config['verification']); - $credentials = bratonien_tools_nc_connector_scoped_secret($connection); - $new_db_password = (string)($_POST['nc_db_password'] ?? ''); - if ($new_db_password !== '') $credentials['db_password'] = $new_db_password; - if (trim((string)($credentials['db_password'] ?? '')) === '') throw new RuntimeException('Für die Legacy-Verbindung ist kein Datenbankpasswort gespeichert.'); - $config_json = json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if (!is_string($config_json)) throw new RuntimeException('Connector-Konfiguration konnte nicht serialisiert werden.'); $secret_payload = json_encode($credentials, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); @@ -191,5 +330,9 @@ function bratonien_tools_nc_connector_update_local_friendly() $now = date('Y-m-d H:i:s'); pwg_query("UPDATE `$table` SET name='".pwg_db_real_escape_string($name)."', config_json='".pwg_db_real_escape_string($config_json)."', secret_blob='".pwg_db_real_escape_string($secret_blob)."', updated='".pwg_db_real_escape_string($now)."' WHERE id=".$id." LIMIT 1"); - return array('message'=>'Verbindung #'.$id.' wurde gespeichert. Die neuen Werte gelten ab dem nächsten Connector-Lauf.'); + $updated = bratonien_tools_nc_connector_connection($id, true); + $migration = $updated ? bratonien_tools_nc_connector_migration_state($updated) : array('ready'=>false); + return array( + 'message'=>'Verbindung #'.$id.' wurde gespeichert. '.(!empty($migration['ready']) ? 'Die WebDAV-Migration ist jetzt bereit.' : 'Die WebDAV-Migration ist noch nicht vollstaendig vorbereitet.'), + ); } From e3b1f06be330bb54d3d60bf532e733908b948d0d Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Wed, 19 Aug 2026 13:44:46 +0200 Subject: [PATCH 2/6] 0.9.6.10 expose complete safe edit metadata and migration readiness --- nc-connector-edit-data.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nc-connector-edit-data.php b/nc-connector-edit-data.php index 99e82f8..f1ecdb0 100644 --- a/nc-connector-edit-data.php +++ b/nc-connector-edit-data.php @@ -27,6 +27,7 @@ if (!function_exists('is_admin') || !is_admin()) require_once(BRATONIEN_TOOLS_PATH.'include/nc_connector.inc.php'); require_once(BRATONIEN_TOOLS_PATH.'include/nc_connector_manage.inc.php'); require_once(BRATONIEN_TOOLS_PATH.'include/nc_connector_connection_scope.inc.php'); +require_once(BRATONIEN_TOOLS_PATH.'include/nc_connector_edit.inc.php'); $id = (int)($_GET['connection_id'] ?? 0); $connection = bratonien_tools_nc_connector_connection($id, true); @@ -39,13 +40,19 @@ if (!$connection) $config = isset($connection['config']) && is_array($connection['config']) ? $connection['config'] : array(); $credentials = array(); +$migration = array('ready'=>false, 'missing'=>array()); try { $credentials = bratonien_tools_nc_connector_scoped_secret($connection); + if ((string)$connection['adapter'] === 'local') + { + $migration = bratonien_tools_nc_connector_migration_state($connection); + } } catch (Throwable $e) { $credentials = array(); + $migration = array('ready'=>false, 'missing'=>array('gespeicherte Zugangsdaten konnten nicht gelesen werden')); } $storages = array(); @@ -79,6 +86,15 @@ $payload = array( 'full_sync_seconds'=>(int)($config['full_sync_seconds'] ?? 86400), 'storages'=>$storages, ), + 'webdav'=>array( + 'nextcloud_url'=>(string)($config['nextcloud_url'] ?? ''), + 'nextcloud_user'=>(string)($credentials['nextcloud_user'] ?? $config['nextcloud_access_user'] ?? $config['access_user'] ?? ''), + 'has_nextcloud_password'=>(string)($credentials['nextcloud_password'] ?? '') !== '', + 'api_key_id'=>(string)($credentials['api_key_id'] ?? ''), + 'has_api_key_secret'=>trim((string)($credentials['api_key_secret'] ?? '')) !== '', + 'migration_ready'=>!empty($migration['ready']), + 'migration_missing'=>array_values((array)($migration['missing'] ?? array())), + ), ); echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); From 94c81789eda50b1ef237f2c1521b4523d0422033 Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Wed, 19 Aug 2026 13:46:26 +0200 Subject: [PATCH 3/6] 0.9.6.10 rebuild connection editor around complete connection data --- js/nc_connector_edit_v2.js | 205 +++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 js/nc_connector_edit_v2.js diff --git a/js/nc_connector_edit_v2.js b/js/nc_connector_edit_v2.js new file mode 100644 index 0000000..59966ac --- /dev/null +++ b/js/nc_connector_edit_v2.js @@ -0,0 +1,205 @@ +(function () { + 'use strict'; + + function ready(callback) { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function () { window.setTimeout(callback, 0); }); + } else { + window.setTimeout(callback, 0); + } + } + + ready(function () { + var section = document.getElementById('nc-connector'); + if (!section) return; + + var pwgTokenInput = section.querySelector('input[name="pwg_token"]'); + var pwgToken = pwgTokenInput ? pwgTokenInput.value : ''; + var modeKey = 'bratonienNcWizardMode'; + + function escapeHtml(value) { + return String(value == null ? '' : value).replace(/[&<>"']/g, function (c) { + return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]; + }); + } + + function setMode(value) { + try { sessionStorage.setItem(modeKey, value); } catch (e) {} + } + + function postForm(label, tool, id, mode) { + var form = document.createElement('form'); + form.method = 'post'; + form.style.display = 'inline'; + form.dataset.ncV2Action = tool; + form.innerHTML = '' + + '' + + ''; + if (mode) form.addEventListener('submit', function () { setMode(mode); }, true); + return form; + } + + function loadConnection(id) { + return fetch('plugins/bratonien_tools/nc-connector-edit-data.php?connection_id='+encodeURIComponent(id)+'&_='+Date.now(), { + credentials:'same-origin', + cache:'no-store', + headers:{'Accept':'application/json'} + }).then(function (response) { + return response.json().then(function (data) { + if (!response.ok) throw new Error(data.error || ('HTTP '+response.status)); + return data; + }); + }); + } + + function dialog() { + var node = document.getElementById('bratonien-nc-connection-edit-v2'); + if (node) return node; + node = document.createElement('dialog'); + node.id = 'bratonien-nc-connection-edit-v2'; + node.className = 'bratonien-edit-dialog'; + node.innerHTML = '
' + + '
' + + '

Verbindung bearbeiten

Alle Daten dieser Verbindung werden hier gepflegt. Eine Migration ist ein eigener Vorgang.

' + + '
' + + '
'; + document.body.appendChild(node); + node.querySelector('[data-edit-v2-close]').addEventListener('click', function () { node.close(); }); + node.addEventListener('click', function (event) { if (event.target === node) node.close(); }); + return node; + } + + function storageRow(storage) { + storage = storage || {}; + return '
' + + '' + + '' + + '' + + '
'; + } + + function openEditor(id) { + var editDialog = dialog(); + var content = editDialog.querySelector('[data-edit-v2-content]'); + content.innerHTML = '

Verbindung wird geladen …

'; + if (typeof editDialog.showModal === 'function') editDialog.showModal(); + else editDialog.setAttribute('open', 'open'); + + loadConnection(id).then(function (data) { + if (data.adapter !== 'local') throw new Error('Diese Ansicht ist nur für die bestehende Legacy-Verbindung vorgesehen.'); + var legacy = data.legacy || {}; + var webdav = data.webdav || {}; + var storages = Array.isArray(legacy.storages) ? legacy.storages : []; + var rows = storages.map(storageRow).join('') || storageRow({}); + var migrationText = webdav.migration_ready + ? 'Bereit. Nextcloud-Zugang und verbindungseigener Piwigo-API-Key sind vollständig gespeichert.' + : 'Noch nicht bereit. Es fehlen: '+escapeHtml((webdav.migration_missing || []).join(', ') || 'WebDAV-Zugangsdaten')+'.'; + + content.innerHTML = '
' + + '' + + '' + + '
Verbindung
' + + '' + + '
' + + '
Nextcloud / WebDAV
' + + '

Diese Angaben werden für den neuen WebDAV-Weg benötigt und gehören zu genau dieser Verbindung.

' + + '
' + + '' + + '' + + '' + + '
' + + '
Piwigo API dieser Verbindung
' + + '

Der API-Key wird verbindungseigen gespeichert und beim Speichern geprüft.

' + + '
' + + '' + + '' + + '
' + + '

WebDAV-Migration: '+migrationText+'

' + + '
Bestehender Legacy-Weg
' + + '' + + '' + + '' + + '' + + '' + + '
' + + '
Speicherorte
'+rows+'
' + + '' + + '
Erweiterte Legacy-Einstellungen
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + '
' + + '
'; + + var form = content.querySelector('[data-edit-v2-form]'); + form.querySelector('[data-edit-v2-cancel]').addEventListener('click', function () { editDialog.close(); }); + form.querySelector('[data-add-storage]').addEventListener('click', function () { + form.querySelector('[data-storage-list]').insertAdjacentHTML('beforeend', storageRow({})); + }); + form.addEventListener('click', function (event) { + var remove = event.target.closest('[data-remove-storage]'); + if (!remove) return; + var row = remove.closest('[data-storage-row]'); + if (row) row.remove(); + }); + }).catch(function (error) { + content.innerHTML = '

Bearbeiten nicht möglich: '+escapeHtml(error.message || String(error))+'

'; + }); + } + + function rebuildLocalActions(deleteForm, id) { + var actions = deleteForm.parentElement; + if (!actions) return; + + [].slice.call(actions.querySelectorAll('form')).forEach(function (form) { + var migrate = form.querySelector('button[value="nc_connector_migrate_start"]'); + if (migrate) form.remove(); + }); + [].slice.call(actions.children).forEach(function (child) { + if (child.tagName === 'BUTTON' && (child.textContent || '').trim() === 'Bearbeiten') child.remove(); + if (child.dataset && child.dataset.ncMigrationInfo) child.remove(); + }); + + var edit = document.createElement('button'); + edit.type = 'button'; + edit.className = 'buttonLike'; + edit.textContent = 'Bearbeiten'; + edit.addEventListener('click', function () { openEditor(id); }); + actions.insertBefore(edit, deleteForm); + + var info = document.createElement('span'); + info.dataset.ncMigrationInfo = '1'; + info.className = 'bratonien-base-note'; + info.textContent = 'WebDAV-Migration wird geprüft …'; + actions.insertBefore(info, deleteForm); + + loadConnection(id).then(function (data) { + var webdav = data.webdav || {}; + if (webdav.migration_ready) { + info.remove(); + actions.insertBefore(postForm('Auf WebDAV migrieren', 'nc_connector_migrate_start', id, 'migrate'), deleteForm); + } else { + var missing = (webdav.migration_missing || []).join(', '); + info.textContent = 'WebDAV-Migration noch nicht bereit: '+(missing || 'Zugangsdaten fehlen')+'. Zuerst „Bearbeiten“.'; + } + }).catch(function (error) { + info.textContent = 'WebDAV-Migration kann nicht geprüft werden: '+(error.message || String(error)); + }); + } + + [].slice.call(section.querySelectorAll('button[value="nc_connector_delete"]')).forEach(function (deleteButton) { + var deleteForm = deleteButton.closest('form'); + var card = deleteButton.closest('details'); + if (!deleteForm || !card) return; + var idInput = deleteForm.querySelector('input[name="connection_id"]'); + if (!idInput) return; + var text = card.textContent || ''; + var isLocal = text.indexOf('bestehende Legacy-Konfiguration') !== -1; + if (isLocal) rebuildLocalActions(deleteForm, idInput.value); + }); + }); +})(); From 84d263b16b473e52d8ef719debefdd269c4614b3 Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Wed, 19 Aug 2026 13:47:48 +0200 Subject: [PATCH 4/6] 0.9.6.10 load complete connector editor on admin page --- include/tool_registry.inc.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/tool_registry.inc.php b/include/tool_registry.inc.php index 7846821..a267193 100644 --- a/include/tool_registry.inc.php +++ b/include/tool_registry.inc.php @@ -4,6 +4,16 @@ if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!'); } +if (isset($GLOBALS['template']) && is_object($GLOBALS['template']) && method_exists($GLOBALS['template'], 'func_combine_script')) +{ + $GLOBALS['template']->func_combine_script(array( + 'id'=>'bratonien_nc_connector_edit_v2', + 'path'=>BRATONIEN_TOOLS_PATH.'js/nc_connector_edit_v2.js', + 'load'=>'footer', + 'version'=>function_exists('bratonien_tools_current_version') ? bratonien_tools_current_version() : '0.9.6.10', + )); +} + require_once(BRATONIEN_TOOLS_PATH . 'tools/image_cache.inc.php'); require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark.inc.php'); require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark_profiles.inc.php'); From 60c0a51f01e6f240131a507a0d17755994e7641e Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Wed, 19 Aug 2026 13:48:07 +0200 Subject: [PATCH 5/6] 0.9.6.10 bump plugin version --- main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.inc.php b/main.inc.php index dd78481..f9896a1 100644 --- a/main.inc.php +++ b/main.inc.php @@ -1,7 +1,7 @@ Date: Wed, 19 Aug 2026 13:48:26 +0200 Subject: [PATCH 6/6] 0.9.6.10 lint standalone connector editor JavaScript --- .github/workflows/lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 60d8fad..76e6c52 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -42,6 +42,7 @@ jobs: set -euo pipefail sed -n '/