#!/bin/bash
# shellcheck disable=SC1091,2089,2090
#(c) Copyright Barry Kauler 2010, bkhome.org
#2010 Lesser GPL licence v2 (/usr/share/doc/legal/lgpl-2.1.txt)
#100308 first version of script, open and wep networks only.
#100309 supports wpa. 100310 bug fixes.
#100312 wireless code cleanup, bug fixes.
#100313 wpa_supplicant, try different values for ap_scan.
#100313 added support for ndiswrapper.
#100314 bugfixes.
#100320 fix if essid has spaces. Extra logging. handle special cases.
#100321 fuCNT fix. 100323 FLAGERR fix.
#100324 Start firewall, change from button to checkbox.
#100325 DHCPCDFIX option for wired.
#100405 append last 10 lines of /var/log/messages to error log.
#100413 attempt restart blinky_tray.
#100513 more delay, repeat scan attempt.
#100608 k2.6.27.47: anomaly, 'readlink /sys/class/net/$INTERFACE/device/driver' returns 'ath5k_pci' but module is 'ath5k'.
#100608 have changed most xmessage displays to yaf-splash.
#100703 extra flush seems to be needed when release interface.
#101029 fix when no wireless networks found.
#101118 bugfix, so network-disconnect works.
#110203 improve scanning.
#110505 support sudo for non-root user.
#120107 gtkdialog3 to gtkdialog4, new 'Profile' frame in main window, new profiles help window.
#120204 rodin.s: internationalized.
#120222 small change to 'connect now' button.
#120323 replace remaining 'xmessage' with 'pupmessage'.
#120324 fix syntax error gettext.
#130221 vertical scrollbar if more than 9 wireless networks found.
#131227 zigbert: gui (gtkdialog) improvements.
#170329 rerwin: set as current network exec, retaining previous exec name.
#170402 change check for dhcpcd success, to rely on dhcpcd exit code.
#170514 add message about already running.
#170529 fix delete buttons to handle ' or " in SSID or password.
#170619 display networks in order of signal quality.
#170924 add short sleep to allow time for dhcpcd to write to resolv.conf.
#180706 v2.0: Accommodate large network list, by omitting unneeded iwlist lines and limiting search for 'Scan completed'.
#190209 v2.1.1: Increase wait for ethtool link detected, to 6 secs total).
#190216 v2.2: Correct 'already running' check; correct support of long SSIDs truncated for display; avoid wait after link timeout; move 'current exec' logic, so exec change avoided if main window aborted (X); update 'make default' message.
#190223 v2.2.1: Avoid exec change on exiting if connect/disconnect and interface buttons not used; add 'note' regarding connection not started by SNS.
#190525 v2.3: Add version to main window; re-check SNS running, in case slow to terminate; for interface change, kill current connection.
#200412 v2.3.1: Increase wait for ethtool link detected, to 15 secs.
#200521 v2.3.2: Correct damage to SNS_error dialog window title syntax; export version.
#201001 v2.3.3: Change SRLINES to handle (erroneously) positive signal level for sort.
#201017 v2.4: Change module detection to handle multiple aliases for a device and driver preferences (in rc.network & build_udevmodulelist).
#201110 v2.4.1: Test for connection with udhcpc (peasywifi), as well as dhcpcd; make SNS current before networkdisconnect.
#210601 v2.4.2: Add wireless rescan button.
#210130 Correct setting of DHCPCDFIX.
#210201 Reorganized code into segments.
#210202 Replace deprecated ifconfig and route with busybox-compatable subset of ip (assuming nonfunctional -oneline); replace iwconfig with iw; replace pidof with 'ps -C'; replace iwlist scan with 'iw scan'; use signal level instead of quality for strength icon.
#210204 Replace busybox ps+grep with 'ps -C'+grep for dhcpcd & udhcpc.
#210205 Shorten delays after bringing link up.
#210206 Ensure driver names placed in udevmodulelist for immediate use.
#210207 Change WEP support to use wpa_supplicant; add nl80211 as default wpa driver.
#210208 Prepend new connection, so newest profile tried first at boot-up; replace profile only for same SSID and MAC address; use 'read' to extract scan content.
#210209 add message and no interface buttons if no interface detected; ensure all active interfaces down before starting new interface; kill wpa_supplicant when bringing interface down.
#210210 Obtain bus type from /sys/class/net/ instead of modinfo aliases, which may support multiple buses; simplify truncation of interface descriptions (info).
#210211 Show correct interface (or space) in profile tab.
#210212 BK: /tmp/sns_interface_success no longer used (derived from easyos 190215).
#210213 Remove wpa_supplicant.conf for profile being deleted.
#210226 Resolve shellcheck issues.
#210623 v3.0 (not annotated) Support hidden networks; remove unnecessary user selection of encryption protocols; use 'read' to extract fields from one-line entries; change profile format to omit unused fields; add wireless network name to status message; use eval_gettext where appropriate; rework connection wait splash messaging.
#210703 v3.1 Accommodate EasyOS which does not use pup_event_backend_modprobe for module loading (udev rule, build_udevmodulelist, rc.network); change yaf-splash to gtkdialog-splash.
#211002 v3.2 Add 'wired' profiles to top of connections list (as well as 'wireless' profiles); add splash message if 'iw' command not installed.
#211215 v3.3 Accommodate spoofed gadget (USB-tethered smartphone) MAC addresses; add spoofing if macchanger installed; group same-MAC connections, so list shows connection priority; correct driver & interface searches and selection; override default dhcpcd response timeout if not already in conf file, to compensate for router possibly slowing due to MAC spoofing.
#211231 v3.3 Replace ethtool with ip-show test for LOWER_UP.
#220123 v3.3 Add iw-missing message to wireless configure dialog; remove unnecessary iw splash message (211002) and avoid iw-missing error messages, for clean support of wired interfaces when 'iw' is missing.
#220704 v3.3.1 rc.network updated. 
#230919 BK: /usr/local/simple_network_setup/rc.network renamed to rc.snsnetwork; simplified already-running check.
#230919 BK: For EasyOS compatability, removed "Barry's ..." from window title; removed "Puppy" from messages.
#230920 BK: chmod 600 /etc/simple_network_setup/connections so non-root apps cannot see it.
#230924 v3.3.2 BK: Fix for tainted module, for which modinfo doesn't work.
#230930 v3.4 For gtkdialog '-p SNS_' argumemt, use long option for connectwizard_exec to find; running check improved; use profile security key if none entered; rc.snsnetwork updated; build_modulelist updated.
#231106 Use gtk+ 2 version of gtkdialog, to work around gtk+ 3 sizing issue.
#240216 Add frisbee to check for dhcpcd running.
#240305 Remove tests of /etc/resolv.conf, dhcpcd, udhcpc in find_usable_interfaces.
#240307 Reset resolv.conf before dhcpcd.
#240309 Add message if active connection by another network manager.
#240403 v3.5 Reimplement registering change to sns upon connect/disconnect
# to accommodate switching from connman or peasywifi, which starts netmon_wce.
#240418 v3.5.1 Improve already-running response to avoid subsequent connectwizard prompt and to kill possible remaining xdialog.
#240605 v3.5.2 Add use of gtk2dialog by all dialogs; add GTKDIALOG_BUILD to utilize gtk2 theming.

export VERSION='3.5.2'  #UPDATE this with each release!

export TEXTDOMAIN=simple_network_setup
export OUTPUT_CHARSET=UTF-8
. gettext.sh

[ "$(whoami)" != "root" ] && exec sudo -A "${0}" "${@}" #110505

#Running? #170514... #190216 #190525
XDLGPID="$(pgrep -fd ' ' '\--wmclass sns')" #240418
[ -n "$XDLGPID" ] && kill "$XDLGPID" #240418
WAITCNT=4
while pgrep -x 'sns' | grep -qwv "$$"; do #240418
    if [ $((WAITCNT--)) -le 0 ]; then
        Xdialog --left --wmclass "sns" --title "$(gettext 'Simple Network Setup')"  --backtitle "\n$(gettext 'Simple Network Setup cannot start now because it is already active.')" --icon /usr/local/lib/X11/pixmaps/error.xpm --msgbox "\n$(gettext 'Please use the active SNS session or\nterminate it and start SNS again.')\n" 0 70
        RC="$?"; [ "$RC" -le 2 ] && RC=3; exit "$RC" #Avoid connectwizard prompt #240418
    fi
    sleep 0.5
done

GTKDIALOG='gtkdialog' #231106...
which gtk2dialog >/dev/null \
  && GTKDIALOG='gtk2dialog' && GTKDIALOG_BUILD=GTK2 #force gtk2 theming #240605

. /usr/local/simple_network_setup/macaddress_spoofing_functions #211215

#each line of /etc/simple_network_setup/connections has everything needed about a connection:
#(please ignore spaces, put here for readability only)
#        1                 2          3         4       5                                       6         7          8                 9        10                         11
#format: MACADDRESS       |IF_INTTYPE|IF_DRIVER|IF_BUS |IF_INFO                                |DHCPCDFIX|CELL_ESSID|CELL_ADDRESS     |SEC_MGMT|SEC_KEY                   |WPA_DRIVER|
#ex:     00:17:36:84:E5:1A|Wired     |sky2     |pci    |Marvell Yukon 2 Gigabit Ethernet driver|         |belkin54g |00:17:3F:68:33:7E|WPA-PSK |000102030405060708090a0b0c|nl80211   |
SEC_KEY_FIELD=10 #230930

