Skip to content

[Bug] CodeLLDB produces "Cannot read properties of undefined (reading 'uri')" upon invocation. #199

@RokeJulianLockhart

Description

@RokeJulianLockhart

JS Logs

VM167:1 Console was cleared
undefined
notificationsAlerts.ts:40 TypeError: Cannot read properties of undefined (reading 'uri')
    at t.Cargo.runCargo (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:66785)
    at t.Cargo.getLaunchConfigs (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:65611)
    at k.getLaunchLessConfig (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:58595)
    at k.resolveDebugConfiguration (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:56128)
    at Object.resolveDebugConfiguration (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:53033)
    at /usr/share/code/resources/app/out/vs/workbench/api/node/extensionHostProcess.js:128:102844
c @ notificationsAlerts.ts:40
(anonymous) @ notificationsAlerts.ts:28
B @ event.ts:1219
C @ event.ts:1230
fire @ event.ts:1254
addNotification @ notifications.ts:228
error @ notificationService.ts:189
startDebugging @ debugService.ts:445
await in startDebugging
handler @ debugCommands.ts:763
await in handler
invokeFunction @ instantiationService.ts:109
n @ commandService.ts:99
executeCommand @ commandService.ts:63
(anonymous) @ window.ts:173
emit @ VM4 sandbox_bundle:2
onMessage @ VM4 sandbox_bundle:2
notificationsAlerts.ts:40 TypeError: Cannot read properties of undefined (reading 'uri')
    at t.Cargo.runCargo (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:66785)
    at t.Cargo.getLaunchConfigs (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:65611)
    at k.getLaunchLessConfig (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:58595)
    at k.resolveDebugConfiguration (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:56128)
    at Object.resolveDebugConfiguration (vscode-file://vscode-app/home/RokeJulianLockhart/.vscode/extensions/vadimcn.vscode-lldb-1.11.5/extension.js:1:53033)
    at /usr/share/code/resources/app/out/vs/workbench/api/node/extensionHostProcess.js:128:102844
c @ notificationsAlerts.ts:40
(anonymous) @ notificationsAlerts.ts:28
B @ event.ts:1219
C @ event.ts:1230
fire @ event.ts:1254
addNotification @ notifications.ts:228
error @ notificationService.ts:189
(anonymous) @ window.ts:177
await in (anonymous)
emit @ VM4 sandbox_bundle:2
onMessage @ VM4 sandbox_bundle:2

Reproduction

  1. Demonstration

    @.Origin.xdg-email.-.Visual.Studio.Code.Date.20250620T193452+0100.Type.Video.webm
  2. Content

    Details
    #!/usr/bin/sh
    #---------------------------------------------
    #   xdg-email
    #
    #   Utility script to open the users favorite email program, using the
    #       RFC 2368 mailto: URI spec
    #
    #   Refer to the usage() function below for usage.
    #
    #   Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
    #   Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
    #   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
    #   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
    #
    #   LICENSE:
    #
    #   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.
    #
    #---------------------------------------------
    
    manualpage()
    {
    cat << '_MANUALPAGE'
    Name
    
       xdg-email - command line tool for sending mail using the user's
       preferred e-mail composer
    
    Synopsis
    
       xdg-email [--utf8] [--cc address] [--bcc address] [--subject
       text] [--body text] [--attach file] [ mailto-uri | address(es)
       ]
    
       xdg-email { --help | --manual | --version }
    
    Description
    
       xdg-email opens the user's preferred e-mail composer in order
       to send a mail to address(es) or mailto-uri. RFC2368 defines
       mailto: URIs. xdg-email limits support to, cc, subject and body
       fields in mailto-uri, all other fields are silently ignored.
       address(es) must follow the syntax of RFC822. Multiple
       addresses may be provided as separate arguments.
    
       All information provided on the command line is used to prefill
       corresponding fields in the user's e-mail composer. The user
       will have the opportunity to change any of this information
       before actually sending the e-mail.
    
       xdg-email is for use inside a desktop session only. It is not
       recommended to use xdg-email as root.
    
    Options
    
       --utf8
              Indicates that all command line options that follow are
              in utf8. Without this option, command line options are
              expected to be encoded according to locale. If the
              locale already specifies utf8 this option has no effect.
              This option does not affect mailto URIs that are passed
              on the command line.
    
       --cc address
              Specify a recipient to be copied on the e-mail.
    
       --bcc address
              Specify a recipient to be blindly copied on the e-mail.
    
       --subject text
              Specify a subject for the e-mail.
    
       --body text
              Specify a body for the e-mail. Since the user will be
              able to make changes before actually sending the e-mail,
              this can be used to provide the user with a template for
              the e-mail. text may contain linebreaks.
    
       --attach file
              Specify an attachment for the e-mail. file must point to
              an existing file.
    
              Some e-mail applications require the file to remain
              present after xdg-email returns.
    
       --help
              Show command synopsis.
    
       --manual
              Show this manual page.
    
       --version
              Show the xdg-utils version information.
    
    Environment Variables
    
       xdg-email honours the following environment variables:
    
       XDG_UTILS_DEBUG_LEVEL
              Setting this environment variable to a non-zero
              numerical value makes xdg-email do more verbose
              reporting on stderr. Setting a higher value increases
              the verbosity.
    
    Exit Codes
    
       An exit code of 0 indicates success while a non-zero exit code
       indicates failure. The following failure codes can be returned:
    
       1
              Error in command line syntax.
    
       2
              One of the files passed on the command line did not
              exist.
    
       3
              A required tool could not be found.
    
       4
              The action failed.
    
       5
              No permission to read one of the files passed on the
              command line.
    
    See Also
    
       xdg-open(1), xdg-mime(1), MIME applications associations
       specification, RFC 6068 - The 'mailto' URI Scheme
    
    Examples
    
    xdg-email 'Jeremy White <jwhite@example.com>'
    
    xdg-email --attach /tmp/logo.png \
              --subject 'Logo contest' \
              --body 'Attached you find the logo for the contest.' \
              'jwhite@example.com'
    
    xdg-email --subject 'Your password is about to expire' \
              'jwhite@example.com' 'bastian@example.com' 'whipple@example.co
    m'
    _MANUALPAGE
    }
    
    usage()
    {
    cat << '_USAGE'
       xdg-email - command line tool for sending mail using the user's
       preferred e-mail composer
    
    Synopsis
    
       xdg-email [--utf8] [--cc address] [--bcc address] [--subject
       text] [--body text] [--attach file] [ mailto-uri | address(es)
       ]
    
       xdg-email { --help | --manual | --version }
    
    _USAGE
    }
    
    #@xdg-utils-common@
    #----------------------------------------------------------------------------
    #   Common utility functions included in all XDG wrapper scripts
    #----------------------------------------------------------------------------
    
    #shellcheck shell=sh
    
    DEBUG()
    {
      [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
      [ "${XDG_UTILS_DEBUG_LEVEL}" -lt "$1" ] && return 0;
      shift
      echo "$@" >&2
    }
    
    # This handles backslashes but not quote marks.
    first_word()
    {
        # shellcheck disable=SC2162 # No -r is intended here
        read first rest
        echo "$first"
    }
    
    #-------------------------------------------------------------
    # map a binary to a .desktop file
    binary_to_desktop_file()
    {
        search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
        binary="$(command -v "$1")"
        binary="$(xdg_realpath "$binary")"
        base="$(basename "$binary")"
        IFS=:
        for dir in $search; do
            unset IFS
            [ "$dir" ] || continue
            [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
            for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do
                [ -r "$file" ] || continue
                # Check to make sure it's worth the processing.
                grep -q "^Exec.*$base" "$file" || continue
                # Make sure it's a visible desktop file (e.g. not "preferred-web-browser.desktop").
                grep -Eq "^(NoDisplay|Hidden)=true" "$file" && continue
                command="$(grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word)"
                command="$(command -v "$command")"
                if [ x"$(xdg_realpath "$command")" = x"$binary" ]; then
                    # Fix any double slashes that got added path composition
                    echo "$file" | tr -s /
                    return
                fi
            done
        done
    }
    
    #-------------------------------------------------------------
    # map a .desktop file to a binary
    desktop_file_to_binary()
    {
        search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
        desktop="$(basename "$1")"
        IFS=:
        for dir in $search; do
            unset IFS
            [ "$dir" ] && [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
            # Check if desktop file contains -
            if [ "${desktop#*-}" != "$desktop" ]; then
                vendor=${desktop%-*}
                app=${desktop#*-}
                if [ -r "$dir/applications/$vendor/$app" ]; then
                    file_path="$dir/applications/$vendor/$app"
                elif [ -r "$dir/applnk/$vendor/$app" ]; then
                    file_path="$dir/applnk/$vendor/$app"
                fi
            fi
            if test -z "$file_path" ; then
                for indir in "$dir"/applications/ "$dir"/applications/*/ "$dir"/applnk/ "$dir"/applnk/*/; do
                    file="$indir/$desktop"
                    if [ -r "$file" ]; then
                        file_path=$file
                        break
                    fi
                done
            fi
            if [ -r "$file_path" ]; then
                # Remove any arguments (%F, %f, %U, %u, etc.).
                command="$(grep -E "^Exec(\[[^]=]*])?=" "$file_path" | cut -d= -f 2- | first_word)"
                command="$(command -v "$command")"
                xdg_realpath "$command"
                return
            fi
        done
    }
    
    #-------------------------------------------------------------
    # Exit script on successfully completing the desired operation
    
    # shellcheck disable=SC2120 # It is okay to call this without arguments
    exit_success()
    {
        if [ $# -gt 0 ]; then
            echo "$*"
            echo
        fi
    
        exit 0
    }
    
    
    #-----------------------------------------
    # Exit script on malformed arguments, not enough arguments
    # or missing required option.
    # prints usage information
    
    exit_failure_syntax()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
            echo "Try 'xdg-email --help' for more information." >&2
        else
            usage
            echo "Use 'man xdg-email' or 'xdg-email --manual' for additional info."
        fi
    
        exit 1
    }
    
    #-------------------------------------------------------------
    # Exit script on missing file specified on command line
    
    exit_failure_file_missing()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
        fi
    
        exit 2
    }
    
    #-------------------------------------------------------------
    # Exit script on failure to locate necessary tool applications
    
    exit_failure_operation_impossible()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
        fi
    
        exit 3
    }
    
    #-------------------------------------------------------------
    # Exit script on failure returned by a tool application
    
    exit_failure_operation_failed()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
        fi
    
        exit 4
    }
    
    #------------------------------------------------------------
    # Exit script on insufficient permission to read a specified file
    
    exit_failure_file_permission_read()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
        fi
    
        exit 5
    }
    
    #------------------------------------------------------------
    # Exit script on insufficient permission to write a specified file
    
    exit_failure_file_permission_write()
    {
        if [ $# -gt 0 ]; then
            echo "xdg-email: $*" >&2
        fi
    
        exit 6
    }
    
    check_input_file()
    {
        if [ ! -e "$1" ]; then
            exit_failure_file_missing "file '$1' does not exist"
        fi
        if [ ! -r "$1" ]; then
            exit_failure_file_permission_read "no permission to read file '$1'"
        fi
    }
    
    check_vendor_prefix()
    {
        file_label="$2"
        [ -n "$file_label" ] || file_label="filename"
        file="$(basename "$1")"
        case "$file" in
           [[:alpha:]]*-*)
             return
             ;;
        esac
    
        echo "xdg-email: $file_label '$file' does not have a proper vendor prefix" >&2
        echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
        echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
        echo "Use --novendor to override or 'xdg-email --manual' for additional info." >&2
        exit 1
    }
    
    check_output_file()
    {
        # if the file exists, check if it is writeable
        # if it does not exists, check if we are allowed to write on the directory
        if [ -e "$1" ]; then
            if [ ! -w "$1" ]; then
                exit_failure_file_permission_write "no permission to write to file '$1'"
            fi
        else
            DIR="$(dirname "$1")"
            if [ ! -w "$DIR" ] || [ ! -x "$DIR" ]; then
                exit_failure_file_permission_write "no permission to create file '$1'"
            fi
        fi
    }
    
    #----------------------------------------
    # Checks for shared commands, e.g. --help
    
    check_common_commands()
    {
        while [ $# -gt 0 ] ; do
            parm="$1"
            shift
    
            case "$parm" in
                --help)
                usage
                echo "Use 'man xdg-email' or 'xdg-email --manual' for additional info."
                exit_success
                ;;
    
                --manual)
                manualpage
                exit_success
                ;;
    
                --version)
                echo "xdg-email 1.2.1"
                exit_success
                ;;
    
                --)
    	        [ -z "$XDG_UTILS_ENABLE_DOUBLE_HYPEN" ] || break
    	        ;;
            esac
        done
    }
    
    check_common_commands "$@"
    
    [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
    # shellcheck disable=SC2034
    if [ "${XDG_UTILS_DEBUG_LEVEL-0}" -lt 1 ]; then
        # Be silent
        xdg_redirect_output=" > /dev/null 2> /dev/null"
    else
        # All output to stderr
        xdg_redirect_output=" >&2"
    fi
    
    #--------------------------------------
    # Checks for known desktop environments
    # set variable DE to the desktop environments name, lowercase
    
    detectDE()
    {
        # see https://bugs.freedesktop.org/show_bug.cgi?id=34164
        unset GREP_OPTIONS
    
        if [ -n "${XDG_CURRENT_DESKTOP}" ]; then
          case "${XDG_CURRENT_DESKTOP}" in
             # only recently added to menu-spec, pre-spec X- still in use
             Cinnamon|X-Cinnamon)
               DE=cinnamon;
               ;;
             ENLIGHTENMENT)
               DE=enlightenment;
               ;;
             # GNOME, GNOME-Classic:GNOME, or GNOME-Flashback:GNOME
             GNOME*)
               DE=gnome;
               ;;
             KDE)
               DE=kde;
               ;;
             DEEPIN|Deepin|deepin)
               DE=deepin;
               ;;
             LXDE)
               DE=lxde;
               ;;
             LXQt)
               DE=lxqt;
               ;;
             MATE)
               DE=mate;
               ;;
             XFCE)
               DE=xfce
               ;;
             X-Generic)
               DE=generic
               ;;
          esac
        fi
    
        # shellcheck disable=SC2153
        if [ -z "$DE" ]; then
          # classic fallbacks
          if [ -n "$KDE_FULL_SESSION" ]; then DE=kde;
          elif [ -n "$GNOME_DESKTOP_SESSION_ID" ]; then DE=gnome;
          elif [ -n "$MATE_DESKTOP_SESSION_ID" ]; then DE=mate;
          elif dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager > /dev/null 2>&1 ; then DE=gnome;
          elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
          elif xprop -root 2> /dev/null | grep -i '^xfce_desktop_window' >/dev/null 2>&1; then DE=xfce
          elif echo "$DESKTOP" | grep -q '^Enlightenment'; then DE=enlightenment;
          elif [ -n "$LXQT_SESSION_CONFIG" ]; then DE=lxqt;
          fi
        fi
    
        if [ -z "$DE" ]; then
          # fallback to checking $DESKTOP_SESSION
          case "$DESKTOP_SESSION" in
             gnome)
               DE=gnome;
               ;;
             LXDE|Lubuntu)
               DE=lxde;
               ;;
             MATE)
               DE=mate;
               ;;
             xfce|xfce4|'Xfce Session')
               DE=xfce;
               ;;
          esac
        fi
    
        if [ -z "$DE" ]; then
          # fallback to uname output for other platforms
          case "$(uname 2>/dev/null)" in
            CYGWIN*)
              DE=cygwin;
              ;;
            Darwin)
              DE=darwin;
              ;;
            Linux)
              grep -q microsoft /proc/version > /dev/null 2>&1 && \
              command -v explorer.exe > /dev/null 2>&1 && \
              DE=wsl;
              ;;
          esac
        fi
    
        if [ x"$DE" = x"gnome" ]; then
          # gnome-default-applications-properties is only available in GNOME 2.x
          # but not in GNOME 3.x
          command -v gnome-default-applications-properties > /dev/null || DE="gnome3"
        fi
    
        if [ -f "$XDG_RUNTIME_DIR/flatpak-info" ]; then
          DE="flatpak"
        fi
    }
    
    #----------------------------------------------------------------------------
    # kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
    # It also always returns 1 in KDE 3.4 and earlier
    # Simply return 0 in such case
    
    kfmclient_fix_exit_code()
    {
        version="$(LC_ALL=C.UTF-8 kde-config --version 2>/dev/null | grep '^KDE')"
        major="$(echo "$version" | sed 's/KDE.*: \([0-9]\).*/\1/')"
        minor="$(echo "$version" | sed 's/KDE.*: [0-9]*\.\([0-9]\).*/\1/')"
        release="$(echo "$version" | sed 's/KDE.*: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/')"
        test "$major" -gt 3 && return "$1"
        test "$minor" -gt 5 && return "$1"
        test "$release" -gt 4 && return "$1"
        return 0
    }
    
    #----------------------------------------------------------------------------
    # Returns true if there is a graphical display attached.
    
    has_display()
    {
        if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then
            return 0
        else
            return 1
        fi
    }
    
    #----------------------------------------------------------------------------
    # Prefixes a path with a "./" if it starts with a "-".
    # This is useful for programs to not confuse paths with options.
    
    unoption_path()
    {
    	case "$1" in
    		-*)
    			printf "./%s" "$1" ;;
    		*)
    			printf "%s" "$1" ;;
    	esac
    }
    
    #----------------------------------------------------------------------------
    # Performs a symlink and relative path resolving for a single argument.
    # This will always fail if the given file does not exist!
    
    xdg_realpath()
    {
    	# allow caching and external configuration
    	if [ -z "$XDG_UTILS_REALPATH_BACKEND" ] ; then
    		if command -v realpath >/dev/null 2>/dev/null ; then
    			lines="$(realpath -- / 2>&1)"
    			if [ $? = 0 ] && [ "$lines" = "/" ] ; then
    				XDG_UTILS_REALPATH_BACKEND="realpath"
    			else
    				# The realpath took the -- literally, probably the busybox implementation
    				XDG_UTILS_REALPATH_BACKEND="busybox-realpath"
    			fi
    			unset lines
    		elif command -v readlink >/dev/null 2>/dev/null ; then
    			XDG_UTILS_REALPATH_BACKEND="readlink"
    		else
    			exit_failure_operation_failed "No usable realpath backend found. Have a realpath binary or a readlink -f that canonicalizes paths."
    		fi
    	fi
    	# Always fail if the file doesn't exist (busybox realpath does that for example)
    	[ -e "$1" ] || return 1
    	case "$XDG_UTILS_REALPATH_BACKEND" in
    		realpath)
    			realpath -- "$1"
    			;;
    		busybox-realpath)
    			# busybox style realpath implementations have options too
    			realpath "$(unoption_path "$1")"
    			;;
    		readlink)
    			readlink -f "$(unoption_path "$1")"
    			;;
    		*)
    			exit_failure_operation_impossible "Realpath backend '$XDG_UTILS_REALPATH_BACKEND' not recognized."
    			;;
    	esac
    }
    
    run_thunderbird()
    {
        local THUNDERBIRD MAILTO NEWMAILTO TO CC BCC SUBJECT BODY ATTACH
        THUNDERBIRD="$1"
        MAILTO="$(echo "$2" | sed 's/^mailto://')"
        echo "$MAILTO" | grep -qs "^?"
        if [ "$?" = "0" ] ; then
            MAILTO="$(echo "$MAILTO" | sed 's/^?//')"
        else
            MAILTO="$(echo "$MAILTO" | sed 's/^/to=/' | sed 's/?/\&/')"
        fi
    
        MAILTO="$(echo "$MAILTO" | sed 's/&/\n/g')"
        TO="$(/bin/echo -e "$(echo "$MAILTO" | grep '^to=' | sed 's/^to=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }')")"
        CC="$(/bin/echo -e "$(echo "$MAILTO" | grep '^cc=' | sed 's/^cc=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }')")"
        BCC="$(/bin/echo -e "$(echo "$MAILTO" | grep '^bcc=' | sed 's/^bcc=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }')")"
        SUBJECT="$(echo "$MAILTO" | grep '^subject=' | tail -n 1)"
        BODY="$(echo "$MAILTO" | grep '^body=' | tail -n 1)"
        ATTACH="$(/bin/echo -e "$(echo "$MAILTO" | grep '^attach=' | sed 's/^attach=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }' | sed 's/,$//')")"
    
        if [ -z "$TO" ] ; then
            NEWMAILTO=
        else
            NEWMAILTO="to='$TO'"
        fi
        if [ -n "$CC" ] ; then
            NEWMAILTO="${NEWMAILTO},cc='$CC'"
        fi
        if [ -n "$BCC" ] ; then
            NEWMAILTO="${NEWMAILTO},bcc='$BCC'"
        fi
        if [ -n "$SUBJECT" ] ; then
            NEWMAILTO="${NEWMAILTO},$SUBJECT"
        fi
        if [ -n "$BODY" ] ; then
            NEWMAILTO="${NEWMAILTO},$BODY"
        fi
    
        if [ -n "$ATTACH" ] ; then
            NEWMAILTO="${NEWMAILTO},attachment='${ATTACH}'"
        fi
    
        NEWMAILTO=$(echo "$NEWMAILTO" | sed 's/^,//')
        DEBUG 1 "Running $THUNDERBIRD -compose \"$NEWMAILTO\""
        "$THUNDERBIRD" -compose "$NEWMAILTO"
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    open_kde()
    {
        local kreadconfig profile client
        if [ -n "$KDE_SESSION_VERSION" ] && [ "$KDE_SESSION_VERSION" -ge 5 ]; then
            kreadconfig=kreadconfig$KDE_SESSION_VERSION
        else
            kreadconfig=kreadconfig
        fi
    
        if command -v "$kreadconfig" >/dev/null; then
            profile="$("$kreadconfig" --file emaildefaults \
                                         --group Defaults --key Profile)"
            if [ -n "$profile" ]; then
                client="$("$kreadconfig" --file emaildefaults \
                                            --group "PROFILE_$profile" \
                                            --key EmailClient \
                                      | cut -d ' ' -f 1)"
                if [ -z "${client%%*.desktop}" ] && ! command -v "$client" >/dev/null 2>&1; then
                    client="$(desktop_file_to_binary "$client")"
                fi
    
                if echo "$client" | grep -Eq 'thunderbird|icedove'; then
                    run_thunderbird "$client" "$1"
                fi
            fi
        fi
    
        local command
        case "$KDE_SESSION_VERSION" in
            '') command=kmailservice ;;
            4) command=kde-open ;;
            *) command=kde-open$KDE_SESSION_VERSION ;;
        esac
    
        if command -v "$command" >/dev/null; then
            DEBUG 1 "Running $command \"$1\""
            if [ "$KDE_SESSION_VERSION" = 3 ]; then
                # KDE3 uses locale's encoding when decoding the URI,
                # so set it to UTF-8
                LC_ALL=C.UTF-8 "$command" "$1"
            else
                "$command" "$1"
            fi
        else
            DEBUG 1 "$command missing; trying generic mode instead."
            open_generic "$1"
        fi
    
        if [ $? = 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    open_gnome3()
    {
        local client
        local desktop
        desktop="$(xdg-mime query default "x-scheme-handler/mailto")"
        client="$(desktop_file_to_binary "$desktop")"
        case "$client" in *thunderbird*|*icedove*)
            run_thunderbird "$client" "$1"
        esac
    
        if gio help open 2>/dev/null 1>&2; then
            DEBUG 1 "Running gio open \"$1\""
            gio open "$1"
        elif gvfs-open --help 2>/dev/null 1>&2; then
            DEBUG 1 "Running gvfs-open \"$1\""
            gvfs-open "$1"
        else
            DEBUG 1 "Running gnome-open \"$1\""
            gnome-open "$1"
        fi
    
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    open_gnome()
    {
        local client
        client="$(gconftool-2 --get /desktop/gnome/url-handlers/mailto/command | cut -d ' ' -f 1)"
        case "$client" in *thunderbird*|*icedove*)
            run_thunderbird "$client" "$1"
        esac
    
        if gio help open 2>/dev/null 1>&2; then
            DEBUG 1 "Running gio open \"$1\""
            gio open "$1"
        elif gvfs-open --help 2>/dev/null 1>&2; then
            DEBUG 1 "Running gvfs-open \"$1\""
            gvfs-open "$1"
        else
            DEBUG 1 "Running gnome-open \"$1\""
            gnome-open "$1"
        fi
    
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    
    open_lxqt()
    {
        local client
        local desktop
        desktop="$(qtxdg-mat def-email-client 2>/dev/null)"
        client="$(desktop_file_to_binary "$desktop")"
        echo "$client" | grep -E 'thunderbird|icedove' > /dev/null 2>&1
        if [ $? -eq 0 ] ; then
            run_thunderbird "$client" "$1"
        fi
    
        if qtxdg-mat open --help 2>/dev/null 1>&2; then
            qtxdg-mat open "$1"
        else
            exit_failure_operation_impossible "no method available for opening '$1'"
        fi
    
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    
    open_xfce()
    {
        DEBUG 1 "Running exo-open \"$1\""
        exo-open "$1"
    
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    open_envvar()
    {
        old_ifs="$IFS"
        IFS=:
        for i in $MAILER; do
    	    IFS="$old_ifs"
    
    	    eval "$i" '"$1"'
    
    	    if [ $? -eq 0 ]; then
    	        exit_success
    	    fi
        done
    
        exit_failure_operation_failed
    }
    
    open_flatpak()
    {
        gdbus call --session \
            --dest org.freedesktop.portal.Desktop \
            --object-path /org/freedesktop/portal/desktop \
            --method org.freedesktop.portal.OpenURI.OpenURI \
            "" "$1" {}
    
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    }
    
    open_generic()
    {
        local client
        local desktop
        desktop="$(xdg-mime query default "x-scheme-handler/mailto")"
        client="$(desktop_file_to_binary "$desktop")"
        case "$client" in *thunderbird*|*icedove*)
            run_thunderbird "$client" "$1"
        esac
    
        xdg-open "$1"
        exit $?
    }
    
    url_encode()
    {
    # The shell needs the default internal field separator
    # otherwise it would search for $utf8 as a command in whole.
    IFS=" "
    str="$(echo "$1" | $utf8)"
    local ORIG_LANG ORIG_LC_ALL
    ORIG_LANG="$LANG"
    ORIG_LC_ALL="$LC_ALL"
    LANG=C
    LC_ALL=C
    result=$(echo "$str" | awk '
        BEGIN {
            for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
            e = ""
            linenr = 1
        }
        {
            if ( linenr++ != 1 ) {
                e = e "%0D%0A"
            }
            for ( i=1; i<=length ($0); ++i ) {
                c = substr ($0, i, 1)
                if ( ord [c] > 127 ) {
                    e = e "%" sprintf("%02X", ord [c])
                } else if ( c ~ /[@a-zA-Z0-9.\-\\\/]/ ) {
                    e = e c
                } else {
                    e = e "%" sprintf("%02X", ord [c])
                }
            }
        }
        END {
            print e
        }
    ')
    LANG="$ORIG_LANG"
    LC_ALL="$ORIG_LC_ALL"
    }
    
    options=
    mailto=
    utf8="iconv -t utf8"
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift
    
        case "$parm" in
          --utf8)
            utf8="cat"
            ;;
    
          --to)
            if [ -z "$1" ] ; then
                exit_failure_syntax "email address argument missing for --to"
            fi
            url_encode "$1"
            options="${options}to=${result}&"
            shift
            ;;
    
          --cc)
            if [ -z "$1" ] ; then
                 exit_failure_syntax "email address argument missing for --cc"
            fi
            url_encode "$1"
            options="${options}cc=${result}&"
            shift
            ;;
    
          --bcc)
            if [ -z "$1" ] ; then
                exit_failure_syntax "email address argument missing for --bcc"
            fi
            url_encode "$1"
            options="${options}bcc=${result}&"
            shift
            ;;
    
          --subject)
            if [ -z "$1" ] ; then
                exit_failure_syntax "text argument missing for --subject option"
            fi
            url_encode "$1"
            options="${options}subject=${result}&"
            shift
            ;;
    
          --body)
            if [ -z "$1" ] ; then
                exit_failure_syntax "text argument missing for --body option"
            fi
            url_encode "$1"
            options="${options}body=${result}&"
            shift
            ;;
    
          --attach)
            if [ -z "$1" ] ; then
                exit_failure_syntax "file argument missing for --attach option"
            fi
            check_input_file "$1"
            file="$(xdg_realpath "$1")" # Normalize path
            if [ -z "$file" ] || [ ! -f "$file" ] ; then
                exit_failure_file_missing "file '$1' does not exist"
            fi
    
            url_encode "$file"
            options="${options}attach=${result}&"
            shift
            ;;
    
          -*)
            exit_failure_syntax "unexpected option '$parm'"
            ;;
    
          mailto:*)
            mailto="$parm"
            ;;
    
          *@*)
            url_encode "$parm"
            if [ -z "${mailto}" ] ; then
                mailto="mailto:${result}?"
            else
                options="${options}to=${result}&"
            fi
            ;;
    
          *)
            exit_failure_syntax "unexpected argument '$parm'"
            ;;
        esac
    done
    
    if [ -z "${mailto}" ] ; then
        # TO address is optional
        mailto="mailto:?"
    fi
    
    case $mailto in
          *\?)
            mailto="${mailto}${options}"
            ;;
    
          *\?*)
            mailto="${mailto}&${options}"
            ;;
    
          *)
            mailto="${mailto}?${options}"
            ;;
    esac
    
    # Strip trailing ? and &
    mailto="$(echo "${mailto}"| sed 's/[?&]$//')"
    
    # Shouldn't happen
    [ x"${mailto}" != x"" ] || exit_failure_syntax
    
    if command -v xdg-email-hook.sh > /dev/null; then
        xdg-email-hook.sh "${mailto}"
        if [ $? -eq 0 ]; then
            exit_success
        else
            exit_failure_operation_failed
        fi
    fi
    
    detectDE
    
    if [ x"$DE" = x"" ]; then
        DE=generic
    fi
    
    if [ x"$MAILER" != x"" ]; then
        DE=envvar
    fi
    
    case "$DE" in
        envvar)
        open_envvar "${mailto}"
        ;;
    
        kde)
        open_kde "${mailto}"
        ;;
    
        gnome)
        open_gnome "${mailto}"
        ;;
    
        gnome3|cinnamon|lxde|mate|deepin)
        open_gnome3 "${mailto}"
        ;;
    
        lxqt)
        open_lxqt "${mailto}"
        ;;
    
        xfce)
        open_xfce "${mailto}"
        ;;
    
        flatpak)
        open_flatpak "${mailto}"
        ;;
    
        generic|enlightenment)
        open_generic "${mailto}"
        ;;
    
        *)
        exit_failure_operation_impossible "no method available for opening '${mailto}'"
        ;;
    esac
    

    1

Environment

  1. Extension

    0.3.9

  2. VSC

    rpm -qa returns code-1.101.0-1749655297.el8.x86_64, whereas dnf5 info returns:

    Installed packages
    Name            : code
    Epoch           : 0
    Version         : 1.101.0
    Release         : 1749655297.el8
    Architecture    : x86_64
    Installed size  : 415.1 MiB
    Source          : code-1.101.0-1749655297.el8.src.rpm
    From repository : <unknown>
    URL             : https://code.visualstudio.com/
    Vendor          : Microsoft Corporation
  3. OS

    PRETTY_NAME="Fedora Linux 42 (KDE Plasma Desktop Edition)"
    CPE_NAME="cpe:/o:fedoraproject:fedora:42"

Footnotes

    1.   #!/usr/bin/env sh
        dnf5 provides $(command -v xdg-email)
      
    2. xdg-utils-1.2.1-3.fc42.noarch : Basic desktop integration functions
      Repo         : fedora
      Matched From : 
      Filename     : /usr/bin/xdg-email
      

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions