pax_global_header00006660000000000000000000000064146470022540014516gustar00rootroot0000000000000052 comment=edba2bc34b510d7aa8ce1b0af2c616c9cdfbd6fa ereandel-0.26.0/000077500000000000000000000000001464700225400133625ustar00rootroot00000000000000ereandel-0.26.0/.github/000077500000000000000000000000001464700225400147225ustar00rootroot00000000000000ereandel-0.26.0/.github/FUNDING.yml000066400000000000000000000000771464700225400165430ustar00rootroot00000000000000# These are supported funding model platforms github: blmayer ereandel-0.26.0/.github/workflows/000077500000000000000000000000001464700225400167575ustar00rootroot00000000000000ereandel-0.26.0/.github/workflows/shellcheck.yml000066400000000000000000000004511464700225400216070ustar00rootroot00000000000000on: push: branches: - main pull_request: branches: - main name: 'Trigger: Push action' jobs: shellcheck: name: Shellcheck runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run ShellCheck uses: ludeeus/action-shellcheck@master ereandel-0.26.0/CONTRIBUTING.md000066400000000000000000000013221464700225400156110ustar00rootroot00000000000000# How to contribute First of all, thanks for dedicating your time on this project, your contributions are very welcome. ## First steps Feel free to navigate on the code, run code analysis tools etc, to spot bugs or vulnerabilities. ## Issues You can check the issues to find something already mapped out, if you find a new issue you can add it, suggestions are welcome too! ## Submitting changes After finding an issue to work on, fork the repo, make the desired changes. Then use shellcheck to lint the code, please fix any warnings before submitting your changes. Now you can submit the PR. I'll review it and if I'm happy with it, the PR will be approved and merged. And that's it, you made a contribution. ereandel-0.26.0/LICENSE000066400000000000000000000020541464700225400143700ustar00rootroot00000000000000MIT License Copyright (c) 2021 Brian Mayer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ereandel-0.26.0/Makefile000066400000000000000000000010201464700225400150130ustar00rootroot00000000000000.PHONY: install uninstall PREFIX ?= ~/.local BINDIR?=$(PREFIX)/bin DOCDIR?=$(PREFIX)/share/doc/ereandel MANDIR?=$(PREFIX)/share/man/man1 LICENSEDIR?=$(PREFIX)/share/doc/ereandel install: mkdir -p $(BINDIR) $(DOCDIR) $(LICENSEDIR) $(MANDIR) install -m +rx ereandel -t $(BINDIR) install -m +r README.md CONTRIBUTING.md -t $(DOCDIR) install -m +r LICENSE -t $(LICENSEDIR) install -m +r ereandel.en.1 $(MANDIR)/ereandel.1 uninstall: rm $(BINDIR)/ereandel rm -rf $(DOCDIR) rm -rf $(LICENSEDIR) rm -f $(MANDIR)/ereandel.1 ereandel-0.26.0/README.md000066400000000000000000000061051464700225400146430ustar00rootroot00000000000000# ereandel ![print](https://github.com/blmayer/ereandel/blob/main/ereandel.png?raw=true) > A Gemini web browser using shell script ## Installing There is an AUR package for archlinux users: [![ereandel](https://img.shields.io/aur/version/ereandel?label=ereandel&logo=arch-linux)](https://aur.archlinux.org/packages/ereandel) [![ereandel-git](https://img.shields.io/aur/version/ereandel-git?label=ereandel-git&logo=arch-linux)](https://aur.archlinux.org/packages/ereandel-git) You can also move the file *ereandel* to a folder in your PATH variable, or run `make install`, by default it will be installed into *~/.local/bin*. Use *PREFIX* to override the install location, e.g. ## Using Start browsing by running ereandel with an optional URL: `ereandel gemini://rawtext.club:1965/~sloum/spacewalk.gmi` you can omit the protocol and port: `ereandel rawtext.club/~sloum/spacewalk.gmi` no arguments takes you to *gemini.circumlunar.space*: `ereandel` ### Client certificates ereandel can work with client certificates if capsules requires them for authentication. ereandel allows a single client certificate per (sub)domain identified by it's name. If a client cert for a specific domain is available ereandel will send it to the server with every request. When a resource requires a client cert and ereandel can't find one it will show you a command to create a client cert for the capsule. The certificates are stored in `~/.config/ereandel/certs/`. To remove a certificate simply delete the `.crt` and `.key` files in the directory mentioned above. ### Key bindings - `b` to go back one page - `u` go one path segment up - `o` to open a new URL, you'll be prompted to type it - `r` to reload the page - `H` to go to the home page - `g` to follow a link in the current page, a link will be displayed, and - `s` to save the page to a file - `m` to add the current page to bookmarks - `M` to go to a bookmark - `K` to delete the bookmark of the current page - `q` to quit More coming. ### Configuration You can setup a config file at `~/.config/ereandel/ereandel.conf` to configure *ereandel* the way you like. The file uses a simple `key=value` style, see the complete example for the default values below. **hints:** * `ereandel` will be appended to `cachehome`, the directory must be writable for your user. * The `style-` keys must be ANSI style codes. ``` margin=8 homepage="gemini.circumlunar.space/" sty_header1='\033[35;7;1m' sty_header2='\033[35;4;1m' sty_header3='\033[35;4m' sty_quote='\033[2;3m ' sty_linkb='\033[35m' sty_linkt=' => \033[36;3m ' sty_listb='\033[35;1m •' sty_listt='\033[0m' ``` ## Meta This software is a work in progress and may not work as it is intended to. ### Contributing Please read the [contributing file](CONTRIBUTING.md). ### Further works - Better history - Opening files - Support input ### Inspired by - [gmi](https://sr.ht/~chambln/gmi/) - [bollux](https://sr.ht/~acdw/bollux/) ### Packaging I'm not the maintainer of the AUR packages for this project, thanks [guzzisti](https://aur.archlinux.org/account/guzzisti) for the contribution. ereandel-0.26.0/ereandel000077500000000000000000000341301464700225400150700ustar00rootroot00000000000000#!/bin/sh version="0.26.0" usage() { echo "ereandel v$version: Browse the gemini web on the terminal." echo "" echo "Usage: ereandel [URL]|[OPTION]" echo "" echo "Options:" echo " -h, --help show this help" echo " -v, --version show version info" echo "" echo "Configuration:" echo "You can setup a config file at ~/.config/ereandel/ereandel.conf to configure *ereandel* the way you like." echo "" echo "Commands:" echo "These are the default keybindings to use while running ereandel:" echo "" echo " q quit" echo " g go to a link" echo " r reload current page" echo " b go back one page" echo " u jump one path segment up" echo " o open an address" echo " s save current page" echo " H go to homepage" echo " m add bookmark" echo " M go to a bookmark" echo " K remove bookmark for current url" echo "" echo "Examples:" echo " ereandel Start browsing the default webpage" echo " ereandel url Start browsing url" echo " ereandel --help Show help" echo "" echo "Report bugs to: bleemayer@gmail.com" echo "Home page: " echo "General help: " } version() { echo "ereandel $version" echo "" echo "Copyright (C) 2021-2023 Brian Mayer." echo "License MIT: MIT License " echo "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND," echo "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF" echo "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT." echo "" echo "Written by Brian Lee Mayer." } debug() { [ "$debug" ] && echo "DEBUG: $*" >&2 && sleep "$debug" } # Parse arguments debug "parsing args" while [ "$1" ] do case $1 in "-v") debug=1 ;; "-h" | "--help") usage exit 0 ;; "--version") version exit 0 ;; "-f"|"--file") shift file="$1" ;; "") break ;; *) url="$1" ;; esac shift done # Save terminal tput smcup # Configuration confighome=${XDG_CONFIG_HOME:-$HOME/.config} mkdir -p "$confighome/ereandel" configfile="$confighome/ereandel/ereandel.conf" bookmarkfile="$confighome/ereandel/bookmarks" certdir="$confighome/ereandel/certs" mkdir -p "$certdir" cachedir="${XDG_CACHE_HOME:-$HOME/.cache}/ereandel" # Default values # user config margin=8 homepage="geminiprotocol.net/" # keybindings openkey='o' openlocalkey='O' gokey='g' refreshkey='r' backkey='b' quitkey='q' markkey='b' gomarkkey='M' delmarkkey='K' goupkey='u' homekey='H' # styles sty_header1='\033[35;7;1m' sty_header2='\033[35;4;1m' sty_header3='\033[35;4m' sty_quote='\033[2;3m ' sty_linkb='\033[35m' sty_linkt=' => \033[36;3m ' sty_listb='\033[35;1m •' sty_listt='\033[0m ' if [ ! -s "$configfile" ] then # Default values cat <<- EOF > "$configfile" # where to store temp files cachedir="$cachedir" # user config margin=8 homepage="gemini.circumlunar.space/" # keybindings openkey='o' openlocalkey='O' gokey='g' refreshkey='r' backkey='b' quitkey='q' markkey='b' gomarkkey='M' delmarkkey='K' goupkey='u' homekey='H' # styles sty_header1='\033[35;7;1m' sty_header2='\033[35;4;1m' sty_header3='\033[35;4m' sty_quote='\033[2;3m ' sty_linkb='\033[35m' sty_linkt=' => \033[36;3m ' sty_listb='\033[35;1m •' sty_listt='\033[0m ' EOF fi # shellcheck source=/dev/null . "$configfile" mkdir -p "$cachedir" pagefile="$(mktemp -p "$cachedir" -t curpage.XXXXXX)" histfile="$(mktemp -p "$cachedir" -t history.XXXXXX)" linksfile="$(mktemp -p "$cachedir" -t links.XXXXXX)" tracefile="$(mktemp -p "$cachedir" -t trace.XXXXXX)" debug "read configs" # Restore terminal trap 'rm -f $histfile $linksfile $pagefile $tracefile > /dev/null 2>&1 && tput rmcup && printf "\033[?25h" && stty echo && exit' EXIT INT HUP stop() { [ "$trace" ] || return if [ -z "$stopwatch" ] then stopwatch=$(date +%s.%N) else dur=$(echo "$(date +%s.%N) - $stopwatch" | bc) printf "%s took %s seconds\n" "$1" "$dur" >> "$tracefile" unset stopwatch fi } getprevious() { sed -i '$d' "$histfile" prev="$(tail -n 1 "$histfile")" sed -i '$d' "$histfile" echo "$prev" } # Returns the complete url scheme with gemini defaults # Parameters: url parseurl() { # Credits: https://stackoverflow.com/a/6174447/7618649 debug "parsing: $url oldhost: $oldhost oldpath: $oldpath" proto="$(echo "$url" | grep :// | sed -e 's,^\(.*://\).*,\1,g')" if [ "$proto" ] then url="$(echo "$url" | sed -e "s@$proto@@g")" else if [ "$oldhost" ] then case "$url" in "/"*) url="$oldhost$url" ;; *) oldpath="/${oldpath#/*}"; url="$oldhost${oldpath%/*}/$url" ;; esac fi fi debug "url: $url" proto="$(echo "$proto" | sed -e 's,:\?//,,g')" user="$(echo "$url" | grep @ | cut -d@ -f1)" hostport="$(echo "$url" | sed -e "s/$user@//g" | cut -d/ -f1)" host="$(echo "$hostport" | sed -e 's,:.*,,g')" port="$(echo "$hostport" | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')" path="$(echo "${url#/*}" | sed "s@/\?$hostport@@")" debug "parsed: proto: ${proto:-gemini} host: $host port: ${port:-1965} path: ${path#/*}" echo "${proto:-gemini}" "$host" "${port:-1965}" "${path#/*}" "$rest" } typesetgmi() { # some setup first [ -f "$linksfile" ] && rm "$linksfile" cols=$(tput cols) linkcount="0" # shellcheck disable=SC2154 width=$((cols - (2*margin))) debug "text width: $width" stop while IFS='' read -r line || [ -n "$line" ]; do # shellcheck disable=SC2059 line="$(printf "$line\n" | tr -d '\r')" printf "$line\n" | grep -q "^\`\`\`" && pre=$((1 - pre)) && line="" # add margins and fold if [ "$pre" = 1 ] then printf '%*s%s\n' "$margin" "" "$line" continue fi # shellcheck disable=SC2154 case "$line" in "### "*) sty="$sty_header3" && line="${line#'### '}" ;; "## "*) sty="$sty_header2" && line="${line#'## '}" ;; "# "*) sty="$sty_header1" && line="${line#'# '}" ;; "> "*) sty="$sty_quote" && line="${line#> }" ;; "=>"*) link="$(echo "${line#'=>'}" | tr -s '\t' ' ')" echo "${link#' '}" >> "$linksfile" linkcount=$((linkcount+1)) line="$(echo "$link" | cut -d' ' -f2-)" [ -z "$line" ] && line="$link" sty="$sty_linkb${linkcount}$sty_linkt" ;; '* '*) sty="$sty_listb$sty_listt" && line="${line#* }";; *) sty='' ;; esac # shellcheck disable=SC2059 printf -- "$line\n" | fold -w "$width" -s | while IFS='' read -r txt do printf "%*s" "$margin" "" # shellcheck disable=SC2059 printf -- "$sty$txt\n\033[m" done done stop "typeset" } # some help: # \033[;H move to top # \033[NH move to bottom N lines # \033[?25l hide cursor # \033[?25h unhide cursor # \033[2K erase line pager() { clear # hide cursor printf '\033[?25l' # lines columns lines="$(tput lines)" head -n "$((lines-1))" "$1" l="$(wc -l < "$1")" if [ "$lines" -lt "$l" ]; then pos="$lines"; else pos="$l"; fi # stop echoing user input and read input unbufered stty -echo -icanon min 1 time 0 # read inputs while k="$(dd bs=1 count=1 status=none | od -c -An | tr -d ' ')" do case "$k" in # command sequences "033") b="$(dd bs=2 count=1 status=none)" case "$b" in # up arrow '[A') [ "$pos" -le "$lines" ] && continue line="$(sed "$((pos-lines))q;d" "$1")" pos="$((pos-1))" printf '\033[H\033[L%s\033[%sH\033[2K' "$line" "$lines" ;; # down arrow '[B') [ "$pos" -ge "$l" ] && continue printf '\033[%sH' "$lines" sed "${pos}q;d" "$1" pos="$((pos+1))" ;; # page up '[5') # discard one extra byte dd bs=1 count=1 status=none > /dev/null [ "$pos" -le "$lines" ] && continue scroll="$((pos-lines))" [ "$scroll" -gt "$lines" ] && scroll="$((lines-1))" # shellcheck disable=SC2086 for i in $(seq 1 "$scroll") do line="$(sed "$((pos-lines))q;d" "$1")" pos="$((pos-1))" printf '\033[H\033[L%s\033[%sH\033[2K' "$line" "$lines" done ;; # page down '[6') # discard one extra byte dd bs=1 count=1 status=none > /dev/null [ "$pos" -ge "$l" ] && continue scroll="$((lines-1))" end="$((pos+scroll))" [ "$end" -ge "$l" ] && scroll="$((l-pos))" # shellcheck disable=SC2086 for i in $(seq 1 "$scroll") do printf '\033[%sH' "$lines" sed "${pos}q;d" "$1" pos="$((pos+1))" done ;; esac ;; "$quitkey") exit 0 ;; "$openkey") printf '\033[%sH\033[?25h\033[2KType url: ' "$lines" stty echo icanon read -r url <&1 # add gemini:// to begining if not (for convenience) case "$url" in "gemini://"*) ;; *) url="gemini://$url" ;; esac return ;; "$openlocalkey") # Open local gmi file printf '\033[?25h\033[2KType file path: ' stty echo read -r file <&1 typesetgmi < "$file" > "$pagefile" pager "$pagefile" return ;; "$refreshkey") return ;; "$gokey") printf '\033[?25h\033[2KEnter link number: ' stty echo icanon read -r i <&1 debug "selected $i" url="$(sed "${i}q;d" "$linksfile" | cut -f1 | cut -d' ' -f1)" return ;; "$backkey") read -r proto host port path <<- EOF $(getprevious) EOF url="$proto://$host:$port/$path" return ;; "$homekey") url="$homepage"; return ;; "$markkey") printf '\033[?25h\033[KEnter description: (optional)' stty echo icanon read -r desc <&1 echo "$url $desc" >> "$bookmarkfile" return ;; "$gomarkkey") clear cat -n "$bookmarkfile" printf "\033[?25h\033[KEnter link number: " stty echo icanon read -r i <&1 url="$(sed "${i}q;d" "$bookmarkfile" | cut -d' ' -f1)" return ;; "$delmarkkey") grep -iv "^$url " "$bookmarkfile" > "$cachedir/bookmarks" mv "$cachedir/bookmarks" "$bookmarkfile" return ;; "$goupkey") newpath=$(echo "$url" | rev | cut -d'/' -f2- | rev) url="${url%/*}/$newpath" return ;; esac done } # borrowed from https://gist.github.com/cdown/1163649 urlencode() { stop old_lang=$LANG LANG=C old_lc_collate=$LC_COLLATE LC_COLLATE=C length="${#1}" i=1 while [ "$i" -le "$length" ] do c=$(printf '%s' "$1" | cut -c $i) case $c in [a-zA-Z0-9.~_-]) printf '%s' "$c" ;; *) printf '%%%02X' "'$c" ;; esac i=$((i+1)) done LC_COLLATE=$old_lc_collate LANG=$old_lang stop "urlencode" } # Fetches the gemini response from server # Parameters: proto, host, port and path # Spec draft is here: https://gemini.circumlunar.space/docs/specification.html fetch() { if [ ! "$1" = "gemini" ] then echo "Only gemini links are supported." echo "Type a key to continue." read -r i <&1 read -r proto host port path <<- EOF $(getprevious) EOF url="$proto://$host:$port/$path" url="${url:-$homepage}" debug "previous page: $url" return fi debug "requesting $1://$2:$3/$4$5" # set title printf '\033]2;%s\007' "ereandel (c): $2/$4" echo "$1 $2 $3 $4 $5" >> "$histfile" certfile="" if [ -f "$certdir/$2.crt" ] && [ -f "$certdir/$2.key" ] then certfile="-cert \"$certdir/$2.crt\" -key \"$certdir/$2.key\"" debug "using client cert for domain: $certfile" fi port=$( [ "$3" = "1965" ] || ":$3" ) url="$1://$2$port/$4$5" [ "$trace" ] && echo "url: $url" >> "$tracefile" stop echo "$url" | eval openssl s_client \ -connect "$2:$3" "$certfile" -crlf -quiet \ -ign_eof 2> /dev/null > "$pagefile" stop "openssl fetch" stop printf '\033]2;%s\007' "ereandel (r): $2/$4" # First line is status and meta information read -r status meta < "$pagefile" status="$(echo "$status" | tr -d '\r\n')" meta="$(echo "$meta" | tr -d '\r\n')" sed -i '1d' "$pagefile" stop "status extract" debug "response status - meta: $status - $meta" # Validate case "$status" in 10) echo "Input needed: $meta" >&2 echo "Please provide the input:" >&2 read -r input <&1 url="$1://$2:$3/$4?$(urlencode "$input")" return 0 ;; 11) echo "Sensitive input needed: $meta" >&2 read -r input <&1 url="$1://$2:$3/$4?$(urlencode "$input")" return 0 ;; 30|31) # Redirect debug "redirecting to: $meta" # shellcheck disable=SC2046 read -r proto host port path <<- EOF $(oldhost="$2" oldpath="$4" url="$meta" parseurl) EOF url="$proto://$host:$port/$path" return 0 ;; 40) echo "Temporary failure" >&2 echo "Type a key to continue. " read -r i <&1 return 3 ;; 41) return 4 ;; 42) return 5 ;; 43) return 6 ;; 44) return 7 ;; 50|51) echo "Page not found!" >&2 echo "Type a key to return to previous page." read -r i <&1 read -r proto host port path <<- EOF $(getprevious) EOF url="$proto://$host:$port/$path" debug "previous page: $url" return 0 ;; 52) return 10 ;; 53) return 11 ;; 59) echo "Bad request: $meta" >&2 echo "Type a key to continue." read -r i <&1 return 12 ;; 60) printf "client certificate required, to create a client cert use the following command:\n\n" printf "\topenssl req -x509 -newkey rsa:4096 -keyout %s/%s.key -out %s/%s.crt -days 36500 -nodes\n\n" "$certdir" "$2" "$certdir" "$2" printf "press 'return' to reload the page or 'b' to go back to the previous page:\n" read -r in <&1 if [ "$in" = "b" ] then read -r proto host port path <<- EOF $(getprevious) EOF url="$proto://$host:$port/$path" else url="$1://$2:$3/$4?$5" fi return 0 ;; 61) return 14 ;; 62) return 15 ;; esac # Success oldhost="$2" oldpath="$4" # Set charset charset="$(echo "$meta" | grep -i "charset=" | sed -e 's/.*charset=\([^;]\+\).*/\1/Ig')" case "$charset" in "iso-8859-1" | "ISO-8859-1") charset="iso8859" ;; "utf-8" | "UTF-8" | "") charset="utf8" ;; "us-ascii" | "US-ASCII") charset="ascii" ;; esac debug "charset: $charset" printf '\033]2;%s\007' "ereandel (t): $2/$4" case $meta in "text/gemini"* | "") typesetgmi < "$pagefile" > "$pagefile.gmi"; mv "$pagefile.gmi" "$pagefile" ;; *) ;; esac debug "starting pager" printf '\033]2;%s\007' "ereandel (l): $2/$4" pager "$pagefile" debug "new url: $url" } # files are handled differently if [ "$file" ] && [ -f "$file" ] then typesetgmi < "$file" > "$pagefile" pager "$pagefile" fi # first request url="${url:-$homepage}" while : do printf '\033]2;%s\007' "ereandel (w)" # shellcheck disable=SC2046 fetch $(parseurl) done ereandel-0.26.0/ereandel.en.1000066400000000000000000000061721464700225400156320ustar00rootroot00000000000000.TH EREANDEL "1" "November 2023" "ereandel 0.26.0" "User Commands" .SH NAME ereandel \- A Gemini web browser using shell script .SH SYNOPSIS .B ereandel [\fI\,URL\/\fR]\fI\,|\/\fR[\fI\,OPTION\/\fR] .SH DESCRIPTION ereandel v0.26.0: Browse the gemini web on any POSIX compatible terminal. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR show this help .TP \fB\-v\fR, \fB\-\-version\fR show version info .SH COMMANDS These are the default keybindings to use while running ereandel: .TP \fBq quit .TP \fBg go to a link .TP \fBr reload current page .TP \fBb go back one page .TP \fBu jump one path segment up .TP \fBo open an address .TP \fBs save current page .TP \fBH go to homepage .TP \fBm add bookmark .TP \fBM go to a bookmark .TP \fBK remove bookmark for current url .SH ENVIRONMENT Ereandel uses 2 environment variables to help debugging and tracing its execution. .TP \fIdebug To start ereandel in debug mode .TP \fItrace To start ereandel with tracing activated .SH NOTES .SS Client certificates .PP \fBereandel\fR can work with client certificates if capsules requires them for authentication. \fBereandel\fR allows a single client certificate per (sub)domain identified by it's name. If a client cert for a specific domain is available ereandel will send it to the server with every request. When a resource requires a client cert and ereandel can't find one it will show you a command to create a client cert for the capsule. The certificates are stored in \fI$XDG_CONFIG_DIR/ereandel/certs/\fR. .PP To remove a certificate simply delete the \fI.crt\fR and \fI.key\fR files in the directory mentioned above. .SH CONFIGURATION You can setup a config file at \fI$XDG_CONFIG_DIR/ereandel/ereandel.conf\fR to configure \fBereandel\fR the way you like. The file uses a simple \fBkey=value\fR style, see the complete example for the default values below. .PP .EX margin=8 homepage="gemini.circumlunar.space/" sty_header1='\e033[35;7;1m' sty_header2='\e033[35;4;1m' sty_header3='\e033[35;4m' sty_quote='\e033[2;3m ' sty_linkb='\e033[35m' sty_linkt=' => \e033[36;3m ' sty_listb='\e033[35;1m •' sty_listt='\e033[0m' openkey='o' openlocalkey='O' gokey='g' refreshkey='r' backkey='b' quitkey='q' markkey='b' gomarkkey='M' delmarkkey='K' goupkey='u' homekey='H' .EE .SH EXAMPLES .TP ereandel Start browsing the default webpage .TP ereandel url Start browsing url .TP ereandel \-\-help Show help .SH AUTHOR Written by Brian Lee Mayer. .SH "REPORTING BUGS" Report bugs to: bleemayer@gmail.com .br Home page: .br General help: .SH COPYRIGHT Copyright \(co 2021\-2023 Brian Mayer. License MIT: MIT License THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. .SH "SEE ALSO" The full documentation for .B ereandel is maintained as a Texinfo manual. If the .B info and .B ereandel programs are properly installed at your site, the command .IP .B info ereandel .PP should give you access to the complete manual. ereandel-0.26.0/ereandel.png000066400000000000000000001431671464700225400156630ustar00rootroot00000000000000PNG  IHDRڐsBITO IDATx^xƿ4H% ={^RHґ" AzQK'$@ I.ow̙3]33s D IV(O\Ӧnֵ[(S7]lĆcb_ޅr ;}̭[/_&gM:7ep`gc; ~~[l]|]DD=Orշ|ѓP=ko[ E6i1hYk3f~9t}epv]mE]]ܾ[8IO͖[9> ]w*ۡRn5Ӹq+KΞw͙%'f{I;Sf8ɒm܏tN+]ߍ7N( %r\c5̕ٿZv:bb#sL>=9p>yheqMN0-1}ДW,'.B֋2{PE$@$`- /iwCfq?Y @C1w}ުLap?9x!;{O\<5 GgN70_O '_s`/fEzdtșcp^xGCokQ K!cbݮ 3Y X[`v*%^hnXCJ*bfbϩ/UѴWG  E898fkTCܿK7/,򹵵{7cRAsqraK=Zre/ڦ(D<5|.tkw4\rJ[n^,޲ W\. P ᏑdokQs\c&czapaW1_D-vG;pǏꔫS^J$@$`,jpPb]-x\pVzgOqνvurAgM;w0l.1/p_'VV:#im.Ä^FĈ2 Չ-ѱ(nkcQtԴ$ HEX nlQßn[9~c,Dm+y݂bP9C/ܸt WY7_-vS(4Hի鄉$@$@$,,jp#珙+g0aиjGOCU}prv@ެk1m'Ϟb 84^ZG%q"B9 8x"E@͟/b@;[;ow/lYNuNU|䲗a: % 3NCdaBNدGG;lخ 7.Ν[ v~F}B=}fcZ/b,S-O%V,شzeN.cb.z4*3F:E$@$@N``/p.-l iNU6%#OEѤPh $ zU¹ 0)c&ᛜ                                                                   .%*}+uf˰^ͻU/UVoi&GEG %g2 ;'0}ДnM;;:]o9w~Lt/4#  L:5gzl93gɼdQIh¥QAz?޴Kߖ=ޙ&fְi?X8WAŦMݖmnYْ1saGF}?굆/aQW3;[XroLe$ H,dp'KphFddkkk*+}lܾ߾wC?hgc+?V h:UHX򄎟%VĥSFX{~^~tsqØK!A_Ŀ0*ˏ$@$@$,dp`ozdK9.#O^>]x%\S$2&pBC;p}5B,2my1q/_9{ _?Oy_ͬP\wCɜ0HHRMԚb4स΃Aǝ4T+YU6ps`me=g acokh QPTLQ~d Pb zp{|BBCߕ9a:  )SDd8b 3У޲')"1iXl\lq=ĀX67侷W%ux!xy @e|V?Ar5ї Ч ^{DbXo+_?]Կ~dEd=[&ϙC  9NIec4~D ]'L= )OZ3мfS$ݹ^̨s'~`boQErҸV.oZM11/žST+U[ujd 0SI0~Ӕ @*#={;vDFF޺usoӧ۵kgmoz$)kiŋϟl~gAAAM4y>̝;̃Wߏ?IH :thnnn%K|A2eޤ"ExyymۛIZɓIXYYI3\RIz_oup`@}wB$ ̙3>>WT\D 2y޽'NZH޽+=:{ӧ߼yTR"oXTTAXXXnݶo~ʕ(- *ͅ Ο?ߦMYq%|l]v-Z4Q{Y|J*N-vE/^01SQ셁No߾xJ+S˗/ի'ct H~appǏ YK tppu׮]vϞ=#G7ΰc7ed˖ RDmڵkE%K$2UVp8dȐ[W\Y|.]کS'% >0jI 91́f<0ƀ 2 @p>22?ze~Ix KxթS0@Cn#G0EY Sk{QΝ;7]t snoooHF}5D?wޭVg^ @h֬իW)S&/j5qq=tk>c ð ⏵RDmH9sVZU`AJ.E*TDKi/3j(rʅūu%Z ҬWRwx`_xxQu^ʕ6l(5ɚ5+)S,oܸ\]>sϟ?W[,Y[[Ï^E{˖-+Z9ʼn~t3H 5Л(N  ayfR z3/,ޅGGGe'ɑMQ_ӧOÕ?EL߿_eL0 Ch)Õ:~K.}fΜYN,\xQ',u2{Y<DzcDDڿuDS=z$lPxd`^!444..NأD$:e~~~uc&>~X\uҿh(?8EqhD $`!sqq~&:~`5f?)R5^)W eՌya&ܹsիWdR?][40ffٳGUΕۚh]~-nd <==6x0H:Flb|s2{Y0'Dfon47ړ 6 sW5kL<ѫa3h4coz8|[ײe\]]Sg{7nX@Ć}OBτu9igcS']^SR79ņ hJ%kE],B.v¢6c nl0twݫث#>wb3#l+U`0&EVr_Y1f% d ;Vj1y0qDm x G7s5~ԊQ;?G5Gt/C7ŵft5jq  GWy)%6cE;-Z_D3~t0a.:tyNd3m\=e`Çmի,RذaymCPɗ/}ѣlHjР^{4ĮYDjԹ85m[\  NfS{H,+$+:#P6I.$@$=l& O~id,>̝;wXѶkDcs/^?~R]憪O+q#g 8 Pxq++ "gOmfn&PBz {XFc  P@D;=C.\p6mh7~0 ۷7oݻw_|ĉUVU˗/k׮!hѢ"W^SlN:{locǎիWϰZѣG3f(O9'SX1fkK3~ ֭ۯ\2`jTTr%2d'L0ngΜAJ94h={gϞƙ\|T3HH M(؈NCjazQQQF3k׮Okɒ%\bZ{ܹҥ+\pddq]t@>UVFuVHdɂp~rʆX~Ѳ?41@>Q \VlfpSLElAia+ 1jݺ5Rc#fS>3c(?}||}z^B+lذaXNWn48;99y('%KZn+#͊0 p!JAR, RãG5ݕtufӘH$@i"/ݾY;v$tZxOr0_\obo>aٳϛ7oΝ^67nGX4i%k0_<ɹ:;F@`쌉Q<882 *2 Ь7hD Hދ +vn1ݤ?uft`Q߆/A?`mxٲeF p۱cGO,CYf!xMdKr1† 9sfH׉_Q.߿/v%&&FܹsA1Z޽{bvbuQNE" (ذS #[F 5j~]^vh)ORs̉YÿqㆲKK.gl :v.ZH_j@<:tPR >!Ǐqߋ\M—>h؆`oXW5ۥN`vʕKk `ARj 6lC޾}{q"7贂Y$@$@$@ofh= 0P2 EXV0SqM0c2uB   TJZ]Rp"Qc @H.UF%s|#4]MQg\S5Q]WS4ē䊌 TjD HAܐh ?TqrlaMISS45ɪ&Kcf~Nz $@$`880&AQӵLMQF'*2Rœ\+k&|(^nr :~{C-IHQepޑ沂ZMQSN0.,,[UQuPӿ,ReKV)Nԩp<%xva)z,Xc"q>& 54`" @ R!sR ;yUuIUFYdW5jQIxlgݺuʁ8AH$@DRPEF(<eߍf<ɢ(kN{5]au?z̙3! /Rd0)ML$ K"`T({tdj2{Y~ZQا~UFYdU|rl\\\ vZlܳg(ЗRΙB$@Cؐ|{ 5 Ui>,KQ7^s &(LfȐ ^ZR%1sM6,O}}}1Ņc)x! `;6xԪbLQ`cҡj֞={yaܹsիW0c#r bxUW}jn= -ņDU!>tfx=zhZL9/M|J… ;v=^.ݻW)kz:t:*ڵCA;AЉQdg~I ѯWƒ|_'SHH,:iӦmB:jFf'S̗/ꏞZj5U՞EJz>Ε"aÆ 5BаQtTnݺ&`DV:Bi_48kG2n8N$@$@K(V,yl { o>s=:# %[HHHHHHHHHHH-S$i釣_s .Àq4!=ҥ˛;|{RkN<'JZER7W)$@$`*;;;XjUwqARš*;4M&v3gΜ3grn^6i)'i&<}PEL38HroMB3  -h4ۋ<;;;k?P=9W (jB-뉣}^ۧ:urLPBz ϟFI0Fxc. ELQfE8`Ŋ8 aO>IS߽{Q?5䣄gM>:5'б׌2IM>'NR b%_fgsQIS?.]|!C_!틇.HdB|~t7,H LWe,N N1ŸE j :H.P[LpڵBkɒ%lѣa(%Swԏڵ+w"N9rqㄍLQX,&K#F|tkteO6&e|.]کS'Z Fi³~SR?WxdJB•Z lݺ5r!؍#q̔7M5Kʼnt(~s,x XW8 E}ѪW6^Y*;8*Ó&M_CVe9~ׇ3~dHFZu͚5߿PYp^olʠoM6ƈeUc8a_/*͊Ϟ= L rʭYט1<=iݺuW^xGN8Q./+h=8<ރ˔)@- ^V {e.Ov4FbtL̈>3Z3 .hIԡrNcxX,UF{tƣF*P97og\>@73B-\P8WT 'O<'Y -[ pB?*\uGs*D` 3*#yƸ~SESLiѢ!yFeeE̵ڤxuj3q`*:NA~S]x485]A B ZPaVt(;45iI2c:Ĉ7lr,վ7b3M4)^YJ!X|W[Bs͊_)2UFda7mڄhzH4 e%Q{ڤȡ̉ ӀeϞ=s}@|UP}4t.SD_qFX;SnzC"J5Ղ%I{ioGRcO"ܽ{7v3\reѢEH<<^caаaC\8 ܹs_ bg 4&e|nܸ1ax*ʷWd,"HJ]f)@\>}0R95h/Sщ\n8N$@$@'GI7f/& ex/,VE`wȴi.L!`c)k#[D$@$@!`8=N4jjo˴ؐkxڒ)$@$@$@$@$@$@$@$@$@$@8Qr{},ؽmޟ\%~{sUej~t5M']^c,T>D' 1T˥ ,'ҀcQF)jf X Rz!vSbFM~gSw@޷gK{o@jMĻ|ȑWƤ;:}T{ڛRY/ =_KE;wėe0)Ula][{S3%                                                                xuo>{5-gO읷q˗/NmJ$@$@$ `piZN#(B[k$ H=lRO(Iphșd,fԷewW査vAgy^N^X'tӢGL\̂MK_<)җ]0/1sO!mieeIU>tvt]_O-g͘%&6f{NOZ<Ʌ~HHH"`8s`ԬJ ? AzΓ51sllE?(Y׮N~!^{IuFzLW~YcpZ*۲'<2y0߄5a># "M$@$@Ejf:tQwo}`zεGs8p5Br7ݼ|wҟt Y|ut'>޼N݂?sKmy1v.%3G{[{緭n#qeNŅKg_Ŀ6O#A==> 64pu,>>^$FDF sѯ$@$@$6X^=;s >= n.z9g˗=Ϙn#18, `A\]Þ>_Ogm-ۧ71tZ<}?{͍mr$  }{;}pf5`aqfW{\_uXV,H`"*: q;Awj\Yrf=wh'69-TddVmw;"8% 3HHK9kn`AL]-ؼfS\ݹyTПCH.&X4TO\cߖUoIm+6 }{cvAxJ=ZS$xka. ]rhN@zR{RfVK$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$Ȓ` n?2hJyfXz;1鵼c槳5R$1^Z X>>YgkV;=2ej"j36U\m:]b=;b_2);p驪o>WMK  l 6۵c/_L-&Yaicg)wΈRv)U1 HY5~䋸8cpj2 \:Mg( 8.+P{' w>eRf/)k,Q  X>2K_Z͔f?˰_NWutc6ZYŏ?\llzXsH?~Irlac=3g?oEk8a=kƢ镚4a:GgHG<5&\c\K贫A­a[dxx)"WG^x 5 :)-p/ܸdU/ KYzgst pcƵK>ha#x??w\<<a ̳w /_bB0Wr&f~)>>b2kx$lDkt__ o_u<֯µ]2(+o_|7$5Aʱ_x8>.V& 4_G_c ? Ahk4utpY >Cbc\K+̇?y {]2;Y1\G{.Л PRkW S`yi#f sk8;:w+ Ly DF=sSXek"~xH|BVЍDdq@vOJH:5òӇb" I^W?HHH 0]?ö۹~_k]h՛DDaKD[Y\F{eq ݼ}]4{#|]Ii| ^] g)0y˰{H4EU|tApqK3xe }(mK z=0Θ?upsp`MrnXIÄ́^Y߼u{𔏱Q@occ^6ZW~.9 H̒ êl__>Kؘ xds @@u' QeZy[lTi/r{˗G0J#km9"WZ>vHt6F?}f- uId% k\=}#уQƸ97aGa7Μjt61- =FqLMޠG#q!sQqL%0   5 fbahNbl歳~:f$"PWOUaFll Pnˇzz;DAb9h)$@$@ 7UF<=8$+V^#@R(6 Yji b 6*dF+~4u\W8a hlYRUe M[~4 .}%qwe*EW"?*XVZȩbjAGM.98j>L$ H%,dp i,- 2BfaH#V*XVK?`@zgc[֋R:jpbk3 ~1HHHHHHHHHHHHHHHHHHHHHH,@ES4 _J)R VLYHH}$U2 v4+.U.e!` IDAT6f*nd0 5Lwb -K1$,E$@A9xsUvm8r Jqv~8"Th2[bP>̔;A=Âj(# NɌCubv/g9֌7hb-6vvq11VDJ$5D#mNs~~%G'&0HHr$*#t>>^8G{)}LQGPӏ, >Cbc\K=y cڡ~Z\(XZе+ap~߆)ejDMG<+v.{^?Ȃg: ! $*#^ܾ3U[w,^Ó;6 ۇ5Fb\(S5=UNExh_ I2C_\׮@ ц?z1RR^'5U"eq^SW/gKxQchƣ?HH28-+3-Dײk ć*rψŌLQj(#{"1?agPVs{/^/s+YEa‹]j՝ٵ]q_ȭJ~e*_x0DyDdRG$)S!",̮9X43J1^T},T:NNg@^D H.UƴB.!X)Ɇ_.rEm/S~Dxd@=)׫ؠS  5 9,l*cZQAQ_!=UTS`Z,> 8Y(zuTN. HBDUƴTSQ3;;[{(QUE:s{TcTk8b2eNV4L1^E)N֯$@$@&Ar2Dbeu/@M lT3ηctCco!Pإw|tڛ:zQPu;wΙB$@$428-+ʘVT^|q <3eܼmLeF@gHm/Sqvvwup?ypP(MWGe11&A]/T~% H d4W1 /=zx|ƙޮm1ïf6(Iqq2{㝋g^0xƻ߻tGvG MWGecw㰍'ۛ "ba-RQ@ HHLfӜ4`Cۯ'"#cv%iy($  TI*UFŠOcxz?yƔ맏0\          H*ʘj2 k\7' K&>2ڡ0W\{z\~d풥I>ˏ,N @r Xvm8r˗/o󰴱~/R^c"e82uDU mm.߂c|bb7h0JaM_b0vgֲUS⁁fdꋊ bg( ~ gO-elTv܎#3zwhg_<G,; 2?e|tec4p ԒQuګ2իG_=DnxN$@$`*M\*5kithb av?υt66]\f}G\sU5i8'׌E?j) fӟ~Dbem5 NB Ve~dy4zIf rBdq,O=t_!hdqϜj?haϭsxf"k m;ڻclt4^ V;q!D}sݿj5WxW#52H mA-M?7~xQLs#&zeꕱɢzeq(UATg[ &2¡[F_e&cXBPASGu:~CY$@i 7UFHK? {$2Lgr ݼ}]4{R tgwOlkxx疰1WQ>WЇ!K&'{Q<"N#NE RӏzuP=R&H  Ȗ,U1Aw1K6gw Ui޿hɅÿP9CaP,Cݹx6e =˷kg5?ve^?~һd$c7"uE Rӏze~CY$@i d-U,rWK޻rQYK5*1{ùzI~sU5#|ʗ/\=a<%'WPM?y uIHa)M?SR4zIf +]'aU_QcyHִA"UR  l,D`/wwEs\\ҥKw:++/_IN }&XHHސ yyEn >>)3m=*:j]P+T^:wzp>ʕ.Zyyo>mmiee۸ʇΎ.ݿWY2fӢGL\̂MK_&6֨lX?HgN\]Þ>6IiWODFGԫ? ٰe3g_WY$@$@$( YVx$[0Ipj~x'Na+KL^箟Wi$"|N(ARGu(~;nTt46Eb. HBf01<;W/)W c`W[\nmm 郧`>熛0s 조gOcՠo^ͪ7n$Q/M5$&-X8qaboɌ" wicoZY9|cm_cUPxK$@$@$MLu&%s#HH;ˀo0ZFCް 4{C,N$@$@$`*yܲӎHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH%%_~dВ?r(h_SF=ӝect;Oћe,,؉Yт9i$@$dɒ?{^Ȕ TNJO/hVq1NtYn>.=2}g;Jvoáq~FI$@oB mENr 3ykp/_&ŗD= 8}",m3wQz.5Ơ)Ə|tN\AӝZ3E 5l-6vvq11VФeB"óA=Âue\ql? *p轪D]|엱QQ2'yT޾;+;1w:R4[JaTЇ2H/|嫄?z!-/ q;ݡa~9=|0k;уE`Y ^2jk\2z . rNHt.ZC!KG ½ƚEfw1#Wwn;P/{GW/;'4Y$@$@(S L)V?.f~9^v6zҍ| k*#vy.t66]\f}ؠ_-rXYG˰,:g4|hyӻ"s67NՑ() zձf;:NfkoG-u<A XAf{^Sϡ+`ںyUZ_)aoM'aNtHxc;k嫀o?v B׈AAUu5;tVWg ӫ 63~ UJڠTu,T_~+K$@o[Μppi/uƥo~'zye\m,0tTvW.^fG6s thHuLYpWxx}gX}C0~?)9]02iB˗з75ƛ TocxxxHgc+Nlh)#k/\k71<,}tD7 {g7\˃ ooc"[C+O9{(!/>ʺxxkbg~߿rN{5DW/wncǏ 5 '~E9ra_s_fepx[++jGGnX CSb%` t>x14d@k)pr/,~ bڍslL \!OEeOFMصdt,@Thzq 00q"ѽ;pRK 00T}.`="aђ ":괂Y$@$ X@œ'U]lhLCleGw墾[{Se1gDu8>󖭈I&bzb=aqWCk 2{uJ zD,c7|ބ ucW|p ò^^q]>?mY/ڛ9o7ՉYY9k{ݮ}`7Nl}]D6*`x#,ߌ=|~{'qOq0/P}S}[2PDYq   4MܢnU1 Wk x`]To 6L88:o[z  /+Ϸ65_T|`#NJzzHHHHHHHHHHL$ӑqoLi&mUCJnHkO+TL+wq M ?4xTMJ_ߥ_P'7QU@JCU%(T4H" PQb#ގo+Ge*2Djj G)(' $JRUP5U%e0H $*#0a`q L)TQPS5`gKJDTa*$U% UCPUR& 2ʎO7]83Ջq\?|8P"jDgG::2B'SԼT$ E5ײk IDAT燪1H@ADUFC`%8Gg""j"K_Ġc u>*f*IUI<j(eU%5b" `!Re,^WԼ-a?w3*SSQTMJSGq9!·P6呥$U%CUIS ,dp [V0K5>y0QLMQ"⚪P5 V+%F\UFu>*#KUIJ!=?T?$@ d,U5\\x5;[|)TQDS5/W^E7׿:|2U@&SUR`񤪤PUR & @"* f X(2ZeU%"} =n#NM*c!                                                                 HԂ\|FtҦnUXYY]nB\>v=n3eڠQQ7oHHHR/t6[R8WA%cΒ #Q'y&j rewur}KHH$`cvsq| s7i#CCD2{g۲;ްgo?{ޞͻ998FDFb_miee۸ʇΎ.ݿ#\zn=k,11Ksrt+uut^ڍ#ųE7-T*|`=B9 m GbѿEծ^zj;wrƮ{Je~dG\  H?}ДG)Xް? AzHɓ51sllESf56R)Rd۲',V-{wĿQ5[ |o? Qh)QQsǟ| W\wwk^ .1nSRa8#CzN$2짧{`kT1 pO 'gkrUf @V@%ƭ۷ E< O3cO)`ldb"Ѵljbl _k  =OJI=>"!LnjlB<Jdg?Ȓ 2 a:19f!ONI* rխ1HHF x?ϢzӅ 8Y4V6P h[yx!~yC; mLAtS?@-4=Em"Gf'!)$\ s $4冖n$@$@y@Vypq/_So=,Nz_#cn#--:5-%$2K VBbF4yaFϲQϢ*GQg?}Rd%7 yLS]nh֘J$@$ 䑑kw`G/-7{<.lߠ މ{q b8sg]REJ2lΆ*=s!tlC> E1IEM!\|@۾=uwm %`d/qr>esG񰃊CU1$   7@ |H._V}Ϝ7ڽi.  @ u,m#?b^hHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH ^6fiЗK%cVcv`R! @Gł($ xHp%>eociay)OeO +B=XHTK7oʅ8FO| %ߺ[PzyBZX^S_;^_ǜK^keo\T_vV0&2"#=F *gqCsv }cA.ZͻXX6}^0Wֽ4B` zx_f&}$w߳p6*oz$`VB!YfNq57l>UF"pv~,*;K%cHv 8>S v/X$@$@@ d KVQo%A!w75%ݕ;FM>“#;yE]+f0~~~mAX`nX+B=M"OĽ;¾PtgȒzJDFиݹG| ?~GdQ]o;),k$^X]cw~8\^"lTf403q/Hm,lУ3'2IJW  I 2d_?Y?o^nwͫ!7: t]m^3tztHqBt TDxWadlq~B>{+Є{L}*9>ݸsQ79I?ow)B~Γn0Q[vUX0tF?A^"ճdd~ꅼx):hMq3?n|sFF'xnY<&  7@ljӪƹ¡#'ߡۛ" x 4kAw\3RۧRLk ߜElM9>  @V0n9 3سiڄ'Zx=x6K!                                                                 x 律^cvԯQBrjߍ&)9^l1T?fj,>Y}֚HH ՈX*Yt*_/b{a[+[0T?dM##W޼ѳ=] +'0 ^qst]>qaFƠbG'%ภЎm1|ת+A ze\KMKZUԭi!Șyёi5Y:{b_w$[aYYXfΖێ^8&ag󡀊+8O' yo7-r пgJj~p\+K~v^_h2Pdɻ4hdd h-k5Ր'З##AQ" ߸8wQ C:wuHIKYg/}2 MUJUZu;jfM[ک+⸉_clrɊެnɽի\[WuV qw>sUןklJC#cNֽ!2}-FSݚ8nW~猘P_;[WX/m.ծmV;gmvwryej! RzّM]i=_#(Z)G_ %$@$@ "fɉK~Z`|ō&>uǷa8tRXOmͺ;}0[!PQى*<јE}*kYT˪@9 ;vぼԀ -)e딒 <=sr e-FcHH  h395o|XT(,e896+0)E&<&[v -$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@r>%]u?PYWBfçR5Pr_8/fGjhdv+Tt3q,XHWoWq[O#SHHHU0~U \=K.n/}f/9'`ꇵoӴٍs"Z[Q g'7M~yWE̎kb=}{hbVu>h6`wF*/)>.^ASHHr@\yw˞po]gUt̗(&.پ~^-usGSRe|MLmAByZڹ1 wbgQejZp~WեHѨ dv-JڷlFF٫a*p ׎9I9 Ry$88w|eݽʯ\=uTqݾM2M }C_B&.Ƿ-bm ><Ⱥ8)[2%){¾瓐8qpJ}xawn#(%$@$@$ KR}bR*\cd o[㐇\\܁m=}'##&"ۍ2;1Z$E|u.q7n7| >W?D$@$@@ d FFF5:1% ߸ -%D1exM y}"f= C9ڢV&2;X ~~kja bB@~ѪnrB|Cn=ZIHHKJJc,V;0'+6j݆ܒ W415}p铱"z.[QAFFV.Pe{7WQx"M=Ân"c FY0K)"   򕤾5b>ybW{6`yM72g^g6oP!%1A ظ׺kQ9mŐj]O:OoؤzBFۏW].tp/XňҒu+WG@"/=|JVq穩 > gd $@$@$7ؕqݚetrN=dw8 ݶ3k1"qfԤ%W IDATc蛚oYv oc䚸 cR؁- /--Mθ?21kwI~4Nk=M1 dI O+h]QcϽX,-_ŃeMؽ`0h^K\>lY# 96d(t0! n߈ffV.ıI|I|x1[Gru\~1l}}J\ IIOD|&HH %Gڕx՚ Oo^ǰ[wng8sLdSfNq57l>U>P5.h (xyG޿BnXпKvB_Tɇr8wgfǴ tA3tpHH$Gsw]KVQo%A!wS%ek7su[XcDǂ^^lV7==XBXs?=} JT{#2p(~Ν65O/ZI:v&GғGOk{'X.$i.iBLRعGGi+n$ӫLW/kSy@$@$@!`W'4*ѱ1٬Bͫki1dl6ihAR10РG?3>t, @Pugt1l`jff$ ;x`=z1W}7?~erB<^aiRw{Ow.\f_TC%[ OؔX8z $b).ؓͺSHHHGN|C72PHHZyQW#gkbU{B$@$@$ 08a"=`p-VT"          Ȓ6rPij* B 'PQ` ?%]s\gؐ)ٱsIHH 䑗 p`WFɸՈU~rȁ"+4n؍akW]IVfC?i))kvQ~+cM𾁘ȰS$"m}m6xҺ)q!G ¶xb\;C1 y$8>YXڻdmz݇My>"٧GDzbzhw+xa[L~9`*aBL tm,/2jгsaoBbx++x1f~%"6ؖ2')'  WG ' pbWؕqXANۤԯU&I1Ϣ"B9xéP]##^hj?xY!o6HRܭXS;$ y;1 `Wƾ> Yk`aexC88"&1zWp(!5__hB!$gwܽtW'l=PQsmт6Ya>%o}5+vgf Nyd@6jk_ubJ#߸T:֋ؤ:J3o8DwmLcGyl/Y8xISf/0`n>v}ĆOX9v}*S!`yL$@$@@ d ʈ M-,/bO`x+zfxF.ٯm$L`wDlʬɅm:o3"K)ˡ6RSRcdXp1W3bv   #E~T}9ƮۍCn\uv:M *T8xF&F6P`vVxnܛ|󗓄" Y;5< :Pxw7d2UF LiZv`$@$@$ W$flf~> .}*Uzlf Fy&RGslF]4Y!          ȓz\v3#ߊS߭& |:m'c ݛ /Fw=kUϞ]1h PүVsw!5~v$@O 2b3>be_4z͎,^{⓶2Ⱦ] ]%KwuǣU+^Q ӐTorzacy$ urA<%~*vUO<ϖ$WM 2iiaA76V7ǽ/v|jRʼ_=M$b7Ő[՛^>HÃkL/F΍x!v~~ eHáV3i̭s'oj5#uځ3l1d{Q[gOllWɉ̚zq1kw-=}R|2v9dێ5˰]VXV?;$v<ϝK/_G~b?BCCrʕq wx5cEIq+ x(˪ٻy`P6O.;ee+  D;Con)4e翌Bџ؁WX2lekR(,"$@]x}ku:5lŁ]db7Kk錼|vZVf|' ZƯUGG55 1 Jt{^BDƖaQ~VV/-&MGWai[7M j2,gǗs6Ůg-ҕ|4#_CHcWuC`GW|葫y@otX\unBXv2FĮ܎@ExUR"] N]MW#~OOP@nj+Qs{v9iLzZ)ct(^M=nK[ǡ0Jͯ O;%2cM^2шn\8!KNN\mr.;eچ=@-˗#f/7W9U.T1Ȏi)&աH Hpe+cmܕweXoDܱɣx$1݀\0#-56,p*Tff1F]qb=2PF/t 8*]2#'DUf D8Snjgffjnwt2'r,/X=ah&56L|Fjj?M^-͇2럗b9,"Ŵeߕ_()ew*ڗQ9B.QIIL*bD.߅?u#ObrJF @ rkWF\Iָǘȷu֬5+䢽a[& v/ԼHhIhpv-dRLX`Wt2~}">z{>pN+Uuk"5o\E.L`Le>QyErkmūbD4D,21+1&p 3XVn른[&ʵ*`E#oV DXj]@ew쨜Zu 8T.^N QWc1:{f"Uj D iCwet-~6bHJej54|E_sX0ؠGgNh;ܴaEFC "#yot؇.2y cn2;I1_>SA4̾Ƭo-MgU:CŸ}`+j@jwb!LXtM*[f+66r,H>GL=8'vM^2G|1^DEE^,p]7j]@ew쨜 iYO/4Y|LtݽWaph ?:_JW$b($<*o讌O쇗I4m/[9##ٓ[gLі)|LO(̺v )~ۼfv)b_w4_[vc1SrZ'lݏw|@ͻ؟G7;.뗜eʸ%-S bؘ; :ڵG'n;5Gd]@ew쨜gv,l#BOY);eEw!P;Z4oB! Kkla:;.9ݲtrkܲa<`7UzHo5[0A5doJy?ɭ]@s[sj~[6]% xIsHgʏbbRbP3c柇.P*9cnɱ9#K}$hG$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$V0y+Vry|1C;l(!9N]%ʾMRrҽ`lnّ^SM׺w= gMՍOy:.!VIHÿVq!KP"D7r=_#^ģ0z\Kkቢ>&[8HɘovU¸>D♄chX>v6vhx<^H \=κzA+rPH9#f 4ψ6pֹ:W*3Hrqnw혛%&'‡p_n1P80 b=SD<}DU*"EG%%'b(BES%rm>%-5GW;pt6qf)Wž"W\[86L~CQA$ Ey$8@g +]Raٽ[n+ZVWR_x^й jV YT>'ѳllo?*E0Hr@9%;V 8)pEp/ѱ}6pxgBfi색YCD*nRӲ/!v`ֺovԮ^Ĕ~^_;up\Q&&&\x`˓gOdN a~zF.޺Tr/#k/vcXh96Xcel6FٗqwMF[i_d̵stбA[ eZ7Wt<ҟ??33KKI޾]z"Ld)cbZz'N36ɇA|]5nHȭ*ձGy߹|jRی\n# kF/nQU x`{^lP4Uv̢=[ ^'rȢy}*7m \eii35pūLxsɰ*IeeLv0`ԛgC~] uzx_OsK'$<{*Qd~fYA* xtujNw)}&,?iFf6nתcKJICzZ+/UNa`={)Mm>pT^(Jju;&&Z5R1W&!̆Fx ;r})b¥ǗsaM;8!hQy+7xZӤfi[4M S̟̾g,I_ᐱFL-WOv]Up[ʕ^; +%GF];ibwkwo|+/Wa9p\oL :ߺ÷dG}J7q'PWݧdxFNڢoD_^ދJMNFjX-&݊`,A? BvS;6c?:"TWMk;(Xу8HOr?MLtfx咣'0Pu%>NOOǍx(ܔWGW}dTr4u*Z IDATw1`FͿVL|ae#L<-**^5 &G,1)۾~K K(>A~ǷC8aWS 1\ IׯzP_ǭci;^_K^Epv EpYffQo8h⢟Ŀ VRT TUS 'GL+6B;7 g~NLI²7./;xASBEo߭fΞIO+zL)I{ah=j68pœ`}#,}%_+TڽpV =msKܼom ܎y[t6dMQ⧢[ wdK:> "eE|֯(rGE \3[5.Ё.^ޑS)WOY(' C i%+(`뒠W=]&`f=vacFrtZ9VWoyןHKILgjJQMP܌b1q qW elc:^bLB͍#7#.ٯ_r뚾qEOC0ٍ'c.GYIQ@/)VNg{̾J0yu:zzY;Dݻ|&GY2?+E! 6y$8R3m,8}V|g"YfHG'n;5z,+^ q~B2{xV֟n܋Q79IkSM( f]o|@rǭÖoHuS [})漳 2 1Mb^C? "8N}ˊr?yХXIͫ?Zty/x]5I+??JYf_^h; ڗ]k#?}CVO} r&UI ӥI'~/k(y|1C;l(!9NRwcIJNʾ䟧{"F?7}RB$@$@LA92Fr:{W#>bߪg ||r`D{a[+[Ⱦ>w'[Vќ7zKAEB  7@7WC&SR[jfmi!O"QbAgN}UW 7drE']Kx~Awo#T|Pqy߲nwBeL_5+08Y5ܴz#7/:r7mq\jښ嫣'uH+)UJUF[K͇vI!%-eu_ ^nudea;[n;zᘐ#2(Qdi߸8wud)ZjhAY&- UqI$@$@$`0AJO\a|95yͦ(ƷPSW"U)+:v+&)ip9&&fl\bF7뢛}rq*֕o^8;mIWtBiqaw/1}Q_И?zvF8.Q0:1F2t;nJȁ?2W~zvڜ[SN$@$}W}K5m>%-52>uǷvtR*rYMZL&XVpܪ,7uT}1@N! C-RN$@$ i}%8fބo+zI)ɺpl HMLL.k5箝vƀvX[૊(/z'-- ggDBRp];ned)MxщcoS .!_E^1xU]vd|]ݙ, ʤ?B"UdO$@$*`¢)^ǔu?Ϣ1gL72M! o0"ڑrMpciwOZF?^k5Jo.GǾL^%$%#@Ap  &- ߆swCCngc7HK8eNbc}[ MCjyTL CAxʝՔ zB <8)9:$&'a< 8Cp{Iqi1 B OXؾA 8"L.3dNJ0e N;X7kȈ{r>e˹xHAV2;Z-hWubJW?rwLLL0'Ϟh9Àc˜!ρ?h۷G.NԼ}A   xA `@l$@$@@蕺+3gN,@Q"o* Uy$8ȫ͓d4';G|;peY5                                                                  xduZoߒo}j[M3I|4= e/Ybߓ+f+EO꫘~"gjCV,WΆ֋$@k.5Wճdq7Pdwo[ ],(*)p)7NӵcfUyj`zZlEǷgvok;vJ63i ֲ-;3CV,7vu[ܲc(s@^%z7C#\=cݧ}{[5>1E]zc\"Ld)cb^>ĝkL<-Mȧ8hpCƺuF v}+^z.[Ԩ ##+qgf2}#Bu8$_rB uejկ"0r̀gQKJ:").vY33)ډTݰ⁽5osx튲?OCЗYuG230:"LE_U 5 B³PFoQc[Z߹|jRreܐE9XCT4Yd繬h"7Q]Lv0`ԛgCØ𾌿̎II+]yӂ(]rJ KoZỸx'wuwħT:f|glkiгWBLxm9.3˹^ސȨbGfXW8jvb X=kQ\jk@&aj M4{(klb2uB*X';,4)n^}?[7mloʪ^{"$5uxGf)Fku257G]-ZתM0e9SfJv,;eed 4bN=E)jDql D Aok;M.s_sXAN$4pp+~崂[Q߈ABOaӹɣ!咣Hs =Jdؑc45%SyץQbX-fj>%Nڒ&n\8!ɉaYh,-o.[pEc6vltLtDq}?M?$>Өed`B]_UFY3y4d z]{/+59_QGaA\}n”Avϱ2kCSE< 7"4w1Ȼ۫/WD$}y$8Ȳ}ʶR*ʮb=I㳻\z}5s?/{^ȝ ur153C4 ]EgL)ڑшM>ys: .=._2eP7>%Zq-RLBή1ORSBnݘק)0MY}Qb+>Y7gOxMo0'6E?qPN$`<`ZaL5~xCЭQޯ}։)IXvpEeX%{F߃lJR➅GZ$;g7]_fJR]HpgJM>$c>_Wj1fOBuP,Q|B6b6WVnZJ Rq$n‚n,cGykxv2 '$ 3`@&*" %.^ޑ 8h#<yW{fzH\EnjGys̔Y>gO8/}",KaoT颚9#C9 A bZ3 ?DQdl]2qg_@o0`ae?=$V>,+_޾!(? <7$v~O5$#k3L+*]ƩcYy~+!۹;ԔSs ZIX^Ԇ{oChǛ[|fUw/yO3"/_͌[Qݑ}?yOӋ L+: atxËe}ݛ&lBNTCn9!r+_ю)3Xzs6˸i[w㐇h} E!;2> D ꌀT}n=9fΔ~Lq/§b;*>]o ]\ͫ?Zkwf*BfG!n: Z7m W[%k=`CGS~<g tvޭ#(ـ|s< ͐cY~a_E#SFyQXre2oQʉm.ۈX'SA0F}ǭÖoHGi=aAVڑ?e jwgCOW]@s'~6|>V[ؑHHHHHHHHHHHHHHHHHHHHHHHHHHHHH$`jŦDotHHH KMMݱcG͚5/ޣGWPM ^>?޽o޼Yf4~HHHHoo2e +tHH ܕhzA$@$@>=   7we|[ we56J$@$@+: we5kJ$@$@9%]sJHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHrweu4H$@$@o+&  &]s( @#]^F$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$@$஌omq  mܕ1 +rHH^X$                              O0OU%  ͻn,(ϙs9s֭d{7nRSR˗ܹS^< ۷ܹs :U.888gysW7Wny,8##aH"GY{m\~k׮mڴi_zy %J>Zj):SQUsk *;v9& H WoK /^D gg;whN}S+H ڻ)S{w~J.]qvV9vXɒ%Q3g-Z͛96֭ t˗}eYA2˖-kҤ9s>}w9rD+Q9qtt}=VZf7Y]~]$*U JhΚ5L\h'==ta ?~WʙԠA;v藨G [XX$&&\}o1̙3)Y~aG 2;.\ΝY(%{6mڄ\_5Nj[\ ?|0Ϥ={|k32;2qB,𓱲B ͕UR߾*vPÇ[[[+|6ڶm=zԵk2; AqႀAz)ڇAyll,:hQz…u{;iOݻ7矸&%%IK◅ϓ&MRo/,k/E>(Bq'B/Jΰ0t opQ78r;&&&hT'SP_Eqb Ȉ[]v)Z9v~f1o X\e'np78p@|Ui/?Ed|d#U$yV.8k18]=\YehT0KŔ O al (FAA8qK_XC'0*~')Q}%M`ZS Rz*\XeA.a?o֬rM6[ne*(raUƮFq 5 ;UtLf|rv)ͼ~-<\\UOqMmRtKG~WgϞ/8AD@" ʅs}njn 2e\ѮiD|Ixje'E#K~0ګW?!TΌ ?S0evܓDԏ .-[@ډ^6;eўf\#_W(((((R#ܜp}P|AÆ sV#k/6Nxnh}U+yenjOE*·~~WPgY{'w%/$q֭* #<\L,[ŀ0LNN{r b4cwfi8:+W"Ydv KV^ rʲvYz_AA8VkѢ߸qr9c\a  $Nw`L p$>)R}mi&qouG"vt@u\(a $> nub9iɬl}{IknN'8/ӐJKeZ~{iP8@ :GfOQ1I"_e$v+nL7vN<.86p5B!~=>Y8lQd,4 %7&jQ)Ou>xV%q87$tzJN+6!jF EIN4v(R+cL1O}p\X*sUIcJ=87 Y5>܉O]oHL_ GG+yݐϑ.Mqe0tKKavqߨH-Ⲭx!>9]'