find_interface_driver() {
    FINDTYPE="$(readlink "/sys/class/net/$INTERFACE/device/driver")"
    IF_DRIVER=${FINDTYPE##*/} #basename - ex: ath5k
    IF_BUS="$(grep -o '/bus/[^/]*' <<< "$FINDTYPE" | cut -f 3 -d /)" #210210
    IF_INFO="$(sed -n 's%^description: *%%p' <<< "$(modinfo "$IF_DRIVER" 2>/dev/null)")" #210210
    if [ -z "$IF_INFO" ];then #20230924 fix for tainted module, modinfo doesn't work.
     IF_INFO="$(gettext 'No description available')"
    elif [ "$IF_DRIVER" = "ndiswrapper" ]; then
# shellcheck disable=SC2034
        WINDRVR="$(ndiswrapper -l | grep '^[a-zA-Z0-9]' | cut -f 1 -d ' ')"
        IF_INFO="$(eval_gettext "MS Windows driver '\$WINDRVR'")"
    fi
    if [ ! -e "/tmp/simple_network_setup/udevmodulelist/$IF_DRIVER" ]; then #210206...
        mkdir -p /tmp/simple_network_setup/udevmodulelist
        echo "$IF_DRIVER" > "/tmp/simple_network_setup/udevmodulelist/$IF_DRIVER"
    fi
} #find_interface_driver

collect_interface_data() {
    #want to manipulate the info string for display purposes...
    local CNTLINE=-1; local CLEANINFO #210210...
    CLEANINFO="$(tr '&|"<>[]' ' ' <<< "$IF_INFO" | tr -s ' ')" #filter out chars that mess up xml.
    for ONEWORD in $CLEANINFO; do
        CNTLINE="$((CNTLINE + 1 + ${#ONEWORD}))"
        [ "$CNTLINE" -gt 60 ] && break
    done
    IF_INFO="${CLEANINFO:0:$CNTLINE}"

    if [ -d "/sys/class/net/${INTERFACE}/wireless" ] \
      || grep -q "${INTERFACE}:" /proc/net/wireless ; then
        IF_INTTYPE='Wireless'
        IF_INTTYPE_XLATED="$(gettext 'Wireless')"
    else
        IF_INTTYPE='Wired'
        IF_INTTYPE_XLATED="$(gettext 'Wired')"
    fi

    #accumulate the results into columns...
    ALL_IF_INTERFACE="${ALL_IF_INTERFACE}|${INTERFACE}"
    ALL_IF_INTTYPE="${ALL_IF_INTTYPE}|${IF_INTTYPE_XLATED}"
    ALL_IF_DRIVER="${ALL_IF_DRIVER}|${IF_DRIVER}"
    ALL_IF_BUS="${ALL_IF_BUS}|${IF_BUS:=x}" #If null, replace with x #210210
    ALL_IF_INFO="${ALL_IF_INFO}|${IF_INFO:=x}" #210210
    INTERFACEBUTTONS="${INTERFACEBUTTONS} 
  <button><label>${INTERFACE}</label><action type=\"exit\">Interface_${INTERFACE}</action></button>"
    #save all data about each interface on one line...
    #ex: wlan1|Wireless|ath5k|pci|Support for 5xxx series of Atheros 802.11 wireless LAN cards
    echo "${INTERFACE}|${IF_INTTYPE}|${IF_DRIVER}|${IF_BUS}|${IF_INFO}" >> /tmp/sns_interfaces
} #collect_interface_data

build_interface_display_list() {
    ALL_IF_INTERFACE="$(tr '|' '\n' <<< "${ALL_IF_INTERFACE#|}")"
    ALL_IF_INTTYPE="$(tr '|' '\n' <<< "${ALL_IF_INTTYPE#|}")"
    ALL_IF_DRIVER="$(tr '|' '\n' <<< "${ALL_IF_DRIVER#|}")"
    ALL_IF_BUS="$(tr '|' '\n' <<< "${ALL_IF_BUS#|}")"
    ALL_IF_INFO="$(tr '|' '\n' <<< "${ALL_IF_INFO#|}")"

    INTERFACEDESCR="    <hbox border-width=\"7\" spacing=\"10\">
      <text use-markup=\"true\"><label>\"<b>$(gettext 'Interface')</b>
$ALL_IF_INTERFACE\"</label></text>
      <text use-markup=\"true\"><label>\"<b>$(gettext 'Type')</b>
$ALL_IF_INTTYPE\"</label></text>
      <text use-markup=\"true\"><label>\"<b>$(gettext 'Driver')</b>
$ALL_IF_DRIVER\"</label></text>
      <text use-markup=\"true\"><label>\"<b>$(gettext 'Bus')</b>
$ALL_IF_BUS\"</label></text>
      <text use-markup=\"true\"><label>\"<b>$(gettext 'Description')</b>
$ALL_IF_INFO\"</label></text>
    </hbox>"
} #build_interface_display_list

find_usable_interfaces() {
    #test if connected to internet...
    FLAGINTERNETSTATUS='no'
    WORKINGIF=''
    for ONEIF in $(ip link show | grep -B 1 'link/ether' | grep -w 'UP' | cut -f 2 -d : | tr -d '\n'); do #210202
        WORKINGIF="${WORKINGIF}${ONEIF} "
        FLAGINTERNETSTATUS='yes'
    done
    WORKINGIF="${WORKINGIF% }"
    if [ "$FLAGINTERNETSTATUS" = "yes" ]; then
# shellcheck disable=SC2034 # Missed, but MSGWIF used in eval_gettext.
        MSGWIF="<b>$WORKINGIF</b>"
        if [ "$(wc -w <<< "$WORKINGIF")" -gt 1 ]; then
            MSGSTATUS="$(eval_gettext "Current Internet connections are on interfaces \${MSGWIF}")"
        else
            WORKSSID="$(iw dev "$WORKINGIF" link 2>/dev/null | sed -n 's%.*SSID: \(.*\)%\1%p')" #220123
            if [ -n "$WORKSSID" ]; then
# shellcheck disable=SC2034 # Missed, but MSGWSSID used in eval_gettext.
                MSGWSSID="<b>${WORKSSID:0:20}</b>"
                MSGSTATUS="$(eval_gettext "Current Internet connection is on interface \${MSGWIF} network \${MSGWSSID}")"
            else
                MSGSTATUS="$(eval_gettext "Current Internet connection is on interface \${MSGWIF}")"
            fi
        fi
        COLOR_BG='#80CE7F'; COLOR_FG='#235123'
    else
        MSGSTATUS="$(gettext 'Currently no SNS-controlled Internet connection')"
        COLOR_BG='#CE837F'; COLOR_FG='#512323'
    fi

    grep -qswv 'sns' /root/.connectwizardrc \
      && [ "$FLAGINTERNETSTATUS" = "yes" ] \
      && OTHERMGRMSG="  $(gettext '<b>Note:</b> The current connection(s) was/were started by another network tool and will be disconnected if an interface button is clicked.')" \
      || OTHERMGRMSG='' #240309
    CLICKMSG="$(/usr/lib/gtkdialog/xml_info fixed "internet_connect.svg" 60 "$(gettext 'These network interfaces have been identified on your computer. Click a button to configure the interface for use.')${OTHERMGRMSG}")" #240309
    #100313 add a button for loading a Windows driver...
    if ! grep -q 'ndiswrapper' <<< "$ALL_IF_DRIVER" \
      && modprobe -n ndiswrapper 2>/dev/null; then
        CLICKMSG="$(/usr/lib/gtkdialog/xml_info fixed "internet_connect.svg" 60 "$(gettext "These network interfaces have been identified on your computer. Click a button to configure the interface for use, or click 'Windows' button if you want to install and use a MS Windows driver.")${OTHERMGRMSG}")" #240309
        INTERFACEBUTTONS="${INTERFACEBUTTONS} 
  <button><label>Windows</label><action type=\"exit\">Interface_Windows</action></button>"
    elif [ -z "$ALL_IF_DRIVER" ]; then #210209...
        CLICKMSG="$(/usr/lib/gtkdialog/xml_info fixed "internet_connect.svg" 60 "$(gettext 'No network interfaces have been identified on your computer.')")"
        INTERFACEDESCR=''
        INTERFACEBUTTONS='<text width-request="5"><label>""</label></text>'
    fi
} #find_usable_interfaces

connect_button_splash() { #170505...
# shellcheck disable=SC2317 #connect_button_splash called by gtkdialog program
    gtkdialog-splash -bg orange -close never -fontsize large -text "$(gettext 'Please wait...')" >/dev/null &
# shellcheck disable=SC2317
    echo $! >/tmp/sns_splash_pid
}
export -f connect_button_splash #170505 end

build_connection_display_list() {
    set_active_interface_macaddresses #211215
    echo "" >/tmp/sns_CNT_P
    echo "<b>$(gettext 'Interface')</b>" >/tmp/sns_I_P
    echo "<b>$(gettext 'Type')</b>" >/tmp/sns_T_P
    echo "<b>$(gettext 'Driver')</b>" >/tmp/sns_D_P
    echo "<b>$(gettext 'Bus')</b>" >/tmp/sns_B_P
    echo "<b>$(gettext 'Hardware')</b>" >/tmp/sns_M_P
    echo "" >/tmp/sns_S_P; echo "" >/tmp/sns_SEC_P
    if grep -q '^..:.*|Wireless|' /etc/simple_network_setup/connections; then
        echo "<b>$(gettext 'Network')</b>" >/tmp/sns_S_P
        echo "<b>$(gettext 'Security')</b>" >/tmp/sns_SEC_P
    else
        echo "       " >/tmp/sns_S_P
        echo "        " >/tmp/sns_SEC_P
    fi
    echo "" >/tmp/sns_DEL_BTN
    CNT=0
    while read -r ONECONNECTION; do
        IFS='|' read -r MAC_P TYPE_P DRIVER_P BUS_P _ _ SSID_P _ SEC_P _ <<< "$ONECONNECTION" #210211
        if [ "${#MAC_P}" -ge 17 ]; then #ignore old profile format
            IF_CURR_REAL_MACS="$(grep -E "_${MAC_P}$" <<< "$ACTIVE_INTERFACE_MACADDRESSES")" #211215
            [ -z "$IF_CURR_REAL_MACS" ] \
              && IF_CURR_REAL_MACS=" _${MAC_P}_${MAC_P}" #space before first '_', for "no interface" #211215
            ((++CNT))
            echo "<b>$CNT</b>" >> /tmp/sns_CNT_P
            INTERFACE_P="$(cut -f 1 -d _ <<< "$IF_CURR_REAL_MACS")" #211215
            echo "$INTERFACE_P" >> /tmp/sns_I_P
            if [ "$TYPE_P" = "Wireless" ]; then
# shellcheck disable=SC2005 #need newline by echo
                echo "$(gettext 'Wireless')" >> /tmp/sns_T_P
            else
# shellcheck disable=SC2005 #need newline by echo
                echo "$(gettext 'Wired')" >> /tmp/sns_T_P
            fi
            echo "$DRIVER_P" >> /tmp/sns_D_P
            echo "$BUS_P" >> /tmp/sns_B_P
            MAC_P="$(cut -f 2 -d _ <<< "$IF_CURR_REAL_MACS")" #211215
            [ -z "$MAC_P" ] && MAC_P="$(cut -f 3 -d _ <<< "$IF_CURR_REAL_MACS")" #spoofed gadget #211215
            echo "$MAC_P" >> /tmp/sns_M_P
            if [ "$TYPE_P" = "Wireless" ]; then
                echo "$SSID_P" >> /tmp/sns_S_P
                [ -z "$SEC_P" ] && SEC_P="none"
                echo "$SEC_P" >> /tmp/sns_SEC_P
            else
                echo " " >> /tmp/sns_S_P
                echo " " >> /tmp/sns_SEC_P
            fi
            if [ "$CNT" -gt 12 ]; then
                echo "<i>more...</i>"  >> /tmp/sns_I_P
                break
            fi
            xCONNECTION="$(tr \" . <<< "$ONECONNECTION")" #170529
            WPACONFSFX="$(cut -f 1,7 -d '|' <<< "$xCONNECTION" | sed 's/\(.*\)|\(.*\)/\2-\1/')" #210213
            echo "<button><label>${CNT}</label>
            <action>grep -v \"${xCONNECTION}\" /etc/simple_network_setup/connections > /tmp/sns_action1</action>
            <action>mv -f /tmp/sns_action1 /etc/simple_network_setup/connections</action>
            <action>rm -f /etc/simple_network_setup/wpa_supplicant.conf-\"$WPACONFSFX\"</action>
            <action type=\"exit\">EXITRESTART></action></button>" >> /tmp/sns_DEL_BTN #170529 #210213
        fi
    done <<< "$ALL_CONNECTION_PROFILES" #211215
} #build_connection_display_list

build_display_connect_button() {
    if [ "$FLAGINTERNETSTATUS" = "yes" ]; then
        DISCONNECT_EXIT='DISCONNECTEXITNOW' #190223...
        grep -qswv 'sns' /root/.connectwizardrc \
          && DISCONNECT_EXIT='DISCONNECTRESTART' #240403
        CONNECTBTN_XML="<button>$(/usr/lib/gtkdialog/xml_button-icon internet_connect_no.svg)<label>$(gettext 'Disconnect Now')</label><action type=\"exit\">${DISCONNECT_EXIT}</action></button>" #201110 #240403
    else
        CONNECTBTN_XML="<button>$(/usr/lib/gtkdialog/xml_button-icon internet_connect_yes.svg)<label>$(gettext 'Connect Now')</label><action>connect_button_splash</action><action>/usr/local/simple_network_setup/rc.snsnetwork start & </action><action type=\"exit\">CONNECTEXITNOW</action></button>" #170505 190223 201110 #240403
    fi
    DISCONNECT_XML='' #190223
    grep -qswv 'sns' /root/.connectwizardrc \
      && [ "$FLAGINTERNETSTATUS" = "yes" ] \
      && DISCONNECT_XML="$(gettext '<b>Note:</b> The current connection was started by another network tool.  To control it with SNS, disconnect now, then re-connect or choose an interface.')" #190223
    SPOOFING_XML=''  #211215...
    macaddress_spoofing_enabled \
      && SPOOFING_XML="$(gettext '<b>Note:</b> Active interface hardware address is spoofed.')"
    PROFILE_XML="$(/usr/lib/gtkdialog/xml_info fixed "internet_connect.svg" 60 "$(gettext 'Connection profiles have previously been created by SNS.')" "$(gettext "The <b>Connect</b> button will try to establish an internet connection by any of the available profiles.")" "${DISCONNECT_XML}" "${SPOOFING_XML}")
 <hbox border-width=\"7\" spacing=\"10\"><text use-markup=\"true\"><label>\"$(cat /tmp/sns_CNT_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_I_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_T_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_D_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_B_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_M_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_S_P)\"</label></text><text use-markup=\"true\"><label>\"$(cat /tmp/sns_SEC_P)\"</label></text></hbox>
 <hbox><text><label>$(gettext 'Delete:')</label></text>$(cat /tmp/sns_DEL_BTN)</hbox>
" #190223
} #build_display_connect_button

build_and_display_main_window() {
    if [ "$PROFILE_XML" ]; then
        PAGE_NR=0
    else
        PAGE_NR=1
        PROFILE_XML="$(/usr/lib/gtkdialog/xml_info scale "internet_connect.svg" 60 "$(gettext '<b>No profiles</b>')" "$(gettext 'Set up an interface first, and when connected, a profile will be built for next run.')")"
    fi

    #bring up the main window...
    SNS_main='
<window title="SNS '$VERSION' - '$(gettext "Simple Network Setup")'" icon-name="gtk-network">
<vbox spacing="0" space-expand="true" space-fill="true">
  <eventbox name="status" space-expand="false" space-fill="false">
    <text name="status_text" wrap="false" height-request="20" use-markup="true" space-expand="true" space-fill="true"><label>"'${MSGSTATUS}'"</label></text>
  </eventbox>
  <text height-request="7" space-expand="false" space-fill="false"><label>""</label></text>
  <vbox spacing="5" space-expand="true" space-fill="true">
    <notebook tab-pos="2" page="'$PAGE_NR'" labels="'$(gettext 'Profiles')'|'$(gettext 'Interfaces')'" space-expand="true" space-fill="true">
      <frame '$(gettext 'Profiles')'>
        '${PROFILE_XML}'
        <text height-request="5" space-expand="false" space-fill="false"><label>""</label></text>
      </frame>
      <frame '$(gettext 'Interfaces')'>
        '${CLICKMSG}'
        '${INTERFACEDESCR}'
        <hbox space-expand="false" space-fill="false">'${INTERFACEBUTTONS}'</hbox>
        <text height-request="5" space-expand="false" space-fill="false"><label>""</label></text>
      </frame>
    </notebook>
    <hbox space-expand="false" space-fill="false">
      <button>
        <label>'$(gettext "Help")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon help)"'
        <action>/usr/local/simple_network_setup/help_profiles &</action>
      </button>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext 'Network Information')'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon info)"'
        <action>ipinfo & </action>
      </button>
      <text space-expand="true" space-fill="true"><label>""</label></text>
      '${CONNECTBTN_XML}'
      <button space-expand="false" space-fill="false">
        '"$(/usr/lib/gtkdialog/xml_button-icon quit)"'
        <label>'$(gettext 'Quit')'</label>
        <action type="exit">QUIT</action>
        </button>
    </hbox>
  </vbox>
</vbox>
</window>' #170505 190217
    export SNS_main

    echo 'style "status"
{
  fg[NORMAL] = "'$COLOR_FG'"
  bg[NORMAL] = "'$COLOR_BG'"
}
widget "*status*" style "status"' > /tmp/gtkrc_sns
    export GTK2_RC_FILES=/tmp/gtkrc_sns:/root/.gtkrc-2.0
    . /usr/lib/gtkdialog/xml_info gtk #build bg_pixmap for gtk-theme
    RETSTRING="$("$GTKDIALOG" --program=SNS_main)" ###main window### #170505 #231106
} #build_and_display_main_window

load_windows_driver() {
    if [ -d /etc/ndiswrapper ]; then
        if ls /etc/ndiswrapper/*/*.inf >/dev/null 2>&1; then
            modprobe ndiswrapper
            sleep 1
            exec sns
        fi
    fi
    INFFILE=$(/usr/lib/gtkdialog/file_chooser "$(gettext 'SNS: Install MS Windows driver')" \
 "$(gettext "Select the '.inf' file of the required MS Windows driver. If on a CD, you will have to mount it, then navigate to where the '.inf' file is. Note, choose a Windows XP driver if available...")")
    if [ -f "$INFFILE" ]; then
        case "$INFFILE" in
          *.[iI][nN][fF]) 
            FLAGND=""
            if ndiswrapper -i "$INFFILE"; then #installs driver at /etc/ndiswrapper.
                if ndiswrapper -l; then #tests the driver
                    modprobe ndiswrapper && FLAGND="ok"
                    [ "$FLAGND" != "ok" ] && rmmod ndiswrapper 2>/dev/null
                fi
            fi
            [ "$FLAGND" != "ok" ] && rm -rf /etc/ndiswrapper
            [ "$FLAGND" != "ok" ] && /usr/lib/gtkdialog/box_ok "SNS" error "$(gettext 'Windows driver does not seem to work, it has been uninstalled')"
            [ "$FLAGND" = "ok" ] && sleep 1
           ;;
          *) 
            /usr/lib/gtkdialog/box_ok "SNS" error "$(eval_gettext "ERROR, \$INFFILE is not a .inf file")"
           ;;
        esac
    fi
    exec sns
} #load_windows_driver
 
ensure_interface_is_down() {
    if [ -n "$WORKINGIF" ]; then  #190525...
        for ONEIF in $WORKINGIF; do #210209...
            if ip link show "$ONEIF" | grep -wq 'UP'; then #210202
                gtkdialog-splash -bg orange -placement center -text "$(eval_gettext "Please wait, bringing down '\$ONEIF'...")" >/dev/null &
                PIDX1=$!
                kill_wpa_supplicant #210209
                iw dev "$ONEIF" info 2>/dev/null | grep -qw 'ssid' \
                  && iw dev "$ONEIF" disconnect #210202
                ip link set "$ONEIF" down #210202
                dhcpcd --release "$ONEIF" 2>/dev/null
                ip route flush dev "$ONEIF" #100703
                sleep 1
                kill $PIDX1 2>/dev/null
            fi #190525 end
        done
    fi
} #ensure_interface_is_down

extract_interface_data() {
    fPATTERN='^'"${INTERFACE}"'|'
    IFS='|' read -r _ IF_INTTYPE IF_DRIVER IF_BUS IF_INFO <<< "$(grep "$fPATTERN" /tmp/sns_interfaces)"
# shellcheck disable=SC2060
    MACADDRESS="$(ip link show "$INTERFACE" | grep -o 'link/ether [^ ]*' | cut -f 2 -d ' ')" #210202
} #extract_interface_data

perform_wireless_setup() {
    FLAGERR=
    while true; do #210601
        scan_for_wireless_networks #sets SCANRESULT
        if [ -z "$FLAGERR" ]; then #210201
            echo "STEP1c: ip link set $INTERFACE down" >> /tmp/sns_wireless_log #210202
            ip link set "$INTERFACE" down #100313 210202
            build_display_network_list

            #my wpa_supplicant only supports: wext hostap atmel wired ralink roboswitch
            case $IF_DRIVER in
              hostap*)   WPA_DRIVER="hostap" ;;
              rt61|rt73) WPA_DRIVER="ralink" ;;
              *)         WPA_DRIVER="nl80211,wext" ;; #210207
            esac

            build_display_radio_buttons
            build_and_display_wireless_setup_window #sets RETSTRING
            case "$(sed -n 's/^EXIT="\(.*\)"/\1/p' <<< "$RETSTRING")" in #210601...
              BUT_RESCAN) continue ;;
              BUT_GOBACK) exec sns ;;
              BUT_CONNECT) ;;
              *) exit ;;
            esac

            extract_data_for_selected_network
            if [ -z "$FLAGERR" ]; then
                complete_the_wireless_connection
            fi #end test exist security entries.
        fi #end test ip link set up #210202
        break
    done #210601

    if [ "$FLAGERR" ]; then
        build_and_display_wireless_error_window # sets RETSTRING
        grep '^EXIT' <<< "$RETSTRING" | grep -q 'BUT_GOBACK' && exec sns
    else
        #success!
        add_wireless_connection_profile_and_conf #211002
        build_and_display_wireless_success_window #sets RETSTR3
        if grep '^CHK_SNSDEF' <<< "$RETSTR3" | grep -q 'true'; then
            echo -e '#!/bin/sh\nexec sns' > /usr/local/bin/defaultconnect
        else
            echo -e '#!/bin/sh\nexec connectwizard' > /usr/local/bin/defaultconnect
        fi
        if grep '^CHK_FIREWALL' <<< "$RETSTR3" | grep -q 'true'; then
            "$FW_EXEC"
        fi
    fi
} #perform_wireless_setup

complete_the_wireless_connection() {
    RUNWPASUPP='no'
    FIXUP='1 1 2 0'
    [ "$IF_DRIVER" = "ndiswrapper" ] && FIXUP='2 1 0'
    fuCNT=$(wc -w <<< "$FIXUP")
    for ONEFIX in $FIXUP; do ###BIG FOR LOOP###
        show_wait_splash "$fuCNT"
        ((--fuCNT))
        [ "$CELL_ENCRYPTIONKEY" = "on" ] && configure_wpa_supplicant
        spoof_macaddress 'STEP1d: ' >> /tmp/sns_wireless_log #If using real MAC, spoof it #211215
        echo "STEP5a: ip link set $INTERFACE up" >> /tmp/sns_wireless_log #210202
        ip link set "$INTERFACE" up #210202
        sleep 4
        if [ "$RUNWPASUPP" = "yes" ]; then
            if run_wpa_supplicant; then
                WPA_SEC_MGMT="$(wpa_cli -i "$INTERFACE" status | grep 'key_mgmt=' | cut -f 2 -d =)"
            else
                [ "$fuCNT" -gt 0 ] \
                  && continue #try next FIXUP value. ###BIG FOR LOOP### #210202
                kill_wpa_supplicant_and_link
                FLAGERR=5
            fi #210202
        else #No security (null) #210202...
            if [ -z "$SEC_KEY" ]; then
                iw dev "$INTERFACE" connect "$CELL_ESSID" "$CELL_FREQUENCY" "$CELL_ADDRESS" \
                  || FLAGERR=4
            fi
        fi
        if [ ! $FLAGERR ]; then #210202 end
            wait_until_link_available
            if [ $FLAGERR ]; then
                kill_wireless_link
                [ "$CELL_ENCRYPTIONKEY" = "on" ] \
                  && [ "$fuCNT" -gt 0 ] \
                  && continue #try next FIXUP value. ###BIG FOR LOOP### #210202
            else
                run_dhcpcd
                if [ $FLAGERR ]; then
                    [ "$CELL_ENCRYPTIONKEY" = "on" ] \
                      && [ "$fuCNT" -gt 0 ] \
                      && continue #try next FIXUP value. ###BIG FOR LOOP### #210202
                    kill_wpa_supplicant_and_link
                fi #end test dhcpcd timeout.
            fi #end test access point.
        fi #end test wpa_supplicant timeout.
        break
    done #end for-loop. ###END BIG FOR LOOP###
    [ -n "$PIDX" ] && kill "$PIDX" 2>/dev/null #210201?
} #complete_the_wireless_connection

scan_for_wireless_networks() {
    if rfkill list wlan | grep -q 'Soft blocked: yes' ; then
        rfkill unblock wlan
    fi
    rm -f /tmp/sns_scan_radiobuttons
    rm -f /tmp/sns_scan_radiobuttons_shield
    rm -f /tmp/sns_scan_radiobuttons_strength
    rm -f /tmp/sns_scan_radiobuttons_address
    rm -f /tmp/sns_scan_rawoneline
    rm -f /tmp/sns_scan_oneline
    gtkdialog-splash -placement center -bg orange -text "$(gettext 'Please wait, scanning for wireless networks...')" >/dev/null &
    PIDXMSG=$!
    echo "Information about this interface:
 Interface: $INTERFACE  Driver: $IF_DRIVER  Bus: $IF_BUS  MacAddress: $MACADDRESS
 Description: $IF_INFO
 " > /tmp/sns_wireless_log
    iw dev "$INTERFACE" info 2>/dev/null | grep -qw 'ssid' && iw dev "$INTERFACE" disconnect #210202
    echo "STEP1a: ip link set $INTERFACE up" >> /tmp/sns_wireless_log #210202
    if ! ip link set "$INTERFACE" up >> /tmp/sns_wireless_log 2>&1; then #210202
        FLAGERR=1
    else
        if which iw >/dev/null 2>&1; then #220123
            sleep 0.1 #210205
            echo "STEP1b: iw dev $INTERFACE scan | grep -E (messages & labels)" >> /tmp/sns_wireless_log #180706 210202
# shellcheck disable=SC2034
            for I in 1 2 3 4 5; do #210205
                SCANRESULT="$(iw dev "$INTERFACE" scan | \
                  grep -E '^BSS |freq:|capability:|signal:|SSID:|DS Parameter set:|RSN:|Pairwise ciphers:|Authentication suites:|WPA:')" ###SCANNING### 110203 210203 210202
                [ -n "$SCANRESULT" ] && break #210202
                sleep 1 #210205
            done #210205
            echo "$SCANRESULT" >> /tmp/sns_wireless_log
        else #220123...
            SCANRESULT=''
        fi
    fi #210201
} #scan_for_wireless_networks

build_display_network_list() {
    echo -n '' > /tmp/sns_profile_ssid
    echo -n 'false' > /tmp/sns_show_hidden_ssid_box
    echo -n 'true' > /tmp/sns_show_passphrase_box
    #convert each found network into a single line... 110203
    SRLINES="$(tr '|' ' ' <<< "$SCANRESULT" | tr '\n' '|' | tr -d '\t' | \
      sed -e 's%BSS \([0-9a-f:]\+\)[^\|]*%\n\1%g' \
        -e 's%freq: \([0-9]\+\)[^\|]*%\1%g' \
        -e 's%capability: ESS \([^ \|]\+\)[^\|]*%\1%g' \
        -e 's%signal: \([/0-9-]\+\)[^\|]*%\1%g' \
        -e '{s%SSID: \\x00[^|]*%SSID: %g ; s%SSID: |%(hidden)|%g ; s%SSID: %%g}' \
        -e 's%DS Parameter set: channel %%g' \
        -e 's%\(RSN\)[^\|]*%\1%g' \
        -e 's%\(WPA\)[^\|]*%\1%g' \
        -e 's% \* Pairwise ciphers: %%g' \
        -e 's% \* Authentication suites: %%g' | \
      sort -g -r -t '|' -k 4)" #170619 #201001
    CELL_NUMBER=0 #210208...
    tee -a /tmp/sns_scan_rawoneline <<< "$SRLINES" |
    while IFS='|' read -r CELL_ADDRESS CELL_FREQUENCY CELL_CAPABILITY CELL_SIGNAL CELL_ESSID CELL_CHANNEL CELL_SEC_MGMT CELL_CIPHERS CELL_AUTH CELL_SEC_MGMT2 CELL_CIPHERS2 _; do
        ((++CELL_NUMBER)) #210208 end
        [ -z "$CELL_ESSID" ] && continue #101029
        # Build security summary field...
        if [ "$CELL_CAPABILITY" = 'Privacy' ]; then
            CELL_ENCRYPTIONKEY='on'
            IMG_SHIELD=wifi_encrypted
            PASSBOXVIS='show'
            AUTHSUFFIX=''
            [ "$CELL_AUTH" != 'PSK' ] && AUTHSUFFIX="-${CELL_AUTH:0:1}"
            if [ -z "$CELL_SEC_MGMT" ]; then #200920
                CELL_SEC_MGMT='WEP' #200920
                TXT_SHIELD='WEP'
            elif [ -z "$CELL_SEC_MGMT2" ]; then
                TXT_SHIELD="${CELL_SEC_MGMT}-${CELL_CIPHERS}$AUTHSUFFIX"
            else
                if [ "$CELL_CIPHERS2" = "$CELL_CIPHERS" ]; then
                    TXT_SHIELD="${CELL_SEC_MGMT:0:1}/${CELL_SEC_MGMT2:0:1}-${CELL_CIPHERS}$AUTHSUFFIX"
                else
                    TXT_SHIELD="${CELL_SEC_MGMT:0:1}/${CELL_SEC_MGMT2:0:1}-${CELL_CIPHERS%% .*} ${CELL_CIPHERS2%% .*}$AUTHSUFFIX"
                fi
            fi
            TXT_SHIELD="$(sed '/ / {s/\([ -].\)[^ -]*/\1/g ; s% %/%g}' <<< "$TXT_SHIELD")"
        else
            CELL_ENCRYPTIONKEY='off'
            IMG_SHIELD=wifi_open
            TXT_SHIELD="$(gettext 'Open')"
            PASSBOXVIS='hide'
            [ "$CELL_NUMBER" -eq 1 ] && echo 'false' > /tmp/sns_show_passphrase_box
        fi
        # Determine signal level icon...
        # If signal not in dBm, convert fractional format to pseudo dBm. #210202...
        [ "${CELL_SIGNAL: -4}" = '/100' ] \
          && CELL_SIGNAL=$(( -(100 - ${CELL_SIGNAL%/100}) ))
        if   [ "$CELL_SIGNAL" -gt -50 ]; then IMG_QUALITY=quality_5 #Excellent single strength (Next to Router)
        elif [ "$CELL_SIGNAL" -gt -67 ]; then IMG_QUALITY=quality_4 #Good signal strength for Web browsing, voice/video calls.
        elif [ "$CELL_SIGNAL" -gt -70 ]; then IMG_QUALITY=quality_3 #Best effort for Web browsing for reliable packet delivery.
        elif [ "$CELL_SIGNAL" -gt -80 ]; then IMG_QUALITY=quality_2 #Experience bad connectivity, Packet delivery may be unreliable.
        elif [ "$CELL_SIGNAL" -gt -90 ] ; then IMG_QUALITY=quality_1 #Probably unusable.
        else IMG_QUALITY=quality_0 #Unusable.
        fi #210202 end
        CELL_ESSID_XLATED="$CELL_ESSID"
        [ "$CELL_ESSID" = '(hidden)' ] && CELL_ESSID_XLATED="$(gettext '(hidden)')"
        # For hidden networks, let user provide actual name...
        HIDNETBOXVIS='hide'
        PROFILESSID=''
        if [ "$CELL_ESSID" = '(hidden)' ]; then
            HIDNETBOXVIS='show'
            PROFILESSID="$(grep -sm 1 "^..:.*|$CELL_ADDRESS|" /etc/simple_network_setup/connections | cut -f 7 -d '|')"
            if [ "$CELL_NUMBER" -eq 1 ]; then
                echo -n "$PROFILESSID" > /tmp/sns_profile_ssid
                echo 'true' > /tmp/sns_show_hidden_ssid_box
            fi
        fi
        # Build network column entries...
# shellcheck disable=SC2086
        echo '<radiobutton height-request="25" space-expand="false" space-fill="false">
       <label>'${CELL_ESSID_XLATED}'</label>
       <variable>RADIO_'${CELL_NUMBER}'</variable>
       <action>'${HIDNETBOXVIS}':HIDNETBOX</action>
       <action>echo -n '${PROFILESSID}' > /tmp/sns_profile_ssid</action>
       <action>clear:HIDDEN_NAME</action>
       <action>refresh:HIDDEN_NAME</action>
       <action>'${PASSBOXVIS}':PASSBOX</action>
     </radiobutton>' >> /tmp/sns_scan_radiobuttons #190216
# shellcheck disable=SC2086
        echo '
   <hbox space-expand="false" space-fill="false">
     <text xalign="0" yalign="1" use-markup="true" space-expand="true" space-fill="true">
       <label>"<small><small>'${TXT_SHIELD}'</small></small>"</label>
     </text>
     <pixmap height-request="25" space-expand="false" space-fill="false">
       <input file>/usr/share/pixmaps/puppy/'${IMG_SHIELD}'.svg</input>
       <height>25</height>
     </pixmap>
   </hbox>' >> /tmp/sns_scan_radiobuttons_shield
# shellcheck disable=SC2086
        echo '
   <hbox space-expand="false" space-fill="false">
     <text xalign="0" yalign="1" use-markup="true" space-expand="true" space-fill="true">
       <label>"<small><small>'${CELL_SIGNAL}' mDb</small></small>"</label>
     </text>
     <pixmap height-request="25" space-expand="false" space-fill="false">
       <input file>/usr/share/pixmaps/puppy/'${IMG_QUALITY}'.svg</input>
       <height>25</height>
     </pixmap>
   </hbox>' >> /tmp/sns_scan_radiobuttons_strength
# shellcheck disable=SC2086
        echo '
   <hbox space-expand="false" space-fill="false" height-request="25">
     <text xalign="1" yalign="1" use-markup="true" space-expand="true" space-fill="true">
       <label>"'${CELL_ADDRESS}'"</label>
     </text>
   </hbox>' >> /tmp/sns_scan_radiobuttons_address
        #---
   
        echo "${CELL_NUMBER}|${CELL_ADDRESS}|${CELL_CHANNEL}|${CELL_FREQUENCY}|${CELL_SIGNAL}|${CELL_ENCRYPTIONKEY}|${CELL_ESSID}|${CELL_SEC_MGMT}" >> /tmp/sns_scan_oneline
    done
} #build_display_network_list
 
build_display_radio_buttons() {
    if [ ! -f /tmp/sns_scan_radiobuttons ]; then
        FRAME1='<text space-expand="true" space-fill="true"><label>""</label></text>'
        HIDDENBOX=""
        FRAME2=""
        if which iw >/dev/null 2>&1; then #220123...
            WIN2MSG1="$(gettext 'No wireless networks found.')"
        else
            WIN2MSG1="$(gettext "Cannot scan for networks -- 'iw' command is missing.")"
        fi
        WIN2BUT1=""
        WIN2BUT2=""
    else
        WIN2MSG1="$(gettext "Choose which network you want to use; enter network name if hidden; enter passphrase if encrypted; then click <b>Connect</b> button.")"
        RADIOBUTTONS='
   <hbox space-expand="true" space-fill="true">
     <vbox space-expand="false" space-fill="false">'$(cat /tmp/sns_scan_radiobuttons)'</vbox>
     <text space-expand="true" space-fill="true"><label>""</label></text>
     <vbox space-expand="false" space-fill="false">'$(cat /tmp/sns_scan_radiobuttons_shield)'</vbox>
     <text width-request="2" space-expand="false" space-fill="false"><label>""</label></text>
     <vbox space-expand="false" space-fill="false">'$(cat /tmp/sns_scan_radiobuttons_strength)'</vbox>
     <vbox space-expand="false" space-fill="false">'$(cat /tmp/sns_scan_radiobuttons_address)'</vbox>
   </hbox>'
        FRAME1='
    <vbox space-expand="true" space-fill="true">
    <frame '$(gettext 'Wireless networks')'>
      <vbox scrollable="true" shadow-type="1" space-expand="false" space-fill="false">
        <eventbox name="bg"  above-child="false" visible-window="true" space-expand="true" space-fill="true">
          <vbox border-width="5" space-expand="true" space-fill="true">
            '${RADIOBUTTONS}'
          </vbox>
        </eventbox>
      </vbox>
    </frame>
    </vbox>'

# shellcheck disable=SC2016
        HIDDENBOX='
   <vbox space-expand="false" space-fill="false">
       <hbox border-width="5" space-expand="true" space-fill="true">
             <text space-expand="false" space-fill="false">
               <label>'$(gettext 'Hidden network name:')'</label>
             </text>
             <entry space-expand="true" space-fill="true" caps-lock-warning="true" 
              tooltip-markup="'$(gettext 'Enter network name of selected hidden network')'">
               <variable>HIDDEN_NAME</variable>
               <input>cat /tmp/sns_profile_ssid</input>
             </entry>
       </hbox>
     <variable>HIDNETBOX</variable>
   </vbox>'

# shellcheck disable=SC2016
        FRAME2='
   <vbox space-expand="false" space-fill="false">
           <hbox border-width="5" space-expand="true" space-fill="true">
             <vbox>
               <hbox space-expand="true" space-fill="true">
                 <text xalign="0" space-expand="false" space-fill="false"><label>'$(gettext 'Passphrase:')'</label></text>
                 <notebook show-tabs="false" show-border="false" visible="false">
                   <vbox>
                     <entry space-expand="true" space-fill="true" caps-lock-warning="true" 
                     tooltip-markup="'$(gettext "Enter selected network's passphrase, unless the network is already in a connection profile and its passphrase has not changed")'" visibility="false">
                       <variable>PASS_SHOWN</variable>
                       <input>echo "$PASS_HIDDEN"</input>
                       <action>refresh:PASS_HIDDEN</action>
                     </entry>
                   </vbox>
                   <vbox>
                     <entry space-expand="true" space-fill="true" caps-lock-warning="true" 
                     tooltip-markup="'$(gettext "Enter selected network's passphrase, unless the network is already in a connection profile and its passphrase has not changed")'" visibility="true">
                       <variable>PASS_HIDDEN</variable>
                       <input>echo "$PASS_SHOWN"</input>
                       <action>refresh:PASS_SHOWN</action>
                     </entry>
                   </vbox>
                   <variable>SWITCH</variable>
                   <input>echo $(( (SWITCH+1) &1 ))</input>
                 </notebook>
               </hbox>
               <checkbox space-expand="true" space-fill="true">
                 <label>'$(gettext 'Show passphrase')'</label>
                 <action>refresh:SWITCH</action>
               </checkbox>
             </vbox>
           </hbox>
     <variable>PASSBOX</variable>
   </vbox>'
        WIN2BUT1='
   <button can-default="true" has-default="true" space-expand="false" space-fill="false">
     <variable>BTN_CONNECT</variable>
     <label>'$(gettext "Connect")'</label>
     '"$(/usr/lib/gtkdialog/xml_button-icon internet_connect.svg)"'
     <action type="exit">BUT_CONNECT</action>
   </button>'
        WIN2BUT2='
   <button space-expand="false" space-fill="false">
     <label>'$(gettext 'Help')'</label>
     '"$(/usr/lib/gtkdialog/xml_button-icon help)"'
     <action>/usr/local/simple_network_setup/help_security & </action>
   </button>'
    fi
    kill $PIDXMSG 2>/dev/null ; PIDXMSG=""
} #build_display_radio_buttons

build_and_display_wireless_setup_window() {
    SNS_setup='<window title="'$(gettext 'Simple Network Setup')'" icon-name="gtk-network" height-request="400" width-request="540">
  <vbox space-expand="true" space-fill="true">
    '"$(/usr/lib/gtkdialog/xml_info fixed "internet_connect.svg" 60 "${WIN2MSG1}")"' 
    '${FRAME1}'
    '${HIDDENBOX}'
    '${FRAME2}'
    <hbox space-expand="false" space-fill="false">
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Rescan")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon refresh)"'
        <action type="exit">BUT_RESCAN</action>
      </button>
      '${WIN2BUT2}'
      <text space-expand="true" space-fill="true"><label>""</label></text>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Cancel")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon cancel)"'
        <action type="exit">BUT_GOBACK</action>
      </button>
      '${WIN2BUT1}'
    </hbox>
  </vbox>

  <action signal="map-event">show:SWITCH</action>
  <action signal="map-event">grabfocus:PASS_HIDDEN</action>
  <action signal="show" condition="file_is_false(/tmp/sns_show_hidden_ssid_box) ">hide:HIDNETBOX</action>
  <action signal="show" condition="file_is_false(/tmp/sns_show_passphrase_box) ">hide:PASSBOX</action>
</window>'
    export SNS_setup
    #darker bg
    echo '<?xml version="1.1" encoding="UTF-8"?><svg height="10" width="10">
    <rect style="fill:#000000;fill-opacity:0.2" width="10" height="10" x="0" y="0"/></svg>' > /tmp/sns_bg.svg

    echo '
  pixmap_path "/tmp"
  style "bg" { bg_pixmap[NORMAL] = "sns_bg.svg" }
  widget "*bg*" style "bg"' > /tmp/gtkrc_mono
    export GTK2_RC_FILES=/tmp/gtkrc_mono:/root/.gtkrc-2.0
    #---

    . /usr/lib/gtkdialog/xml_info gtk #build bg_pixmap for gtk-theme
    RETSTRING="$("$GTKDIALOG" --program=SNS_setup)" #231106
} #build_and_display_wireless_setup_window

extract_data_for_selected_network() {
    SEC_KEY="$(grep '^PASS_HIDDEN' <<< "$RETSTRING" | cut -f 2 -d '"' | tr -d '-')" #'geany
    CELL_NUMBER="$(grep '^RADIO' <<< "$RETSTRING" | grep 'true' | cut -f1 -d'=' | cut -f2 -d'_')" #ex: 01
    cnPATTERN='^'"$CELL_NUMBER"'|'
    #grep to temp file then read from temp file, because piping grep output to read fails. #210208
    grep "$cnPATTERN" /tmp/sns_scan_oneline >/tmp/sns_oneline #210208
    IFS='|' read -r CELL_NUMBER CELL_ADDRESS CELL_CHANNEL CELL_FREQUENCY CELL_SIGNAL CELL_ENCRYPTIONKEY CELL_ESSID CELL_SEC_MGMT CELL_CIPHERS CELL_AUTH CELL_SEC_MGMT2 CELL_CIPHERS2 </tmp/sns_oneline #210208
    if [ "$CELL_ESSID" = '(hidden)' ]; then
        CELL_ESSID="$(grep '^HIDDEN_NAME' <<< "$RETSTRING" | cut -f2 -d'=' | cut -f2 -d'"')"
        SCAN_SSID=1
    else
        SCAN_SSID=0
    fi
    if [ -z "$CELL_ESSID" ]; then
        FLAGERR=8
    elif [ "$CELL_ENCRYPTIONKEY" = "on" ]; then
        if [ -z "$SEC_KEY" ]; then #230930...
            SEC_KEY="$(grep "|$CELL_ESSID|$CELL_ADDRESS|" </etc/simple_network_setup/connections | cut -d '|' -f $SEC_KEY_FIELD)"
        fi
        if [ -z "$SEC_KEY" ]; then
            FLAGERR=2 #no security key
        else
            SEC_MGMT="$CELL_SEC_MGMT"
            case $SEC_MGMT in
              WEP) ;; #Restricted (shared key) is deprecated #210207
              *) SEC_MGMT='WPA-PSK' ;; #exs: AES, TKIP
            esac
        fi
    else
        WPA_DRIVER=""
    fi
} #extract_data_for_selected_network

configure_wpa_supplicant() {
    FLAGERR= #100323
    case $SEC_MGMT in
      WEP)
        WEP_KEY0='' #210207...
        case "${#SEC_KEY}" in
          5|13) WEP_KEY0="\"${SEC_KEY}\"" ;;
          10|26) WEP_KEY0="${SEC_KEY}" ;;
          *) echo "Invalid WEP key: $SEC_KEY" >> /tmp/sns_wireless_log ;;
        esac
        echo "ctrl_interface=/var/run/wpa_supplicant
ap_scan=${ONEFIX}

network={
 ssid=\"${CELL_ESSID}\"
 scan_ssid=${SCAN_SSID}
 key_mgmt=NONE
 wep_key0=${WEP_KEY0}
 wep_tx_keyidx=0
}" > "/tmp/sns_wpa_supplicant_conf"
        RUNWPASUPP='yes'
        kill_wpa_supplicant
       ;;
      WPA-PSK|WPA2-PSK) #very simple, handles all ciphers.
        #it works psk="passphrase" (with quotes), but for security encode psk into hex string...
        hexSEC_KEY=$(wpa_passphrase "$CELL_ESSID" "$SEC_KEY" | grep 'psk=[^"]' | cut -f 2 -d '=')
        echo "ctrl_interface=/var/run/wpa_supplicant
ap_scan=${ONEFIX}

network={
 ssid=\"${CELL_ESSID}\"
 scan_ssid=${SCAN_SSID}
 key_mgmt=${SEC_MGMT}
 psk=${hexSEC_KEY}
}" > "/tmp/sns_wpa_supplicant_conf"
        RUNWPASUPP='yes'
        kill_wpa_supplicant
       ;;
      WPA*)  
        #it works psk="passphrase" (with quotes), but for security encode psk into hex string...
        hexSEC_KEY=$(wpa_passphrase "$CELL_ESSID" "$SEC_KEY" | grep 'psk=[^"]' | cut -f 2 -d '=')
        echo "ctrl_interface=/var/run/wpa_supplicant
