#!/bin/bash
#       Name: SearchSploit - Exploit-DB's CLI search tool
#    Version: 3.8.7 (Release date: 2017-11-27)
# Written by: Offensive Security, Unix-Ninja, and g0tmi1k
#   Homepage: https://github.com/offensive-security/exploit-database
#     Manual: https://www.exploit-db.com/searchsploit/
#
## NOTE:
#   Exit code '0' means finished normally
#   Exit code '1' means something went wrong
#   Exit code '2' means help screen
#   Exit code '6' means updated exploitdb package (APT or Git)


## OS settings (get the path of where the script is stored + database file)
gitpath="/opt/exploit-database"
csvpath="${gitpath}/files.csv"


## Program settings
gitremote="https://github.com/offensive-security/exploit-database.git"
progname="$( basename "$0" )"


## Default options
CLIPBOARD=0
COLOUR=1
EDBID=0
EXACT=0
EXAMINE=0
FILEPATH=1
GETPATH=0
JSON=0
MIRROR=0
OVERFLOW=0
SCASE=0
VERBOSE=0
WEBLINK=0
XML=0
COLOUR_TAG=""
TAGS=""
SEARCH=""
EXCLUDE=""
CASE_TAG_GREP="-i"
CASE_TAG_FGREP="tolower"
AWK_SEARCH=""
COLOUR_OFF_GREP=
COLOUR_ON_GREP=

## Check if our grep supports --color
if grep --help 2>&1 | grep "[-]-color" >/dev/null 2>&1 ; then
  COLOUR_OFF_GREP="--color=never"
  COLOUR_ON_GREP="--color=always"
fi

## Set LANG variable to avoid illegal byte sequence errors
LANG=C


## Usage info
function usage()
{
  echo "  Usage: ${progname} [options] term1 [term2] ... [termN]"
  echo ""
  echo "=========="
  echo " Examples "
  echo "=========="
  echo "  ${progname} afd windows local"
  echo "  ${progname} -t oracle windows"
  echo "  ${progname} -p 39446"
  echo "  ${progname} linux kernel 3.2 --exclude=\"(PoC)|/dos/\""
  echo ""
  echo "  For more examples, see the manual: https://www.exploit-db.com/searchsploit/"
  echo ""
  echo "========="
  echo " Options "
  echo "========="
  echo "   -c, --case     [Term]      Perform a case-sensitive search (Default is inSEnsITiVe)."
  echo "   -e, --exact    [Term]      Perform an EXACT match on exploit title (Default is AND) [Implies \"-t\"]."
  echo "   -h, --help                 Show this help screen."
  echo "   -j, --json     [Term]      Show result in JSON format."
  echo "   -m, --mirror   [EDB-ID]    Mirror (aka copies) an exploit to the current working directory."
  echo "   -o, --overflow [Term]      Exploit titles are allowed to overflow their columns."
  echo "   -p, --path     [EDB-ID]    Show the full path to an exploit (and also copies the path to the clipboard if possible)."
  echo "   -t, --title    [Term]      Search JUST the exploit title (Default is title AND the file's path)."
  echo "   -u, --update               Check for and install any exploitdb package updates (deb or git)."
  echo "   -w, --www      [Term]      Show URLs to Exploit-DB.com rather than the local path."
  echo "   -x, --examine  [EDB-ID]    Examine (aka opens) the exploit using \$PAGER."
  echo "       --colour               Disable colour highlighting in search results."
  echo "       --id                   Display the EDB-ID value rather than local path."
  echo "       --nmap     [file.xml]  Checks all results in Nmap's XML output with service version (e.g.: nmap -sV -oX file.xml)."
  echo "                                Use \"-v\" (verbose) to try even more combinations"
  echo "       --exclude=\"term\"       Remove values from results. By using \"|\" to separated you can chain multiple values."
  echo "                                e.g. --exclude=\"term1|term2|term3\"."
  echo ""
  echo "======="
  echo " Notes "
  echo "======="
  echo " * You can use any number of search terms."
  echo " * Search terms are not case-sensitive (by default), and ordering is irrelevant."
  echo "   * Use '-c' if you wish to reduce results by case-sensitive searching."
  echo "   * And/Or '-e' if you wish to filter results by using an exact match."
  echo " * Use '-t' to exclude the file's path to filter the search results."
  echo "   * Remove false positives (especially when searching using numbers - i.e. versions)."
  echo " * When updating or displaying help, search terms will be ignored."
  echo ""
  exit 2
}


## Update database check
function update()
{
  # Update from the repos (e.g. Kali)
  dpkg -l exploitdb 2>/dev/null >/dev/null
  if [[ "$?" == "0" ]]; then
    updatedeb
    exit 6
  fi

  # Update from homebrew (e.g. OSX)
  brew 2>/dev/null >/dev/null
  if [[ "$?" == "0" ]]; then
    # This only really updates ./searchsploit
    updatedbrew
  fi

  # Update via Git
  updategit

  # Done
  exit 6
}


## Update database (via .deb/apt)
function updatedeb()
{
  echo -e "[i] Updating via APT package management (Expect weekly-ish updates).\n"

  sudo apt update \
    || echo -e "\n[-] Issue with apt update (Please check network connectivity & APT SourcesList values)." 1>&2
  sudo apt -y install exploitdb \
    || echo -e "\n[-] Issue with apt upgrade." 1>&2

  echo -e "\n[*] APT update finished."
}

## Update database (via homebrew)
function updatedbrew()
{
  echo -e "[i] Updating via brew package management.\n"

  brew update \
    || echo -e "\n[-] Issue with brew update (Please check network connectivity)." 1>&2
  brew upgrade exploitdb

  echo -e "\n[*] Brew update finished."
}

## Update database (via Git)
function updategit()
{
  echo -e "[i] Updating via Git (Expect daily updates): ${gitpath}\n"

  ## Make sure we are in the correct folder
  mkdir -p "${gitpath}/" 2>/dev/null \
    || sudo mkdir -p "${gitpath}/"
  cd "${gitpath}/"

  ## Are we in a Git repo?
  if [[ "$( git rev-parse --is-inside-work-tree 2>/dev/null )" != "true" ]]; then
    if [[ "$( ls )" = "" ]]; then
      # If directory is empty, just clone
      echo -e "\n[-] Nothing here (${gitpath}). Starting fresh..."
      git clone "${gitremote}" "${gitpath}/" 2>/dev/null \
      || sudo git clone "${gitremote}" "${gitpath}/"
    fi
  fi

  # Is our Git remote added? (aka wouldn't be via homebrew method)
  if [[ "$( git remote -v )" != *"upstream"*"${gitremote}"* ]]; then
    echo -e "\n[-] Missing Git remote upstream (${gitremote})"
    git init 2>/dev/null \
      || sudo git init
    git remote add upstream "${gitremote}" 2>/dev/null \
      || sudo git remote add upstream "${gitremote}"
  fi

  # Make sure to prep checkout first
  git checkout -- . 2>/dev/null \
    || sudo git checkout -- .

  # Update from git
  echo -e "\n[i] Git pull'ing"
  git pull upstream master 2>/dev/null \
    || sudo git pull upstream master

  # If conflicts, clean and try again
  if [[ "$?" -ne 0 ]]; then
    echo -e "\n[-] Git conflict"
    git clean -d -fx "" \
      || sudo git clean -d -fx ""
    git pull upstream master \
      || sudo git pull upstream master
  fi

  echo -e "\n[*] Git update finished."
  echo "[i] Path: ${gitpath}/"
  exit 6
}


## Printing dotted lines in the correct manner
function drawline()
{
  printf "%0.s-" $( eval echo {1..$(( COL1 + 1 ))} )
  echo -n " "
  printf "%0.s-" $( eval echo {1..$(( COL2 - 1 ))} )
  echo ""
}


## Used in searchsploitout/nmap's XML
function validterm()
{
  ## Check to see if its any phrases which would give a TON of incorrect results
  if [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "microsoft" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "microsoft windows" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "windows" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "apache" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "ftp" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "http" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "linux" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "net" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "network" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "oracle" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "ssh" ] \
    || [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "unknown" ]; then
    echo -e "[-] Skipping term: ${1}   (Term is too general. Please re-search manually: $0 ${arg} ${1})\n" 1>&2
    return 1
  fi
  return 0
}


## Used in searchsploitout/nmap's XML
function searchsploitout()
{
  ## Make sure there is a value
  if [ "${software}" = "" ]; then
    return
  fi

  #echo "" 1>&2

  arg="-t"   ## Title search by default!
  [[ "${JSON}" == "1" ]] && arg="${arg} --json"
  [[ "${OVERFLOW}" == "1" ]] && arg="${arg} --overflow"
  [[ "${WEBLINK}" == "1" ]] && arg="${arg} --www"
  [[ "${COLOUR}" != "1" ]] && arg="${arg} --colour"
  [[ "${EDBID}" == "1" ]] && arg="${arg} --id"

  ## Try and remove terms that could confuse searches
  #software=$( echo "${software}" | sed 's_/_ _g' )
  software=$( echo "${software}" | sed -e 's/[^a-zA-Z0-9]/ /g' )

  if [[ "${VERBOSE}" -eq 1 ]]; then
    ## Loop each word?
    tmp=""
    for word in $( echo ${software} ); do
      ## Add current search term on
      tmp="${tmp}${word} "

      ## Check to see if its any phrases which would give a TON of incorrect results
      validterm "${tmp}" \
        || continue

      ## Feedback
      echo "[i] $0 ${arg} ${tmp}" 1>&2
      out=$( bash "$0" ${arg} ${tmp} )

      ## Are there too many result?
      lines=$( echo -e "${out}" | wc -l )
      if [[ "${lines}" -gt 100 ]]; then
        echo -e "[-] Skipping output: ${tmp}   (Too many results. Please re-search manually: $0 ${arg} ${tmp})\n" 1>&2
      ## Are there any result?
      elif [[ "${lines}" -gt 5 ]]; then
        echo -e "${out}\n\n"
      ## If there's no results
      else
        break
      fi
    done

    ## Padding between loops
    echo -e "\n\n" 1>&2
  else
    ## Check to see if its any phrases which would give a TON of incorrect results
    validterm "${software}" \
      || return

    ## Feedback
    echo "[i] $0 ${arg} ${software}" 1>&2
    out=$( bash "$0" ${arg} ${software} )

    ## Are there too many result?
    lines=$( echo -e "${out}" | wc -l )
    if [[ "${lines}" -gt 100 ]]; then
      echo -e "[-] Skipping output: ${software}   (Too many results. Please re-search manually: $0 ${arg} ${software})\n" 1>&2
    ## Are there any result?
    elif [[ "${lines}" -gt 5 ]]; then
      echo -e "${out}\n\n"
    fi
  fi
}


## Read XML file
function nmapxml()
{
  ## Remove any old traces
  rm -f /tmp/searchsploit.{tmp,out}

  ## Feedback to the end user
  echo -e "[i] Reading: '${FILE}'\n"

  ## Read in XMP (IP, name, service and version)
  xmllint --xpath '//address/@addr|//service/@name|//service/@product|//service/@version' "${FILE}" \
    | sed -e $'s/addr=/\\\n[IP] /g; s/name=/\\\n[NAME] /g; s/product=/\\\n[PRODUCT] /g;s/" version="/\\\n[VERSION] /g; s/"//g' \
    | grep -v '\[IP\].*\:' \
    | while read line; do
      type=$( echo "${line}" | cut -d" " -f 1 )
      input=$( echo "${line}" | cut -d" " -f 2- )

      case "${type}" in
        "[IP]")
          #[[ "${VERBOSE}" -eq 1 ]] && echo -e "\n\n\e[32m[*] IP: ${input}\e[39m" 1>&2
          ;;
        "[NAME]")
          ## If we have already looped around and got something, save it before moving onto the current value
          if [[ "${software}" ]]; then
            #searchsploitout
            echo "${software}" >> /tmp/searchsploit.out
          fi
          ## Something is better than nothing. Will just go on the default service that matches the port.   e.g. domain
          software="${input}"
          ## Might not get any more than this, if -sV failed
          echo "${software}" > /tmp/searchsploit.tmp
          ;;
        "[PRODUCT]")
          ## We have a name, but no version (yet?)   e.g. dnsmasq
          software="${input}"
          echo "${software}" > /tmp/searchsploit.tmp
          ;;
        "[VERSION]")
          software="${software} ${input}"
          ## Name & version. There isn't any more information to get, game over.   e.g. dnsmasq 2.72
          echo "${software}" >> /tmp/searchsploit.out
          echo "" > /tmp/searchsploit.tmp
          ;;
      esac
  done

  ## Read in from file (so there are no duplicates - ...but unable to print out IPs)
  cat /tmp/searchsploit.out /tmp/searchsploit.tmp 2>/dev/null | tr '[:upper:]' '[:lower:]' | awk '!x[$0]++' | while read software; do
    searchsploitout
  done
}


## Build search terms
function buildterms()
{
  tag="${1}"

  ## If we are to use colour ("--colour"), add the values to search for between "or"
  if [[ "${COLOUR}" -eq 1 ]]; then
    if [[ "${COLOUR_TAG}" ]]; then
      COLOUR_TAG="${COLOUR_TAG}|"
    fi
    COLOUR_TAG="${COLOUR_TAG}${tag}"
  fi

  ## Search both title AND path
  if [[ "${FILEPATH}" -eq 1 ]]; then
    ## Search command for each term (with case sensitive flag, "-c")
    SEARCH="${SEARCH} | grep ${COLOUR_OFF_GREP} -F ${CASE_TAG_GREP} \"${tag}\""
  ## Search just the title, NOT the path ("-t"/"-e")
  else
    ## If there is already a value, prepend text to get ready
    if [[ "${AWK_SEARCH}" ]]; then
      AWK_SEARCH="${AWK_SEARCH}/ && ${CASE_TAG_FGREP}(\$2) ~ /"
    fi

    ## Escape any slashes
    tag="$( echo ${tag} | sed 's_/_\\/_g' )"

    ## Case sensitive ("-c")?
    if [[ "${SCASE}" -eq 1 ]]; then
      AWK_SEARCH="${AWK_SEARCH}${tag}"
    else
      AWK_SEARCH="${AWK_SEARCH}$( echo ${tag} | tr '[:upper:]' '[:lower:]' )"
    fi
  fi
}


