2023-06-18

the eternal mystery of xdg-open & mimetypes

the eternal mystery of xdg-open & mimetypes

: # Abstract: an Xfce Perspective

In Xfce there are 4 preferred applications maintainable via a settings GUI, which changes are reflected in the ~/.config/xfce4/helpers.rc & a separate infrastructure of exo- programs & *.desktop entries which ultimately get the preferred browser up in many situations. However an app like the html deck which manages the JS 2048 is scheduled via a *.desktop entry invoking xdg-open, a venerable & mannerly mass of /bin/sh code. Although checking envvars for the ${BROWSER} & desktop environment (eg Xfce which it finds on ALTxfce), it is capable of falling thru to a generic handler (which it does on eg TDE or LXQt). In either case it makes a query via the xdg-mime script which returns the target browser from xdg overrides of the mimeDB in /usr/share/mime. These overrides are located in /usr/share/applications [sic], the base called "mimeinfo.cache" (labelled internally as [MIME Cache]), which may be further qualified variously by "mimeapps.list" or "defaults.list" files depending on the implementation. Any of these can be overridden via individual lines placed in decks residing in ~/.local/share/applications or better still, ~/.config.

: # Bringing up a Browser by Mimetype: 2048.desktop

Thus on lubuntu-next a call to "xdg-mime query default text/html" returns firefox despite its absence from the system due to a symlink to /etc/gnome/defaults.list, whereas xdg-open on a vanilla system invokes qupzilla as specified in the mimeinfo.cache. The LXQt preferences have an interface to mime called "FileAssociations" which apparently reads the mimeDB directly, informed by mods made to its packages directory by installs such as Opera, which it represents as the handler for text/html which it is not until it creates an explicit ~/.local/share/applications/mimeapps.list with the requisite [Default Applications] entry.

On the Urix 7.0.3 Xfce implementation a slightly different situation obtains. Although a mimeinfo.cache is present in /usr/share/applications, neither handcoded override in ~/.local/share/applications is observed, so recourse can be made to the Xfce mimetype maintenance in the SettingsManager. Once again this is likely populated from /usr/share/mime, & when the change is made to text/html it places a mimeapps.list in ~/.config itself. In short, its useful to be apprised of the extract xdg is maintaining, but it may have no bearing on what will be sourced at xdg-open time, & a supported distro specific mime maintenance GUI should be consulted for not necessarily authoritative clues to where any resulting user overrides might reside.

A good example of this is a Trinity distro such as ExeGNU, which has a /usr/share/mime but has none of the overrides to it built in /usr/share/applications. Fortunately it has a KDE style "file associations" facility of its own in the Trinity Control Centre under TDEcomponents. When this is used to alter the text/html mimetype, the override is reflected not in ~/.local/share/applications or ~/.config, but rather in a ~/.trinity/share/config resource called the profilerc. As one might expect, this has no effect whatsoever on the behaviour of xdg-open invoked from a *.desktop. In fact, ExeGNU does not even have an xdg-open script at all. Fortunately a pair of packages can be installed: desktop-file-utils which includes update-desktop-database which creates the mimeinfo.cache, & xdg-utils which includes xdg-open. The archwiki maintains that the ~/.config location is preferable over the deprecated ~/.local/share/applications, but in fact even a direct mod to the generated mimeinfo.cache wont keep firefox from being invoked, proving this resource isnt even being consulted. A look at xdg-open shows that it can simply use the (unset) ${BROWSER} envvar, but is in fact dropping thru to the x-www-browser which invokes firefox from /etc/alternatives. This is because its call to "xdg-mime query default" is coming back empty although its looking for the mimeapps.list in a number of places including ~/.local/share/applications. What it therefore requires is a handcoded deck with a single *.desktop handler for text/html under the [Default Applications] category.

On parrotsec mate the 2048.desktop xdg-open brings up the index.html in pluma [sic], but its possible to determine why. First of all, /usr/share/mime exists, & so does /usr/share/applications/mimeinfo.cache, the latter once again unconsulted as its text/html entry points predictably to the browsers. The concatenation in the envvar XDG_DATA_DIRS starts with /usr/share/mate whose applications directory contains a symlink pointing to /etc/mate/defaults.list, a deck of also unconsulted mimetypes which directs text/html to iceweasel. There is no mimetype fileassociation maintenance interface provided by the DE, but if the PreferredApplications GUI is run from the System:Preferences:Personal menu a mimeapps.list is dumped into ~/.config, however including no text/html line. A search thru /etc for pluma finally reveals the /etc/skel/.local/share/applications/mimeapps.list which is copied unaltered at boottime to the ${HOME} directory should it not exist, & which contains both [Default Applications] & [Added Associations] entries associating text/html with pluma.desktop. Adjusting the former via ones preferred text editor allows the 2048 javascript to be executed in a specified webbrowser.