ap_scan=${ONEFIX}

network={
 ssid=\"${CELL_ESSID}\"
 scan_ssid=${SCAN_SSID}
 proto=WPA
 key_mgmt=${SEC_MGMT}
 pairwise=${WPA_ENC}
 group=${WPA_ENC}
 psk=${SEC_KEY}
 wpa_ptk_rekey=600
}" > "/tmp/sns_wpa_supplicant_conf"
        RUNWPASUPP='yes'
        kill_wpa_supplicant
       ;;
    esac
} #configure_wpa_supplicant

run_wpa_supplicant() {
    echo "STEP5b: wpa_supplicant -B -D${WPA_DRIVER} -i${INTERFACE} -c\"/etc/simple_network_setup/wpa_supplicant.conf-${CELL_ESSID}-${MACADDRESS}\"" >> /tmp/sns_wireless_log
    wpa_supplicant -B -D"${WPA_DRIVER}" -i"${INTERFACE}" -c"/tmp/sns_wpa_supplicant_conf" >> /tmp/sns_wireless_log 2>&1
    local wCNT=0
    while [ $((++wCNT)) -le 20 ]; do
        sleep 1
        wpa_cli -i "$INTERFACE" status | grep -q '^bssid=[0-9a-f]' && break
    done
    if [ "$wCNT" -gt 20 ]; then
        echo "Running: wpa_cli -i ${INTERFACE} status" >> /tmp/sns_wireless_log
        wpa_cli -i "$INTERFACE" status >> /tmp/sns_wireless_log 2>&1
        killall -SIGHUP wpa_supplicant
        kill "$PIDX" 2>/dev/null #210201
        return 1
    fi
    return 0
} #run_wpa_supplicant

kill_wpa_supplicant() {
    if ps -C wpa_supplicant >/dev/null 2>&1; then #210202
        wpa_cli terminate #kills any running wpa_supplicant. no it doesn't, just brings down interface.
        killall -q wpa_supplicant
    fi
} #kill_wpa_supplicant

show_wait_splash() { #Argument: fuCNT. Always returns 0.
    [ -n "$PIDX" ] && kill "$PIDX" 2>/dev/null #210201
    case "$1" in
      3) BGCOLOR="DeepPink" ;;
      2) BGCOLOR="pink" ;;
      1) BGCOLOR="HotPink" ;;
    esac
    case "$1" in
      4) gtkdialog-splash -placement center -bg orange -text "$(eval_gettext "Please wait, attempting to connect to '\${CELL_ESSID}'...")" >/dev/null & #210207
        ;;
      *) gtkdialog-splash -placement center -bg "$BGCOLOR" -text "$(gettext 'Please keep waiting, retrying encrypted connection...')" >/dev/null &
        ;;
    esac
    PIDX=$! #210207?
    sleep 0.1
    return 0
} #show_wait_splash
 
wait_until_link_available() {
    #wait until access point becomes available...
    sCNT=0
    while true; do
        iw dev "${INTERFACE}" link | grep -q '^Connected' && break #210202
        sleep 1
        if [ $(( ++sCNT )) -gt 20 ]; then
            {
            echo "" #100320...
            echo "ERROR, TIMEOUT. Have not got an Access Point."
            echo "Result of 'iw dev ${INTERFACE} info':" #210202
            iw dev "${INTERFACE}" info 2>&1 #210202
            echo ""
            } >> /tmp/sns_wireless_log #100320 end
            FLAGERR=7
            break
        fi
    done
} #wait_until_link_available

kill_wireless_link() {
    iw dev "$INTERFACE" info 2>/dev/null | grep -qw 'ssid' && iw dev "$INTERFACE" disconnect #210202
    ip link set "$INTERFACE" down #210202
} #kill_wireless_link

run_dhcpcd() {
    for iterDHCPCD in a b; do #100320
        [ "$iterDHCPCD" = "a" ] && DHCPCDFIX=""
        [ "$iterDHCPCD" = "b" ] && DHCPCDFIX="-I ''" #some dhcp servers require empty Client ID (default is macaddress).
        echo -n > /etc/resolv.conf #240307
        echo "STEP6${iterDHCPCD}: dhcpcd $DHCPCD_TIMEOUT $DHCPCDFIX $INTERFACE" >> /tmp/sns_wireless_log
# shellcheck disable=SC2086 #word-split $DHCPCD_TIMEOUT & $DHCPCDFIX
        dhcpcd $DHCPCD_TIMEOUT $DHCPCDFIX "$INTERFACE" >> /tmp/sns_wireless_log 2>&1 ####DHCP CLIENT#### 121117 #211215
        local RC=$? #170402
        [ $RC -eq 0 ] || break
        #need to wait awhile #210212...
        for ONESLEEP in 0.2 1 2; do
            sleep $ONESLEEP
            grep -q '^nameserver' /etc/resolv.conf && break
        done
        grep -q '^nameserver' /etc/resolv.conf && break
        sleep 1
        [ "$iterDHCPCD" != "b" ] && dhcpcd --release "$INTERFACE"
    done
    [ "$RC" -eq 0 ] \
      && grep -q '^nameserver' /etc/resolv.conf || FLAGERR=6 #170402 #210212
} #run_dhcpcd