## Check for empty args
if [[ $# -eq 0 ]]; then
  usage >&2
fi


## Parse long arguments
ARGS="-"
for param in "$@"; do
  if [[ "${param}" == "--case" ]]; then
    SCASE=1
  elif [[ "${param}" == "--exact" ]]; then
    EXACT=1
  elif [[ "${param}" == "--examine" ]] || [[ "${param}" == "--open" ]] || [[ "${param}" == "--view" ]]; then
    GETPATH=1
    EXAMINE=1
  elif [[ "${param}" == "--help" ]]; then
    usage >&2
  elif [[ "${param}" == "--json" ]]; then
    JSON=1
  elif [[ "${param}" == "--mirror" ]] || [[ "${param}" == "--copy" ]] || [[ "${param}" == "--dup" ]] || [[ "${param}" == "--duplicate" ]]; then
    GETPATH=1
    MIRROR=1
  elif [[ "${param}" == "--overflow" ]]; then
    OVERFLOW=1
  elif [[ "${param}" == "--path" ]]; then
    GETPATH=1
    CLIPBOARD=1
  elif [[ "${param}" == "--title" ]]; then
    FILEPATH=0
  elif [[ "${param}" == "--update" ]]; then
    update
  elif [[ "${param}" == "--www" ]]; then
    WEBLINK=1
  elif [[ "${param}" == "--colour" ]] || [[ "${param}" == "--color" ]]; then
    COLOUR=""
  elif [[ "${param}" == "--id" ]]; then
    EDBID=1
  elif [[ "${param}" == "--nmap" ]]; then
    XML=1
  elif [[ "${param}" =~ "--exclude=" ]]; then
    EXCLUDE="$( echo "${param}" | cut -d '=' -f 2- )"
  elif [[ "${param}" == "--verbose" ]]; then
    VERBOSE=1
  else
    if [[ "${param:0:1}" == "-" ]]; then
      ARGS=${ARGS}${param:1}
      shift
      continue
    fi
    TAGS="${TAGS} ${param//\`/_}"
  fi
done


## Parse short arguments
while getopts "cehjmnoptuvwx" arg "${ARGS}"; do
  if [[ "${arg}" = "?" ]]; then
    usage >&2;
  fi
  case ${arg} in
    c) SCASE=1;;
    e) EXACT=1;;
    h) usage >&2;;
    j) JSON=1;;
    m) GETPATH=1; MIRROR=1;;
    n) XML=1;;
    o) OVERFLOW=1;;
    p) GETPATH=1; CLIPBOARD=1;;
    t) FILEPATH=0;;
    u) update;;
    v) VERBOSE=1;;
    w) WEBLINK=1;;
    x) GETPATH=1; EXAMINE=1;;
  esac
  shift $(( OPTIND - 1 ))
done


## If we cannot find files.csv
if [[ ! -f "${csvpath}" ]]; then
  echo "[!] Could not find: ${csvpath}"
  exit 1
fi


## Read in XML
if [[ "${XML}" -eq 1 ]]; then
  ## Trim white spaces
  FILE=$( echo ${TAGS} | xargs )

  ## Is there a file?
  if [[ ! -f "${FILE}" ]]; then
    echo -e "\n[!] Could not find file: ${FILE}" 1>&2
    exit 1
  fi

  if ! hash xmllint 2>/dev/null; then
    echo -e "\n[!] Please install xmllint" 1>&2
    echo -e "[i]   Kali Linux -> apt -y install libxml2-utils" 1>&2
    exit 1
  fi

  if [[ "${VERBOSE}" -ne 1 ]]; then
    echo "[i] SearchSploit's XML mode (without verbose enabled)"
  fi

  ## Do the magic
  nmapxml

  ## Done
  exit 0
fi


