Total rewrite #15
							
								
								
									
										77
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								README.md
									
									
									
									
									
								
							| @ -1,5 +1,3 @@ | |||||||
| # xdg-sanity |  | ||||||
| 
 |  | ||||||
| The `xdg-sanity` script is built to replace your default web browser in your | 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 | 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 | `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 | ## Installation | ||||||
| 
 | 
 | ||||||
| ### Arch | ### Arch Linux | ||||||
| 
 | 
 | ||||||
| I maintain a package [on the | I maintain a package [on the | ||||||
| AUR](https://aur.archlinux.org/packages/xdg-sanity). | AUR](https://aur.archlinux.org/packages/xdg-sanity). | ||||||
| 
 | 
 | ||||||
| ### From Source | ### From Source | ||||||
| 
 | 
 | ||||||
| First, make sure you have `curl(1)` and `handlr(1)` installed. Then, clone this | Dependencies: | ||||||
| repository and move the `xdg-sanity/` folder into `/etc` and `xdg-sanity.sh` to | - `curl(1)` | ||||||
| `xdg-sanity` wherever your operating system stores locally-installed binaries. | - `handlr(1)` | ||||||
| This is usually `/usr/local/bin`. Make sure the installation location is in your | - [`tomcat(1)`](https://git.tebibyte.media/emma/tomcat) (optional; enables | ||||||
| `$PATH`. | [extensions](#extensions)) | ||||||
| 
 | 
 | ||||||
| Create a `xdg-sanity.desktop` file either manually or with `gendesk(1)`, | Instructions: | ||||||
| placing it, also, where your OS stores locally-installed `.desktop` files, | Clone this repository and move the `xdg-sanity` binary wherever your operating | ||||||
| usually `/usr/local/applications`. Set your default web browser to that | system stores locally-installed binaries. This is usually `/usr/local/bin/` or | ||||||
| `.desktop` file. | `"$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 | Create an `xdg-sanity.desktop` file, placing it where your OS stores | ||||||
| script can forward links to it. | 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, | Extensions are written using TOML and are stored in either | ||||||
| you can call `xdg-sanity` directly with the only argument accepted being a URI. | `/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
									
								
							
							
						
						
									
										133
									
								
								xdg-sanity
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,133 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | # Copyright (c) 2022–2023 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 | ||||||
| @ -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 |  | ||||||
| @ -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 |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| # EXT-TYPE=replace |  | ||||||
| 
 |  | ||||||
| replace youtube.com or youtu.be with piped.mint.lgbt |  | ||||||
| @ -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 |  | ||||||
| @ -1 +0,0 @@ | |||||||
| browser =  |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user