OpenSUSE tumbleweed confirms the essence of the Xfce default behaviour, as /usr/share/applications/mimeinfo.cache exists, & the supplied GUI mimetype editor indeed drops user overrides into ~/.config/mimeapps.list, the preferred location per the archwiki. ZorinLite Xfce introduces an additional twist, as the XDG_DATA_DIRS start with /usr/share/zorin-os-lite whose applications directory contains a defaults.list with a text/html line pointing to the Xfce specific exo-web-browser.desktop. Thus xdg-open invokes the exo- facility which in the absence of a helpers.rc in ~/.config/xfce4 brings up a prompt for a preferred webbrowser. This can be obviated proactively by using the mimetype editor to create a ~/.config/mimeapps.list which will be consulted instead.

Despite being a faithful Xfce / Jessie implementation, Robolinux behaves more like parrotsec, with xdg-open bringing up text/html in mousepad [sic]. Its /usr/share/applications is free of overrides to the mimeinfo.cache which is apparently unconsulted as it specifies thunderbird, firefox, & google-chrome as handlers. The /usr/share/xfce4 leading off the XDG_DATA_DIRS concatenation includes an applications directory with a symlink to an empty /etc/xfce4/defaults.list. & there is a /etc/skel/.config/mimeapps.list copied at boottime to ${HOME} should it not exist, but it contains hardcoded references to a firefox desktop which is not present on the system. In fact, "xdg-mime query default text/html" returns nothing, so the Xfce mimetype editor & xdg-open may both be falling back to text/plain in order to associate text/html with mousepad. When Opera is specified to the mimetype editor the change is reflected in the [Default Applications] portion of the ~/.config/mimeapps.list, which allows the menu pick to execute the javascript in a browser.

MX Linux is as always nearly identical to Robo in its configuration & behaviour, although it brings 2048 up in firefox. The main difference is that in /etc/skel there is a .local/share/applications/mimeapps.list which is copied to ${HOME} at boottime & contains the [Added Associations] & [Default Applications] overrides to text/html in the mimeinfo.cache, all 3 of them specifying firefox. When adjusted via the mimetype editor, changes are reflected in ~/.config/mimeapps.list & bring up 2048 in Opera. In fact, ~/.config/mimeapps.list isnt even consulted by xdg-mime, which isnt used on MX Linux anyway by virtue of XDG_CURRENT_DESKTOP being set to 'XFCE', which causes exo-open to be called directly by xdg-open.

Fedora Xfce takes the RPM style approach encountered in ALTxfce where mimeapps.list is present in /usr/share/applications along with mimeinfo.cache, but the actual overrides are contained in yet another file "xfce-mimeapps.list" which specifies the exo-web-browser. There is nothing added to the XDG_DATA_DIRS & nothing in /etc/skel, but a ~/.config/xfce4/helpers.rc is created at boottime if one does not exist, & in its absence the exo- system prompts for a browser when xdg-open is called. The mimetype editor recognises this & when adjusted puts the overrides in ~/.config/mimeapps.list where they belong.

So the behaviour on ALTlxqt should not be at all surprising. Like ALTxfce both mimeinfo.cache & mimeapps.list appear in /usr/share/applications along with a zeroed out defaults.list, & there are no overrides whatsoever present in ${HOME}. The "xdg-mime query default text/html" call returns qupzilla, as it drops thru all the way to the mimeinfo.cache. The call to xdg-open fails however as it identifies the DE from the DESKTOP_SESSION envvar & tries to invoke pcmanfm which has been summarily removed in favour of pcmanfm-qt. This can be fixed by a single symlink & pcmanfm-qt can be shown to be exhibiting the same behaviour as the "FileAssociations" mimetype editor as it believes Opera is the default handler already, apparently from the installtime update to /usr/share/mime/packages. If the mimetype editor is invoked & Opera confirmed explicitly as the text/html handler, it creates a ~/.local/share/applications/mimeapps.list which is then successfully consulted by xdg-mime when called from xdg-open, taking pcmanfm-qt entirely out of the loop.

& of course the situation with Void Xfce is exactly what one would expect. The Xfce config is completely vanilla & there is a mimeinfo.cache in /usr/share/applications, but although xdg-utils is in the repo it is not installed so a *.desktop referencing xdg-open will fail categorically. Once this is corrected xdg-mime drops thru to the mimeinfo.cache & effects the invocation of firefox, & when adjusted in the mimetype editor a ~/.config/mimeapps.list is created reflecting the user specified browser.

Like parrotsec & robo, the runtu xdg-open brings up text/html in geany [sic] despite a mimeinfo.cache & a defaults.list (once again a symlink to /etc/gnome/defaults.list) specifying firefox. This is due to an /etc/skel/.local/share/applications/mimeapps.list which is copied to ${HOME} at boottime should it be absent. Adjustments made via the Xfce mimetype editor are properly reflected in the ~/.config/mimeapps.list, allowing the 2048.desktop menupick to execute the app in a browser. Xubuntu itself has the dreaded /etc/gnome/defaults.list symlink, but its XDG_DATA_DIRS start with /usr/share/xubuntu whose applications directory contains a defaults.list pointing text/html at the exo-web-browser to be picked up from the ~/.config/xfce4/helpers.rc. Once again the xfce mimetype editor will place the proper adjustment in a ~/.config/mimeapps.list.

The Sparky Xfce situation is also readily understandable. There is no ~/.config/mimeapps.list but there is one in ~/.local/share/applications which seems to have been generated at boottime. The /usr/share/applications/mimeinfo.cache is apparently regenerated if apt-get is used, meaning it is informed by the packages directory found in /usr/share/mime. This means that the call to xdg-mime at xdg-open time succeeds in returning browser.desktop because of my Opera install. On Rosa R9 LQXt the usual lxqt / RPM style pattern is evident. There are both a mimeinfo.cache & a mimeapps.list in /usr/share/applications, the former reflecting the newmoon install & the latter pointing to the not present firefox by virtue of which xdg-mime tries to invoke it at xdg-open time. The LXQt file associations is primed via Opera from the packages directory, but again this is not in effect until confirmed which results in the creation of a ~/.local/share/applications/mimeapps.list.

: # Processing text/plain in xdg-open

Yet more perspective is gained on LXQtExTiX by having nnn select a text/plain document. /usr/share/applications has both the authoritative mimeinfo.cache & the defaults.list symlink to /etc/gnome/defaults.list which last would bind text/plain to gedit.desktop which is not on the system. Theres nothing cluttering ~/.local/share/applications & a CLI xdg-open of the file brings it up in less, owing to the passage in xdg-open which successfully runs the perl script run-mailcap. The doc for nnn says it is using xdg-open directly, & run this way run-mailcap fails & it drops thru to the venerable mimeopen, also in perl, resulting in vim being opened in an xterm by virtue of the mimeinfo.cache referencing the vim.desktop which specifies Terminal=true. The xterm is hardcoded in DesktopEntry.pm in /usr/share/perl5/File & apparently represents one of the most fundamental failsafes in the gnu/linux/x11 world. The LXQt FileAssociations dialogue can now select a more rational standalone editor such as Beaver, which is reflected in the preferred ~/.config/mimeapps.list.

Back at Lubuntu Cosmic Cuttlefish the nnn behaviour isnt so varied. In /usr/share/applications theres still a defaults.list symlink to lala land along with the authoritative mimeinfo.cache pointing text/plain to *.desktops for vim, libreoffice-writer, & featherpad. The xdg-mime query default text/plain unequivocally returns featherpad.desktop however, the behaviour observed from xdg-open both at the CLI & when pressing enter in nnn. This is because of /etc/xdg/xdg-Lubuntu concatenated at the head of ${XDG_CONFIG_DIRS} where it finds a mimeapps.list with 2 lines pointing text & shellscripts to featherpad. Once again a sane alternative can be established in ~/.config/mimeapps.list via FileAssociations.

SparkyLXQt based on buster@testing also exhibits a manageable behaviour. There is no longer a boottime generated mimeapps.list & the mimeinfo.cache routes text/plain merely to libreoffice-writer & featherpad *.desktops, the former used by both nnn & xdg-open to bring up a textfile. FileAssociations establishes a sane alternative in ~/.config/mimeapps.list.