kill_wpa_supplicant_and_link() {
    kill_wpa_supplicant
    kill_wireless_link
    dhcpcd --release "$INTERFACE" 2>/dev/null
    ip route flush dev "$INTERFACE" #100703
} #kill_wpa_supplicant_and_link

add_wireless_connection_profile_and_conf() { #211002
    #100413 have one pc where blinky did not start. try again...
    if which blinky_tray >/dev/null \
      && ! ps -C blinky_tray >/dev/null 2>&1; then
        blinky_tray & #210202
    fi
    [ "$SEC_MGMT" != 'open' ] && SEC_MGMT="$WPA_SEC_MGMT"
    unspoof_macaddress #Set MACADDRESS to permanent MAC address #211215
    touch /etc/simple_network_setup/connections
    chmod 600 /etc/simple_network_setup/connections #230920
    ( #210207,210208,211215...
        echo "${MACADDRESS}|${IF_INTTYPE}|${IF_DRIVER}|${IF_BUS}|${IF_INFO}|${DHCPCDFIX}|\
${CELL_ESSID}|${CELL_ADDRESS}|${SEC_MGMT}|${SEC_KEY}|${WPA_DRIVER}|"
        grep "^$MACADDRESS|" < /etc/simple_network_setup/connections | grep -v "^$MACADDRESS.*|$CELL_ESSID|"
        grep -v "^$MACADDRESS|" < /etc/simple_network_setup/connections
    ) > /tmp/sns_connections.tmp
    mv  /tmp/sns_connections.tmp /etc/simple_network_setup/connections #211002
    mv -f /tmp/sns_wpa_supplicant_conf "/etc/simple_network_setup/wpa_supplicant.conf-${CELL_ESSID}-${MACADDRESS}"
} #add_wireless_connection_profile_and_conf
    
build_and_display_wireless_success_window() {
    XML_FIREWALL=""
    if [ ! -x /etc/rc.d/rc.firewall ] && [ ! -x /etc/init.d/rc.firewall ]; then
        XML_FIREWALL='
         <text><label>"'$(gettext "However, there is one item of recommended housekeeping: you really should be running a firewall. The operating system is inherently secure, however a firewall will give you that extra protection while online. Recommend that you tick the 'Start firewall' checkbox (the firewall will install and will automatically run at all future boots)...")'"</label></text>
         <checkbox>
           <label>'$(gettext 'Start firewall')'</label>
           <default>true</default>
           <variable>CHK_FIREWALL</variable>
         </checkbox>
         <hseparator></hseparator>'
    fi
    kill "$PIDX" 2>/dev/null
    SNS_complete='
        <window title="'$(gettext 'SNS: Simple Network Setup')'" icon-name="gtk-network">
        <vbox>
          <frame>
            '"$(/usr/lib/gtkdialog/xml_pixmap dialog-complete.svg popup)"'
            <text use-markup="true"><label>"<b>'$(gettext 'Successful connection to wireless network')' '${CELL_ESSID}'</b>"</label></text>
            <text><label>""</label></text>
            '${XML_FIREWALL}'
            <hseparator></hseparator>
            <text xalign="0"><label>'$(gettext "SNS will automatically connect to the Internet at bootup, wirelessly if possible.")'</label></text>
            <text xalign="0"><label>'$(gettext "To make SNS the default network setup tool so that clicking the 'connect' icon on the desktop or selecting 'Setup networking' from the network tray icon will immediately launch SNS...")'</label></text>
            <checkbox>
              <label>'$(gettext 'Set SNS as default network setup tool')'</label>
              <default>true</default>
              <variable>CHK_SNSDEF</variable>
            </checkbox>
          </frame>
          <hbox>
            <button space-expand="false" space-fill="false">
              <label>'$(gettext "Ok")'</label>
              '"$(/usr/lib/gtkdialog/xml_button-icon ok)"'
              <action>exit:OK</action>
            </button>
          </hbox>
        </vbox>
        </window>' #190216
    export SNS_complete
    RETSTR3="$("$GTKDIALOG" --program=SNS_complete --center)" #231106
} #build_and_display_wireless_success_window

build_and_display_wireless_error_window() {
    [ "$PIDXMSG" ] && kill "$PIDXMSG" 2>/dev/null
    [ "$PIDX" ] && kill "$PIDX" 2>/dev/null
    case $SEC_MGMT in
      WPA*) ERR_EXTRA1="$(gettext 'Note: the network card and/or Linux driver might not support WPA2, in which case you will need to set the wireless router to WPA. Or, WPA might not be supported at all, in which case you will have to set the router and network card to use WEP.')" ;;
      *)    ERR_EXTRA1="" ;;
    esac
    case $FLAGERR in
      1) ERR_MSG="$(eval_gettext "Failed to activate interface '\${INTERFACE}'. Sometimes this is just a temporary problem. Go back to the main window, and you can try again...")" ; ERR_EXTRA1="" ;;
      2) ERR_MSG="$(gettext 'ERROR: you did not specify a Passphrase')" ; ERR_EXTRA1="" ;;
      4) ERR_MSG="$(eval_gettext "Failed to connect to SSID '\${CELL_ESSID}'.")"; ERR_EXTRA1="" ;; #210202
      5) ERR_MSG="$(eval_gettext "wpa_supplicant failed to associate with the network card, perhaps due to an incorrect password for wireless network '\${CELL_ESSID}' or incorrect name for hidden network.")" ;;
      6) ERR_MSG="$(eval_gettext "DHCP client failed to negotiate with wireless network '\${CELL_ESSID}'")" ;;
      7) ERR_MSG="$(gettext 'Failed to obtain Access Point of network.')";  ERR_EXTRA1="" ;;
      8) ERR_MSG="$(gettext 'ERROR: you did not specify a network name for the hidden network')" ;;
      *) ERR_MSG="$(eval_gettext "Failed to connect to wireless network '\${CELL_ESSID}'")" ;; 
    esac
    SNS_error='
  <window title="'$(gettext 'Simple Network Setup')'" icon-name="gtk-network">
  <vbox>
    <frame>
      '"$(/usr/lib/gtkdialog/xml_pixmap dialog-error popup)"'
      <text use-markup="true"><label>"<b>'${ERR_MSG}'</b>
'${ERR_EXTRA1}'"</label></text>
      <text xalign="0"><label>'$(gettext "So, what do you want to do? If you go back to the main window, you could test a different interface or network. Note, sometimes an error 'goes away' if you retry.")'</label></text>
    </frame>
    <hbox space-expand="false" space-fill="false">
      <button tooltip-text="'$(gettext 'View log of attempted connection:')'" space-expand="false" space-fill="false">
        <label>'$(gettext 'View Log')'</label>'"
        <action>echo ' ' >> /tmp/sns_wireless_log</action>
        <action>echo '*********************************************************' >> /tmp/sns_wireless_log</action>
        <action>echo 'LAST 10 LINES of /var/log/messages:' >> /tmp/sns_wireless_log</action>
        <action>tail -n 10 /var/log/messages >> /tmp/sns_wireless_log</action>
        <action>defaulttextviewer /tmp/sns_wireless_log & </action>"'
      </button>
      <text space-expand="true" space-fill="true"><label>""</label></text>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Retry")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon refresh)"'
        <action type="exit">BUT_GOBACK</action>
      </button>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Quit")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon quit)"'
        <action type="exit">BUT_QUIT</action>
      </button>
    </hbox>
  </vbox>
  </window>'
    export SNS_error
    RETSTRING="$("$GTKDIALOG" --program=SNS_error --center)" #240605
} #build_and_display_wireless_error_window
    
perform_wired_setup() {
    gtkdialog-splash -placement center -bg orange -text "$(eval_gettext "Please wait, trying to connect to interface '\${INTERFACE}'...")" >/dev/null &
    PIDXX=$!
    echo "Information about this interface:
 Interface: $INTERFACE  Driver: $IF_DRIVER  Bus: $IF_BUS  MacAddress: $MACADDRESS
 Description: $IF_INFO
 " > /tmp/sns_wired_log
    spoof_macaddress >> /tmp/sns_wired_log #If using real MAC, spoof it #211215
    if ip link set "$INTERFACE" up >> /tmp/sns_wired_log 2>&1; then #210202
        check_and_connect_wired_link
        kill $PIDXX 2>/dev/null

        if grep -q '^nameserver' /etc/resolv.conf; then #210212
            add_wired_connection_profile #211002
            build_and_display_wired_success_window
        else
            build_and_display_wired_error_window
            grep '^EXIT' <<< "$RETSTRING" | grep -q 'BUT_GOBACK' && exec sns
        fi
    else
        kill $PIDXX 2>/dev/null
    fi
} #perform_wired_setup

check_and_connect_wired_link() {
    TIMEOUT=15 #200412
    while [ $TIMEOUT -ge 0 ]; do #200412
        ip link show "$INTERFACE" | grep -q 'LOWER_UP' && break #211231
        [ $((--TIMEOUT)) -ge 0 ] && sleep 1 #190209 190216 200412
    done
    if [ $TIMEOUT -lt 0 ]; then #211231
        ip link set "$INTERFACE" down #210202
        kill "$PIDXX" 2>/dev/null
        /usr/lib/gtkdialog/box_ok "$(gettext 'Simple Network Setup')" error "<b>$(eval_gettext "There does not seem to be any network connected to \${INTERFACE}")</b>" " " "$(gettext "Is the network cable unplugged? Modem router turned off? If you can fix it, great, otherwise try a different interface.")"
        exec sns
        exit
    fi
    echo -n > /etc/resolv.conf #240307
    DHCPCDFIX=""
# shellcheck disable=SC2086 #word-split $DHCPCD_TIMEOUT
    dhcpcd $DHCPCD_TIMEOUT "$INTERFACE" >> /tmp/sns_wired_log 2>&1 #211215
    RC=$? #170402
    #need to wait awhile #210212...
    if [ $RC -eq 0 ]; then
        for ONESLEEP in 0.2 1 2; do
            sleep $ONESLEEP
            grep -q '^nameserver' /etc/resolv.conf && break
        done
    fi
    if ! grep -q '^nameserver' /etc/resolv.conf; then #170402 end #210212 end
        #fail, try again.
        echo -n > /etc/resolv.conf #240307
        DHCPCDFIX="-I ''"
        dhcpcd --release "$INTERFACE"
        sleep 0.1
# shellcheck disable=SC2086 #word-split $DHCPCD_TIMEOUT
        dhcpcd $DHCPCD_TIMEOUT -I '' "$INTERFACE" >> /tmp/sns_wired_log 2>&1 #211215
        RC=$? #170402
       #need to wait awhile #210212...
        if [ $RC -eq 0 ]; then
            for ONESLEEP in 0.2 1 2; do
                sleep $ONESLEEP
                grep -q '^nameserver' /etc/resolv.conf && break
            done
        fi
    fi
} #check_and_connect_wired_link

build_and_display_wired_success_window() {
    SNS_complete='
  <window title="'$(gettext 'SNS: Simple Network Setup')'" icon-name="gtk-network">
  <vbox>
    <frame>
      '"$(/usr/lib/gtkdialog/xml_pixmap dialog-complete popup)"'
      <text use-markup="true"><label>"<b>'$(gettext 'Successful connection to wired network')' '${INTERFACE}'</b>"</label></text>
      <text><label>""</label></text>
      <hseparator></hseparator>
      <text xalign="0"><label>'$(gettext "SNS will automatically connect to the Internet at bootup, wirelessly if possible.")'</label></text>
      <text xalign="0"><label>'$(gettext "To make SNS the default network setup tool so that clicking the 'connect' icon on the desktop or selecting 'Setup networking' from the network tray icon will immediately launch SNS...")'</label></text>
      <checkbox>
        <label>'$(gettext 'Set SNS as default network setup tool')'</label>
        <default>true</default>
        <variable>CHK_SNSDEF</variable>
      </checkbox>
    </frame>
    <hbox>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Ok")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon ok)"'
        <action>exit:OK</action>
      </button>
    </hbox>
  </vbox>
  </window>' #190216
    export SNS_complete
    RETSTR5="$("$GTKDIALOG" --program=SNS_complete --center)" #240605
    if grep '^CHK_SNSDEF' <<< "$RETSTR5" | grep -q 'true'; then
        echo -e '#!/bin/sh\nexec sns' > /usr/local/bin/defaultconnect
    else
        echo -e '#!/bin/sh\nexec connectwizard' > /usr/local/bin/defaultconnect
    fi
} #build_and_display_wired_success_window

add_wired_connection_profile() { #211002...
    #Use real address if using dynamic MAC addresses 
    unspoof_macaddress #Set MACADDRESS to permanent MAC address #211215
    aPATTERN="^$MACADDRESS.*|Wired|"
    touch /etc/simple_network_setup/connections
    chmod 600 /etc/simple_network_setup/connections #230920
    echo -e "${MACADDRESS}|${IF_INTTYPE}|${IF_DRIVER}|${IF_BUS}|${IF_INFO}|${DHCPCDFIX}|\n$(grep -i -v "$aPATTERN" /etc/simple_network_setup/connections)" > /tmp/sns_connections.tmp #211002
    mv  /tmp/sns_connections.tmp /etc/simple_network_setup/connections #211002
} #add_wired_connection_profile

build_and_display_wired_error_window() {
    ip link set "$INTERFACE" down #210202
    dhcpcd --release "$INTERFACE" 2>/dev/null
    ip route flush dev "$INTERFACE" #100703
    SNS_error='
  <window title="'$(gettext 'Simple Network Setup')'" icon-name="gtk-network">
  <vbox>
    <frame>
      '"$(/usr/lib/gtkdialog/xml_pixmap dialog-error popup)"'
      <text use-markup="true"><label>"<b>'$(eval_gettext "Failed to connect to wired network \${INTERFACE}")'</b>"</label></text>
      <text xalign="0"><label>'$(gettext "The network does exist, however failed to negotiate with the DHCP server. Is there a wireless interface? -- maybe try that.")'</label></text>
    </frame>
    <hbox space-expand="false" space-fill="false">
      <button tooltip-text="'$(gettext 'View log of attempted connection:')'" space-expand="false" space-fill="false">
        <label>'$(gettext 'View Log')'</label>
        <action>defaulttextviewer /tmp/sns_wired_log & </action>
      </button>
      <text space-expand="true" space-fill="true"><label>""</label></text>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Retry")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon refresh)"'
        <action type="exit">BUT_GOBACK</action>
      </button>
      <button space-expand="false" space-fill="false">
        <label>'$(gettext "Quit")'</label>
        '"$(/usr/lib/gtkdialog/xml_button-icon quit)"'
        <action type="exit">BUT_QUIT</action>
      </button>
    </hbox>
  </vbox>
  </window>' #200521
    export SNS_error
    RETSTRING="$("$GTKDIALOG" --program=SNS_error --center)" #240605
} #build_and_display_wired_error_window


################# MAIN ####################

#firewall
if which firewall_ng >/dev/null 2>&1; then
    FW_EXEC=firewall_ng
else
    FW_EXEC="urxvt -e firewallinstallshell"
fi

set_dhcpcd_timeout #211215
echo -n '' > /tmp/sns_interfaces
INTERFACES="$(ip link show | grep -B 1 'link/ether' | grep '^[0-9]' | cut -f 2 -d ':' | tr -d '\n')" #210202
for INTERFACE in $INTERFACES; do #exs: wlan0 eth0
    find_interface_driver
    collect_interface_data
done
build_interface_display_list
find_usable_interfaces #sets WORKINGIF

#120107 new 'Profile' frame...
PROFILE_XML=""
ALL_CONNECTION_PROFILES="$(grep -s '^..:' /etc/simple_network_setup/connections)" #211215
if [ -n "$ALL_CONNECTION_PROFILES" ]; then #211215
    build_connection_display_list
    build_display_connect_button
fi

build_and_display_main_window #sets RETSTRING
EXIT="$(grep '^EXIT' <<< "$RETSTRING" | cut -f2 -d'"')" #'geany
if grep -qE 'CONNECTEXITNOW|DISCONNECTEXITNOW|DISCONNECTRESTART|Interface' <<< "$EXIT"; then
    which connectwizard_exec >/dev/null 2>&1 \
      && connectwizard_exec sns #Update current exec name. 170329 190223 #240403
    grep -qE 'DISCONNECTEXITNOW|DISCONNECTRESTART|Interface' <<< "$EXIT" \
      && networkdisconnect
fi
grep -qE 'EXITRESTART|DISCONNECTRESTART' <<< "$EXIT" \
  && exec sns ###restarting sns###  #240403
grep -qv 'Interface' <<< "$EXIT" && exit

INTERFACE="$(grep 'Interface' <<< "$EXIT" | cut -f2 -d '_')" #ex: wlan1
if [ "$INTERFACE" = "Windows" ]; then #100313
    load_windows_driver
fi

ensure_interface_is_down
extract_interface_data

############ WIRELESS SETUP ###############
if [ "$IF_INTTYPE" = "Wireless" ]; then
    perform_wireless_setup
############ WIRED SETUP ###############
elif [ "$IF_INTTYPE" = "Wired" ]; then
    perform_wired_setup
fi
exit

###END###