## Print the full path. If pbcopy/xclip is available then copy to the clipboard
if [[ "${GETPATH}" -eq 1 ]]; then
  for exploit in $( echo ${TAGS} ); do
    ## Get EDB-ID from input
    edbdb="$( echo ${exploit} | rev | cut -d '/' -f1 | rev | cut -d'.' -f1 | tr -dc '0-9' )"

    ## Check files.csv
    location=$( cut -d ',' -f 2 "${csvpath}" | grep -m 1 -E "/${edbdb}(\..*)?$" )
    title=$( grep -m 1 "${location}" "${csvpath}" | cut -d ',' -f 3 | sed 's/"//g' )

    ## Join paths
    location="${gitpath}/${location}"

    ## Did we find the exploit?
    if [[ -f "${location}" ]]; then
      ## Display out
      echo "Exploit: ${title}"
      echo "    URL: https://www.exploit-db.com/exploits/${edbdb}/"
      echo "   Path: ${location}"
      echo ""

      ## Copy to clipboard?
      if [[ "${CLIPBOARD}" -eq 1 ]]; then
        ## Are any copy programs available?
        if hash xclip 2>/dev/null || hash pbcopy 2>/dev/null; then
          ## Linux (Will require $DISPLAY)
          if hash xclip 2>/dev/null; then
            echo -ne "${location}" | xclip -selection clipboard 2>/dev/null
            echo "Copied EDB-ID #${edbdb}'s path to the clipboard."
          ## OSX
          elif hash pbcopy 2>/dev/null; then
            echo -ne "${location}" | pbcopy
            echo "Copied EDB-ID #${edbdb}'s path to the clipboard."
          fi
        fi

        ## Done (early!)
        exit 0
      fi

      ## Open the exploit up?
      if [[ "${EXAMINE}" -eq 1 ]]; then
        if [[ "${PAGER}" ]]; then
          /bin/sh -c "${PAGER} ${location}"
        elif [[ -f "$( which pager 2>/dev/null )" ]]; then
          pager "${location}"
        else
          less "${location}"
        fi
        echo -e "\n"
      fi

      if [[ "${MIRROR}" -eq 1 ]]; then
        cp -i "${location}" "$( pwd )/"
        echo "Copied to: $( pwd )/$( basename ${location} )"
        echo -e "\n"
      fi
    else
      ## Feedback
      echo "Could not find EDB-ID #${edbdb}"
      echo -e "\n"
    fi
  done

  ## Done
  exit 0
fi


## If we are doing an exact match ("-e")? If so, do NOT check folder path (Implies "-t").
if [[ "${EXACT}" -eq 1 ]]; then
  FILEPATH=0
fi


## Case sensitive?
if [[ "${SCASE}" -eq 1 ]]; then
  ## Remove the default flags
  CASE_TAG_GREP=""
  CASE_TAG_FGREP=""
fi


## Dynamically set column widths to the current screen size
if [[ "${WEBLINK}" -eq 1 ]]; then
  COL2=45
