There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
There is a problem with this format because it doesn't follow the URI RFC so that standard URI parsers won't parse it very well. Adding the // after bridge: makes it a "hierarchical" URI, which means that it has the standard sections of authority, user info, host, port, path, query, and fragment. But the above URI will just stick all of the text in the "authority" part, but that section can't be broken down into the standard parts of the "authority", i.e. user info, host, and port.
To keep the same data format, then this URI should be an "opaque" URI. That just means removing the //. So that makes it like a mailto: URI.
Otherwise, the data could be refactored to fit into the standard parts for a hierarchical URI, then standard URI parsing classes will be able to parse it. For example, android.net.Uri, java.net.URL, etc. That would make the URI look something like this:
After a couple of years of working with URLs for sending info around in ChatSecure, F-Droid, etc. I think should revisit the original ideas of these bridge URIs.
The most popular custom scheme that I can think of are magnet: links for torrents. They are a very similar idea as a bridge link. So we should be able to use BitTorrent apps on all platfroms as an example of how to handle these links. Using a custom URI scheme makes it easier to make a link that the browser will never handle, and always look for an app to send it too. Also, using a custom URI Scheme like bridge: means that clicking these URIs in apps is much less likely to ever go to another app, since those apps would have to have specifically created the association. Also, browser let you specific custom handlers for URI Schemes they do not understand. These can be specified to closely match the Bridge lines in torrc. So this collection of fake bridges:
In desktop Firefox, you can add support for bridge: URIs by adding a custom "Protocol Handler":
load about:config
Right-click -> New -> Boolean -> Name: network.protocol-handler.expose.bridge -> Value -> false
Next time you click a link of protocol-type bridge you will be asked which application to open it with.
Chromium on Ubuntu will automatically prompt to open with xdg-open. That will then use the standard, cross-distro XDG methods for registering and using custom schemes that are used in GNOME, KDE, etc. etc. Tor Browser's .desktop file should be able to do this. Any Debian/etc. package can install and configure the .desktop files and XDG Mime stuff as part of the package install. Here's a manual example:
There are similar mechanisms on Windows and MacOS. For example MacOS has the open util which does was GNU/Linux's xdg-open does.
http: link with fake domain name
One problem with having the bridge link clickable and having a real domain name is that it could leak info to the internet that the user is looking for a bridge. So there could be a fake domain name for these links to provide a pattern to match for in things like the OS-level URL matchers in Android and iOS. Something like http://bridge.onion/ will never exist but is somehow a reserved domain name. These links would then automatically show up as clickable on desktop and mobile apps, but should never cause network traffic.
his will lead to confusing failures since the browser will say "bridge.onion’s server IP address could not be found."
** https: link with real domain name, like ChatSecure**
Using a real domain name like https://bridges.torproject.org provides a way to provide the user direct feedback when they are trying to add a bridge via URL. If the user clicks on a bridge URL and it fails to go to Tor Browser, then they'll see the page on bridges.torproject.org. If the config information is included in the query string, then bridges.torproject.org can automatically generate a proper bridge: URI, which the user can click to send the info out of the browser. The page can also provide a HOWTO for setting up bridge: support for their OS.
ChatSecure's invite links have a nice feature in that Android and iOS will automatically route them to the ChatSecure app, even if they are clicked in the browser. Then if the ChatSecure app is not installed, the link will open up in the browser with instructions on how to get ChatSecure and use the links. With these links, the data is included in the URI Fragment, (e.g. stuff after #) which should never be sent to the network. That protects privacy, but makes it harder for the server to provide useful feedback. Here is an example URI:
Android has this method of registering a domain name as the official domain name that is tied to the app. It has the nice feature that any link with that domain name will go straight to the matching app, and not be sent to other apps. It does require some setup on the web server. The big downside is that it only works if that app only claims links with that domain name and nothing else. We tried using this in F-Droid, but did not want to give up claiming market: and https://play.google.com links. They are known as "Android App Links". iOS also has this, they are known as "Apple Universal Links".
** Use URL-safe base64!!**
Right now, the data is encoded in standard base64, which means it had to be encoded and decoded to work in URIs. It would be better to switch to URL-safe base64 (RFC4648), which replaces the use of the chars + and / with - and _. This is because and _. + and / have special meaning in URIs. I don't know what all this entails, so for now, the URL generation will need to know to URL-encode +, /, and =. (e.g. %2B, %2F, and %3D). Just encoding + is often enough, since / often works fine in a URL query string value, and the base64 padding character = does not seem to be often used in bridge configs.
The additional idea with the " https: link with real domain name, like ChatSecure" proposal, is that if no app intercepts the https link, it will go to a page, that can offer step-by-step how-to and also a bridge: direct link.
This is useful, as well, for someone who doesn't have any app installed yet, and is just given a bridge link. It can take them to the approach app download/install page.
This is what ChatSecure does, offering an xmpp: link on the link invite page.
what we are doing is TorSetConf(), the key is "Bridge" and the value is an array with the bridge lines you got, (that's part of aSettingsObj). Part of aSettingsObj in that case is UseBridges: true as well. This is then sent to tor via a SETCONF command. The resulting changes are written to disk in your tor browser dir at Browser/TorBrowser/Data/Tor/torrc.
One thing I forgot to include here is the possibility of including multiple bridges in a single, clickable URL. All of the logic of clickability and https:// vs bridge: links applies. Allowing multiple bridges in a single URL changes the concept of the URL, since a URL is meant to point to a singular thing. It could be conceived of as a "bridge line URL" vs a "bridge config URL".
The missing piece here is how to clearly mark a bridge URL with multiple bridges so that it can be automatically detected. It could be done via:
scheme: bridge: vs. bridges:
host: http://bridge.onion vs http://bridges.onion
path: https://bridges.torproject.org/bridges?transport0=meek_lite&ip0=0.0.2.0&port0=2&transport1=meek_&ip1=1.0.2.0&1port=4 (there is no standard for encoding arrays in URLs, but transport[]= might be a strong enough convention)
query: ?bridge_config=y&...
etc...
The UX of single bridge URLs seems easier to map out, since clicking a bridge URL maps cleanly to "add a bridge line". But this might mean more clicks for the user, or other confusions. Clicking a bridge config URL is not so clean. Does it mean replace all the bridge lines with what is in the URL? Or just add all those bridges? So the best approach is going to depend a lot on how users conceive of bridges and these URLs they are clicking.