Repository: syncthing/syncthing (language: go)

Issue:
Scope ID should be filtered out of IPv6 addresses when using Remote GUI
Syncthing seems to list IPv6 addresses with their scope ID (e.g. `%Wi-Fi` in the screenshot). These addresses are not supported in popular browsers like Chrome or Firefox. While this doesn't matter much in case of simply listing the address, the problem is real when using the Remote GUI option, as the rendered URLs are broken. In fact, they aren't even treated as proper URLs by the browsers, so there's no copy link option under the right click menu and such.

I think it would be useful to simply filter out scope IDs from the addresses, which should make them work properly in Web browsers.

![image](https://user-images.githubusercontent.com/5626656/147370390-a8895132-9830-46f2-93cd-9e15d57b12e6.png)


Discussion / hints:
Probably the percent sign needs percent encoding. This is the bane of ipv6 addresses in urls. The url won't be usable without it anyhow as the address is link local and only makes sense on the link (interface) in question. 
> The url won't be usable without it anyhow as the address is link local and only makes sense on the link (interface) in question.

It does work fine after removing the scope id. I'm testing on devices that have got only one type of network interface installed though.
I suspect that's a special corner case though, not general. 
During the discussion where the remote GUI link was implemented, this has been considered and deemed too complicated to try any "corrections".  As has been said, link local addresses are only valid on the same host and there even only with the interface specifier.  As we do not even know if the browser displaying the GUI is on the same host or local network, giving out the address verbatim for the user to decide is the best - we could do.  Note that the remote GUI feature needs to be explicitly enabled, so that's only really useful for hosts with a stable IP address.

And browsers not handling link local IPv6 addresses in URLs is a bug in my opinion and still being discussed among browser vendors and the WhatWG. 
> Note that the remote GUI feature needs to be explicitly enabled, so that's only really useful for hosts with a stable IP address.

The situation I've got here is that the devices have static IPs (v4) set on the router. Then, I set the remote GUI port to `8384` in Syncthing. In most cases, the pre-defined IPv4 addresses are filled in automatically and these do work fine. However, sometimes IPv6 addresses get filled in instead. These do not work unless I select and copy the "link" and remove the scope ID from it first.

> And browsers not handling link local IPv6 addresses in URLs is a bug in my opinion and still being discussed among browser vendors and the WhatWG.

Yeah, but as things are right now, the user is left with non-working URLs. It doesn't even seem possible to apply any manual fixes, as only the port can be set for the remote GUI, and not the actual address.
> In most cases, the pre-defined IPv4 addresses are filled in automatically and these do work fine. However, sometimes IPv6 addresses get filled in instead.

So what would help in that case is to restrict the remote device to IPv4 only, something like a `dynamic4` entry in the remote address configuration.

> Yeah, but as things are right now, the user is left with non-working URLs. It doesn't even seem possible to apply any manual fixes, as only the port can be set for the remote GUI, and not the actual address.

If the address is known in advance and never changes, then you can just use a bookmark in your browser. The feature is specifically to use the discovered address, just with a different port. 
> So what would help in that case is to restrict the remote device to IPv4 only, something like a dynamic4 entry in the remote address configuration.

Sort of orthogonal to the rest of discussion, but the way to express this in Syncthing currently is `allowed networks = 0.0.0.0/0`

Fix patch:
diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js
index 8b998a14286..de5d3265932 100755
--- a/gui/default/syncthing/core/syncthingController.js
+++ b/gui/default/syncthing/core/syncthingController.js
@@ -1202,7 +1202,8 @@ angular.module('syncthing.core')
         $scope.remoteGUIAddress = function (deviceCfg) {
             // Assume hasRemoteGUIAddress is true or we would not be here
             var conn = $scope.connections[deviceCfg.deviceID];
-            return 'http://' + replaceAddressPort(conn.address, deviceCfg.remoteGUIPort);
+            // Use regex to filter out scope ID from IPv6 addresses.
+            return 'http://' + replaceAddressPort(conn.address, deviceCfg.remoteGUIPort).replace('%.*?\]:', ']:');
         };
 
         function replaceAddressPort(address, newPort) {


Test patch: