Total rewrite #15

Merged
emma merged 14 commits from rewrite into main 2023-03-22 12:42:30 -06:00
8 changed files with 193 additions and 111 deletions

View File

View File

@ -1,5 +1,3 @@
# xdg-sanity
The `xdg-sanity` script is built to replace your default web browser in your
desktop/XDG settings. It intercepts http/s URIs sent to the default browser by
`xdg-open` and sends it to the appropriate application. For example, it will
@ -7,28 +5,73 @@ send `image/jpeg` MIME type files to your image viewer.
## Installation
### Arch
### Arch Linux
I maintain a package [on the
AUR](https://aur.archlinux.org/packages/xdg-sanity).
### From Source
First, make sure you have `curl(1)` and `handlr(1)` installed. Then, clone this
repository and move the `xdg-sanity/` folder into `/etc` and `xdg-sanity.sh` to
`xdg-sanity` wherever your operating system stores locally-installed binaries.
This is usually `/usr/local/bin`. Make sure the installation location is in your
`$PATH`.
Dependencies:
- `curl(1)`
- `handlr(1)`
- [`tomcat(1)`](https://git.tebibyte.media/emma/tomcat) (optional; enables
[extensions](#extensions))
Create a `xdg-sanity.desktop` file either manually or with `gendesk(1)`,
placing it, also, where your OS stores locally-installed `.desktop` files,
usually `/usr/local/applications`. Set your default web browser to that
`.desktop` file.
Instructions:
Clone this repository and move the `xdg-sanity` binary wherever your operating
system stores locally-installed binaries. This is usually `/usr/local/bin/` or
`"$HOME/.local/bin/"` for your user. Make sure the installation location is in
your `$PATH`.
Add your default web browser to `/etc/xdg-sanity/xdg-sanity.conf` so the
script can forward links to it.
Create an `xdg-sanity.desktop` file, placing it where your OS stores
locally-installed `.desktop` files, which is usually
`/usr/local/share/applications` or `$XDG_DATA_HOME/applications` for your user.
Set your default web browser to that `.desktop` file using `handlr set`.
### Usage
#### Extensions
Open links from applications outside your web browser as normal. Alternatively,
you can call `xdg-sanity` directly with the only argument accepted being a URI.
Extensions are written using TOML and are stored in either
`/usr/share/xdg-sanity` when installed from a package manager,
`/usr/local/share/xdg-sanity` when installed locally, or
`$XDG_DATA_HOME/xdg-sanity` for your user.
Extension support requires the installation of the `tomcat(1)` tool, which
parses TOML for the command line.
There are three kinds of extensions: MIME, replace, and scheme. MIME extensions
are parsed first and replace the MIME type of the content being fetched. Replace
extensions change the URI passed to the command to another. Scheme extensions
replace the protocol by which the URI hostname is being accessed.
The type of the extension depends on the file name. MIME extensions should have
a name ending in `.mime.toml`, replace extensions should have
`.replace.toml`, and scheme extensions should end with `.scheme.toml`.
Here's what a MIME extension looks like:
```
$ cat $XDG_DATA_HOME/xdg-sanity/youtube.mime.toml
[replace]
urls = [ "youtube.com", "youtu.be" ]
[with]
mime = "video/vnd.youtube.yt"
```
what a replace extension looks like:
```
$ cat $XDG_DATA_HOME/xdg-sanity/youtube.replace.toml
[replace]
urls = [ "youtube.com", "youtu.be" ]
[with]
url = "https://piped.mint.lgbt/"
```
and what a scheme extension looks like:
```
$ cat $XDG_DATA_HOME/xdg-sanity/spotify.scheme.toml
[replace]
urls = [ "spotify.com" ]
[with]
scheme = "spotify://"
```

133
xdg-sanity Executable file
View File

@ -0,0 +1,133 @@
#!/bin/sh
# Copyright (c) 20222023 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see https://www.gnu.org/licenses/.
set -e
argv0="$0"
get_urls() {
i="0"
until ! tomcat replace.urls["$i"] "$file" >/dev/null 2>&1
do
URLS="$(printf "%s\n%s" \
"$URLS" \
"$(tomcat replace.urls["$i"] "$file")"
)"
i="$(printf "%s+1\n" "$i" | bc)"
done
}
# check if usage is valid
if test -z "$1"; then
printf "Usage: %s [resource...]\n" "$argv0" 1>&2
exit 64 # sysexits(3) EX_USAGE
fi
for dep in \
curl \
handlr
do
if ! command -v "$dep" >/dev/null 2>&1; then
printf "%s: Missing dependency: %s(1)\n" "$argv0" "$dep" 1>&2
exit 69 # sysexits(3) EX_UNAVAILABLE
fi
done
# check if we have a BROWSER
if test -z "$BROWSER"; then
printf "%s: \$BROWSER not filled.\n" "$argv0" 1>&2
exit 71 # sysexits(3) EX_OSERR
fi
while test -n "$1"; do
URL="$1"
# use curl(1) to write out the request header's content_type, strip everything
# after the first semicolon, chop off any weird whitespace remnants
MIME="$(curl -Ls -o /dev/null -w '%{content_type}' "$1" | sed 's/\;.*//' \
| xargs echo)"
# get the URL with no scheme
NO_SCHEME="$(printf "%s\n" "$URL" | sed -n 's/^h.\+\/\///p')"
# get the pattern for the extensions to MATCH
MATCH="$(printf "%s\n" "$NO_SCHEME" | sed 's/\/.*\+//g')"
# get the non-domain of the URI for tacking onto the end of replaced URIs
URI="$(printf "%s\n" "$NO_SCHEME" | sed -n 's/^[^/]*\///p')"
# only check for extensions if tomcat(1) is installed
if command -v tomcat >/dev/null 2>&1; then
# run through MIME extensions
for file in \
"$XDG_DATA_HOME"/xdg-sanity/*.mime.toml \
/usr/share/xdg-sanity/*.mime.toml \
/usr/local/share/xdg-sanity/*.mime.toml
do
if test -e "$file"; then
get_urls
for url in $URLS; do
if [ "$MATCH" = "$url" ]; then
MIME="$(tomcat with.mime "$file")"
fi
done
fi
done
# then replace extensions
for file in \
"$XDG_DATA_HOME"/xdg-sanity/*.replace.toml \
/usr/share/xdg-sanity/*.replace.toml \
/usr/local/share/xdg-sanity/*.replace.toml
do
if test -e "$file"; then
get_urls
for url in $URLS; do
if [ "$MATCH" = "$url" ]; then
URL="$(tomcat with.url "$file")$URI"
fi
done
fi
done
# and the scheme extensions
for file in \
"$XDG_DATA_HOME"/xdg-sanity/*.scheme.toml \
/usr/share/xdg-sanity/*.scheme.toml \
/usr/local/share/xdg-sanity/*.scheme.toml
do
get_urls
for url in $URLS; do
if [ "$URL" = "$url" ]; then
URL="$(tomcat with.scheme "$file")$MATCH"
fi
done
done
fi
# these commands may fail; this is intentional
if [ "$MIME" = "text/html" ]; then
"$BROWSER" "$URL"
else
handlr launch "$MIME" -- "$URL"
fi
shift
done
exit 0

View File

@ -1,66 +0,0 @@
#!/bin/sh
INPUT=$(echo $1)
echo "Loading configuration..."
CONFIG=$(cat /etc/xdg-sanity/xdg-sanity.conf)
BROWSER=$(echo $CONFIG | sed -ne 's/^browser *= *//p')
if [ "$BROWSER" = "" ]
then
echo "Please place the path to your default browser's executable in /etc/xdg-sanity/xdg-sanity.conf"
exit
else
echo "Found default browser $BROWSER"
fi
echo "Loading extensions..."
for EXT in /etc/xdg-sanity/extensions/*.sh
do
if [ "$EXT" = "/etc/xdg-sanity/extensions/*.sh" ]
then
echo "No extensions to load"
else
for EXT in /etc/xdg-sanity/extensions/*.sh
do
TYPE=$(cat $EXT | sed -ne 's/^# EXT-TYPE=//p' | tr -d '\n')
echo "Found $TYPE extension $EXT"
if [ "$TYPE" = "replace" ]
then
echo "Modifying $INPUT..."
INPUT=$($EXT "$INPUT")
echo "Got $INPUT"
else
if [ "$TYPE" = "mime" ]
then
echo "Modifying MIME type..."
MIME=$($EXT "$INPUT")
echo "Got $MIME"
fi
fi
done
fi
done
if [ "$MIME" = "" ] || [ "$MIME" = "$1" ] || [ "$MIME" = "$INPUT" ]
then
echo "Determining MIME type of $INPUT:"
# Determines HTTP code, might use for something else?
# CODE=$(curl -fLIs "$INPUT" | sed -ne 's/ [[:space:]]*$//p' | sed -ne 's|^HTTP/.\+ ||p')
MIME=$(curl -fLIs "$INPUT" | sed -ne 's/^[cC]ontent-[tT]ype: //p' | sed -e 's/;.\+//p' | tail -n1 | tr -d '\r')
echo $MIME
fi
if [ "$MIME" = "text/html" ]
then
$BROWSER $INPUT
else
handlr launch "$MIME" -- "$INPUT"
fi

View File

@ -1,12 +0,0 @@
#!/bin/sh
# EXT-TYPE=mime
TEST=$(echo $1 | sed -ne 's/^h.\+\/\///p' | sed -e 's/\/.*\+//g')
if [ "$TEST" = "teddit.net" ]
then
echo "text/html"
else
echo $1
fi

View File

@ -1,3 +0,0 @@
# EXT-TYPE=replace
replace youtube.com or youtu.be with piped.mint.lgbt

View File

@ -1,12 +0,0 @@
#!/bin/sh
# EXT-TYPE=replace
TEST=$(echo $1 | sed -ne 's/^h.\+\/\///p' | sed -e 's/\/.*\+//g')
if [ "$TEST" = "youtube.com" ]
then
echo $1 | sed -ne 's/youtube.com/piped.mint.lgbt/p'
else
echo $1
fi

View File

@ -1 +0,0 @@
browser =