mimeo: fix infinite loop when dispatching non-specialized http/s URLs

This commit is contained in:
2023-12-11 04:49:36 +00:00
parent 008a6192d4
commit ad82bb2630
6 changed files with 121 additions and 46 deletions

View File

@@ -44,7 +44,7 @@
./lemoa.nix
./mako.nix
./mepo.nix
./mimeo.nix
./mimeo
./mopidy.nix
./mpv.nix
./msmtp.nix

View File

@@ -204,8 +204,6 @@ in
"x-scheme-handler/about" = desktop;
"x-scheme-handler/unknown" = desktop;
};
# TODO: cleanup mimeo and remove this
mime.urlAssociations."^https?://.*" = "librewolf --name librewolf %U";
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback

View File

@@ -1,42 +0,0 @@
{ config, lib, pkgs, ... }:
let
# [ ProgramConfig ]
enabledPrograms = builtins.filter
(p: p.enabled)
(builtins.attrValues config.sane.programs);
fmtAssoc = regex: cmd: ''
${cmd}
${regex}
'';
assocs = builtins.map
(program: lib.mapAttrsToList fmtAssoc program.mime.urlAssociations)
enabledPrograms;
assocs' = lib.flatten assocs;
in
{
sane.programs.mimeo = {
package = pkgs.mimeo.overridePythonAttrs (upstream: {
nativeBuildInputs = (upstream.nativeBuildInputs or []) ++ [
pkgs.copyDesktopItems
];
desktopItems = [
(pkgs.makeDesktopItem {
name = "mimeo";
desktopName = "Mimeo";
exec = "mimeo %U";
comment = "Open files by MIME-type or file name using regular expressions.";
})
];
installPhase = ''
runHook preInstall
${upstream.installPhase}
runHook postInstall
'';
});
fs.".config/mimeo/associations.txt".symlink.text = lib.concatStringsSep "\n" assocs';
mime.priority = 20;
mime.associations."x-scheme-handler/http" = "mimeo.desktop";
mime.associations."x-scheme-handler/https" = "mimeo.desktop";
};
}

View File

@@ -0,0 +1,78 @@
# mimeo is an exec dispatcher like xdg-open, but why allows mapping different URL regexes to different handlers.
# my setup sets mimeo as the default http/https handler,
# and from there it dispatches specialized rules, falling back to the original http/https handler if no URL specialization exists
{ config, lib, pkgs, ... }:
let
mimeo-open-desktop = pkgs.static-nix-shell.mkPython3Bin {
pname = "mimeo-open-desktop";
src = ./.;
pkgs = [ "mimeo" ];
};
# [ProgramConfig]
enabledPrograms = builtins.filter
(p: p.enabled)
(builtins.attrValues config.sane.programs);
# [ProgramConfig]
sortedPrograms = builtins.sort
(l: r: l.priority or 1000 < r.priority or 1000)
enabledPrograms;
fmtAssoc = regex: desktop: ''
${mimeo-open-desktop}/bin/mimeo-open-desktop ${desktop} %U
${regex}
'';
assocs = builtins.map
(program: lib.mapAttrsToList fmtAssoc program.mime.urlAssociations)
sortedPrograms;
assocs' = lib.flatten assocs;
fmtFallbackAssoc = mimeType: desktop: if mimeType == "x-scheme-handler/http" then ''
${mimeo-open-desktop}/bin/mimeo-open-desktop ${desktop} %U
^http://.*
'' else if mimeType == "x-scheme-handler/https" then ''
${mimeo-open-desktop}/bin/mimeo-open-desktop ${desktop} %U
^https://.*
'' else "";
fmtFallbackAssoc' = mimeType: desktop:
lib.optionalString (desktop != "mimeo.desktop") (fmtFallbackAssoc mimeType desktop);
fallbackAssocs = builtins.map
(program: lib.mapAttrsToList fmtFallbackAssoc' program.mime.associations)
sortedPrograms;
fallbackAssocs' = lib.flatten fallbackAssocs;
in
{
sane.programs.mimeo = {
package = pkgs.mimeo.overridePythonAttrs (upstream: {
nativeBuildInputs = (upstream.nativeBuildInputs or []) ++ [
pkgs.copyDesktopItems
];
desktopItems = [
(pkgs.makeDesktopItem {
name = "mimeo";
desktopName = "Mimeo";
exec = "mimeo %U";
comment = "Open files by MIME-type or file name using regular expressions.";
})
];
# upstream mimeo doesn't run preInstall/postInstall hooks, but we need that for the .desktop file
installPhase = ''
runHook preInstall
${upstream.installPhase}
runHook postInstall
'';
passthru = (upstream.passthru or {}) // {
inherit mimeo-open-desktop;
};
});
fs.".config/mimeo/associations.txt".symlink.text = lib.concatStringsSep "\n" (assocs' ++ fallbackAssocs');
mime.priority = 20;
mime.associations."x-scheme-handler/http" = "mimeo.desktop";
mime.associations."x-scheme-handler/https" = "mimeo.desktop";
};
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p mimeo
# TODO: migrate nixpkgs mimeo to be `buildPythonPackage` to make it importable here.
# see <doc/languages-frameworks/python.section.md>
import subprocess
import sys
desktop = sys.argv[1]
opener_args = sys.argv[2:]
desktop_fields=subprocess.check_output([
"mimeo",
"--desk2field",
"Exec",
desktop
]).decode('utf-8')
# print(f"fields: {desktop_fields!r}")
desktop_exec = '\n'.join(desktop_fields.split('\n')[1:])
# print(f"exec: {desktop_exec!r}")
# TODO: this is obviously not correct if any of the args included spaces
desktop_argv = [f.strip() for f in desktop_exec.split(' ') if f.strip()]
# print(f"desktop_argv: {desktop_argv!r}")
# fields explained: <https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s07.html>
# - %U = all URLs
# - %U = just the first URL
substituted_argv = []
for arg in desktop_argv:
if arg == '%U':
substituted_argv += opener_args
elif arg == '%u':
substituted_argv += opener_args[:1]
else:
substituted_argv += [arg]
# print(f"argv: {substituted_argv}")
print(subprocess.check_output(substituted_argv).decode())

View File

@@ -126,7 +126,7 @@ in
mime.associations."video/quicktime" = "mpv.desktop";
mime.associations."video/webm" = "mpv.desktop";
mime.associations."video/x-matroska" = "mpv.desktop";
mime.urlAssociations."^https?://(www.)?youtube.com/watch\?.*v=" = "mpv --player-operation-mode=pseudo-gui -- %U";
mime.urlAssociations."^https?://(www.)?youtube.com/watch\?.*v=" = "mpv.desktop";
};
}