else
  COL2=$(( ${#gitpath} + 15 ))
fi
COL1=$(( $( tput cols ) - COL2 - 1 ))

## Remove leading space
TAGS="$( echo ${TAGS} | sed -e 's/^[[:space:]]//' )"

## Print header if NOT in JSON ("--json")
if [[ "${JSON}" -eq 0 ]]; then
  drawline
  printf "%-${COL1}s %s" " Exploit Title"
  if [[ "${WEBLINK}" -eq 1 ]]; then
    echo "|  URL"
  elif [[ "${EDBID}" -eq 1 ]]; then
    echo "|  EDB-ID"
  else
    echo "|  Path"
    printf "%-${COL1}s "
    echo "| (${gitpath}/)"
  fi
  drawline
## Print JSON header
else
  echo "{"
  printf "\t\"SEARCH\": \"${TAGS}\",\n"
  printf "\t\"DB_PATH\": \"${gitpath}\",\n"
  printf "\t\"RESULTS\": [\n"
fi


## JSON require full options
if [[ "${JSON}" -eq 1 ]]; then
  ## Read in id, title, path, type, date, platform separated between commas
  SEARCH="awk -F '[,]' '{print \$1\",\"\$3\",\"\$2\",\"\$4\",\"\$6\",\"\$7}' \"${csvpath}\""
else
  ## Read in id, title and path, separated between commas (as these are the only visible fields)
  SEARCH="awk -F '[,]' '{print \$1\",\"\$3\",\"\$2}' \"${csvpath}\""
fi

## EXACT search command ("-e")?
if [[ "${EXACT}" -eq 1 ]]; then
 buildterms "${TAGS}"
## or AND search command?
else
  ## For each term
  for TAG in ${TAGS}; do
    buildterms "${TAG}"
  done
fi


## If we are NOT to use the path name ("-t"/"-e")
if [[ "${FILEPATH}" -eq 0 ]]; then
  SEARCH="${SEARCH} | awk -F '[,]' '${CASE_TAG_FGREP}(\$2) ~ /${AWK_SEARCH}/ {print}'"
fi


## If we are to use colour ("--colour"), add the value here
if [[ "${COLOUR_TAG}" ]] && [[ "${JSON}" -eq 0 ]]; then
  COLOUR_TAG="grep ${COLOUR_ON_GREP} -iE \"${COLOUR_TAG}|$\""
fi


## Search, format, and print results
if [[ "${OVERFLOW}" -eq 1 ]]; then
  FORMAT=${COL1}
else
  FORMAT=${COL1}'.'${COL1}
fi


## Strip un-wanted values
SEARCH="${SEARCH} | sed 's/\"//g'"


## Remove any terms not wanted from the search
if [[ "${EXCLUDE}" ]]; then
  SEARCH="${SEARCH} | grep -vEi '${EXCLUDE}'"
fi


## Magic search Fu
## Print JSON format (full options) ("--json")?
if [[ "${JSON}" -eq 1 ]]; then
  ## Web link format ("--www")?
  if [[ "${WEBLINK}" -eq 1 ]]; then
    OUTPUT="$( eval ${SEARCH} \
      | awk -F ',' '{ printf "\\r\\t\\t'{'\"Exploit\":\"%s\",\"URL\":\"https://www.exploit-db.com/exploits/%s/\"},\n", $2, $1 }' ) "
  ## Just the EDB-ID ("--id")?
  elif [[ "${EDBID}" -eq 1 ]]; then
    OUTPUT="$( eval ${SEARCH} \
      | awk -F ',' '{ printf "\\r\\t\\t'{'\"Exploit\":\"%s\",\"EDB-ID\":\"%s\"},\n", $2, $1 }' ) "
  ## Default JSON
  else
    OUTPUT="$( eval ${SEARCH} \
      | awk -F ',' '{ printf "\\r\\t\\t'{'\"Exploit\":\"%s\",\"Platform\":\"%s\",\"Type\":\"%s\",\"Date\":\"%s\",\"Path\":\"'${gitpath}/'%s\",\"EDB-ID\":\"%s\"},\n", $2, $5, $6, $4, $3, $1 }' ) "
  fi
  OUTPUT="$( echo -e ${OUTPUT} \
    | sort \
    | sed '$ s/,$//g' )"
## Web link format ("--www")?
elif [[ "${WEBLINK}" -eq 1 ]]; then
  OUTPUT="$( eval ${SEARCH} \
    | awk -F ',' '{ printf "%-'${FORMAT}'s | %s\n", $2, "https://www.exploit-db.com/exploits/"$1"/"}' \
    | sort )"
## Just the EDB-ID ("--id")?
elif [[ "${EDBID}" -eq 1 ]]; then
  OUTPUT="$( eval ${SEARCH} \
    | awk -F ',' '{ printf "%-'${FORMAT}'s | %s\n", $2, $1 }' \
    | sort )"
## Default view
else
  OUTPUT="$( eval ${SEARCH} \
    | awk -F ',' '{ printf "%-'${FORMAT}'s | %s\n", $2, $3 }' \
    | sort )"
fi


## Display colour highlights ("--colour")?
if [[ "${COLOUR_TAG}" ]] && [[ "${JSON}" -eq 0 ]]; then
  [[ "${OUTPUT}" ]] && OUTPUT=$( echo -e "${OUTPUT}" | eval ${COLOUR_TAG} )
fi


## Show content
[[ "${OUTPUT}" ]] && echo "${OUTPUT}"

## Print footer if NOT in JSON ("--json")
if [[ "${JSON}" -eq 0 ]]; then
  drawline
## Print JSON footer
else
  printf "\t]\n"
  echo "}"
fi


## Done
exit 0