# vim:ft=sh

### Display a few pertinent facts about a certificate received on stdin.
### Example: openssl s_client -connect localdomain.dk:443 </dev/null |cert_summary
cert_summary() {
    f=`mktemp`
    awk '
        /-+.* CERTIFICATE-+/ { n++; print; next }
        n % 2 { print }
    ' >"$f"

    file "$f" |grep -q 'PEM certificate' || {
        echo "Not a certificate :?" >&2
        return
    }

    openssl x509 -noout \
        -subject \
        -issuer \
        -startdate \
        -enddate \
        -fingerprint \
        <"$f"

    openssl x509 -noout -text <"$f" \
    | perl -ne '
        BEGIN { $s = 0 }
        $s && /^$s\s/ && s/^\s*// && print && next;
        ($s,) = /^(\s+)\S.*Subject Alternative Name:/
    '

    [ -f "$f" ] && rm -f -- "$f"
}


### Generate a hash from a provided subject string.
### Example: subject_hash "CN = localdomain.dk"
subject_hash() {
    subject="${1:-/}"
    if ! printf "$subject" |grep -Eq '^/'; then
        subject=$(printf '%s' "$subject" |sed -e 's/ = /=/g' -e 's#\(^\|, \)#/#g')
        printf "Invalid subject format, normalizing to: \"%s\"\n" "$subject" >&2
    fi


    temp_cert=$(mktemp)

    openssl req \
        -out "$temp_cert" \
        -newkey rsa:2048 \
        -nodes \
        -x509 \
        -subj "$subject" \
        -days 365 \
        2>/dev/null

    openssl x509 -in "$temp_cert" -hash -noout

    [ -f "$temp_cert" ] && rm -f -- "$temp_cert"
}


### Set X11 window title
### Example: setwt "Bob's own window"
setwt() {
    echo -ne "\033]0;$*\007"
}


### Generate a high-entropy yet easy-to-remember passphrase
### (along the lines of: "correct horse battery stable")
ppgen() {
    fn='/usr/share/dict/words'
    [ -r "$fn" ] || {
        printf "No word file available :(\n" >&2
        return
    }
    n=$(printf "%d" "$1" 2>/dev/null)
    [ "$n" -eq "0" ] && n=4
    sort -R <"$fn" \
    | grep -E '^[a-z]{4,7}$' \
    | head -n$n \
    | tr "\n" ' ' \
    | sed 's/\s\+$/\n/'
}


### Generate PLAIN auth string for IMAP
authplain() {
    local user
    local pass

    read -p "Username: " user
    read -s -p "Password: " pass

    echo
    printf "AUTH PLAIN "
    printf "%s\0%s\0%s" "$user" "$user" "$pass" | base64 -w0
    echo
}


authlogin() {
    local deco
    local user
    local pass

    read -p "Username: " user
    read -s -p "Password: " pass

    echo
    printf "> 334 VXNlcm5hbWU6 (Username:)\n"
    printf "%s" "$user" |base64
    printf "> 334 UGFzc3dvcmQ6 (Password:)\n"
    printf "%s" "$pass" |base64
    echo
}


emph_stderr()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1


nsa_codename_generator() {
    n="$1"
    [ -z "$1" ] && n=1
    for k in $(seq 1 "$n"); do
        for what in adj noun; do
            fn="/usr/share/wordnet/index.$what"
            fn="/usr/share/nltk_data/corpora/wordnet/index.$what"
            [ -f "$fn" ] || {
                echo "Cannot open '$fn'" >&2
                return
            }
            awk '$1 ~ /^[a-z]{4,8}$/ { print $1}' <"$fn" \
            | sort -R \
            | head -n1 \
            | tr a-z A-Z
        done \
        | xargs echo -n \
        | sed 's/\s//g'
        echo
    done
}



mkcd() {
    for d in "$@"; do
        mkdir -p -- "$d"
    done
    cd -- "$d"
}



Spadd() {
    ( [ -z "$1" ] || [ -z "$2" ] ) && return

    local var="$(eval echo "\$$1")"
    local ext="$(echo "$2" |sed 's,/$,,')"

    [ -e "$ext" ] || return 1

    local item
    for item in $(echo "$var" |sed 's/:/ /g'); do
        [ "$item" = "$ext" ] && return 1
    done

    local sep
    [ -n "$var" ] && sep=':'
    eval "export $1=$ext$sep$var"
}



if ! which seq &>/dev/null; then
    seq() {
        local a
        local inc
        local b

        a=${1:-1};
        inc=${2:-1}
        b=${3:-dummy}

        if [ "$b" = "dummy" ]; then
            b="$inc"
            inc=1
        fi

        while [ "$a" -le "$b" ]; do
            echo "$a";
            a=$(($a+$inc))
        done
    }
fi


dcm_summarize() {
    if [ ! -d "$1" ]; then
        echo "Folder?" >&2
        return
    fi

    find "$1" -type f \
    | pv -l \
    | xargs -d "\n" -r -n1 -- dcmdump \
    | grep -E '^\(00(10,00[12]0|08,1030)\)' \
    | perl -ne 'BEGIN { my %seen; } print unless $seen{$_}++'
}


random_bytes() {
    n=${1:-8}
    od -tx </dev/urandom \
    | cut -d\  -f2- \
    | tr -d -c 0-9a-z \
    | dd bs=$((2*$n)) count=1 \
    2>/dev/null
    [ -t 1 ] && echo
}


netmounts() {
    [ $(uname) = "Linux" ] \
    && awk '$3 ~ /fuse|cifs|nfs/ {print $3, $2}' /proc/mounts \
    | grep -vE '^fusectl\b'
}


ssh_to_ancient_host() {
    ssl_overrides=$(mktemp)
    cat >"$ssl_overrides" <<EOF
.include /etc/ssl/openssl.cnf
[openssl_init]
alg_section = evp_properties
[evp_properties]
rh-allow-sha1-signatures = yes
EOF
    OPENSSL_CONF="$ssl_overrides" ssh -o PubkeyAcceptedAlgorithms=+ssh-rsa,ssh-dss $*
}


avg() {
    perl -ne "\$sum+=\$_;END{printf\"%.${1:-2}f\n\",\$sum/\$.}"
}


total() {
    perl -ne "\$sum+=\$_;END{printf\"%.${1:-2}f\n\",\$sum}"
}


t() {
    if [ -n "$1" ]; then
        dir=$(mktemp -d -t "$1.XXXX")
    else
        dir=$(mktemp -d)
    fi

    pushd "$dir"
}
