Skip to content

Instantly share code, notes, and snippets.

@IPlayZed
Created December 6, 2024 13:19
Show Gist options
  • Save IPlayZed/32defda4cf4b68073a3055043391fae5 to your computer and use it in GitHub Desktop.
Save IPlayZed/32defda4cf4b68073a3055043391fae5 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
###############################################################################
#The MIT License (MIT)
#Copyright © 2024 <Börcsök Balázs Róbert, Everbridge EMEA>
#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.
###############################################################################
# Name: rdg_to_rdp.sh
#
# Description:
# This script converts Windows .RDG (Remote Desktop Group) files into separate
# .RDP configuration files. The resulting .RDP files can be easily imported
# into the Microsoft Remote Desktop client on macOS, which does not natively
# support .RDG imports.
#
# How It Works:
# The script reads the specified .RDG file line by line, looking for XML-like
# structures that define "servers." For each server, it extracts important
# fields such as:
# - <name>
# - <displayName>
# - <comment>
# - <userName>
#
# Once a server block (from <server> to </server>) is fully read, the script
# generates an .RDP file in the output directory. The filename is derived
# from the server's displayName (and comment, if present).
#
# After running this script, you can open the Microsoft Remote Desktop client
# on macOS and drag-and-drop the generated .RDP files into it for immediate use.
#
# Requirements:
# - bash
# - awk
#
# Usage:
# ./rdg_to_rdp.sh -f <path_to_rdg_file> [-o <output_directory>]
#
# Options:
# -f <file> Path to the .rdg file to process. (Required)
# -o <output_directory> Output directory (optional). If not specified,
# a directory named "<basename_of_file>_output" will
# be created in the current directory.
# -h Display this help message and exit.
#
# Examples:
# ./rdg_to_rdp.sh -f /path/to/default.rdg
# Processes default.rdg and outputs .RDP files into ./default_output
#
# ./rdg_to_rdp.sh -f /path/to/myservers.rdg -o /tmp/myservers_rdp
# Processes myservers.rdg and outputs the .RDP files into /tmp/myservers_rdp
#
# Autocompletion (Optional):
# To enable option completion, you could create a bash completion script in
# /etc/bash_completion.d/ and source it. A sample snippet is provided at the
# bottom of this script as a comment.
#
###############################################################################
#######################################
# Display usage/help message
#######################################
usage() {
echo "Usage: $0 -f <file> [-o <output_directory>]"
echo ""
echo "Options:"
echo " -f <file> Path to the .rdg file to process. (Required)"
echo " -o <output_directory> Output directory (optional). If not specified,"
echo " a directory named '<basename_of_file>_output' will be created."
echo " -h Display this help message."
echo ""
echo "Examples:"
echo " $0 -f /path/to/default.rdg"
echo " $0 -f /path/to/default.rdg -o /path/to/output_dir"
exit 1
}
#######################################
# Parse command-line arguments
#######################################
while getopts ":f:o:h" opt; do
case "${opt}" in
f)
input_file="${OPTARG}"
;;
o)
output_dir="${OPTARG}"
;;
h)
usage
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
usage
;;
:)
echo "Option -${OPTARG} requires an argument." >&2
usage
;;
esac
done
# Verify that the required input file parameter was provided
if [ -z "${input_file}" ]; then
echo "Error: No input file specified."
usage
fi
# If no output directory is specified, create one based on the input file's basename
if [ -z "${output_dir}" ]; then
base_name=$(basename "${input_file}" .rdg)
output_dir="./${base_name}_output"
fi
# Create the output directory if it doesn't exist
mkdir -p "${output_dir}" || {
echo "Error: Unable to create output directory: ${output_dir}"
exit 1
}
# Change into the output directory
cd "${output_dir}" || {
echo "Error: Unable to enter output directory: ${output_dir}"
exit 1
}
#######################################
# Convert the RDG to RDP files
#
# Logic:
# 1. Initialize variables for server attributes.
# 2. Read each line from the RDG file.
# 3. When encountering <server>, start a new record.
# 4. Extract name, displayName, comment, userName as encountered.
# 5. When encountering </server>, finalize the record and write an .RDP file.
#######################################
name=""
displayName=""
comment=""
userName=""
while read -r line; do
# Detect start of a new server record
if [[ $line == *"<server>"* ]]; then
echo "==== NEW RECORD ===="
name=""
displayName=""
comment=""
userName=""
fi
# Extract the <name> value
if [[ $line == "<name>"* ]]; then
name=$(echo "$line" | awk -F'<name>|</name>' '{print $2}')
echo "name=$name"
fi
# Extract the <displayName> value
if [[ $line == "<displayName>"* ]]; then
displayName=$(echo "$line" | awk -F'<displayName>|</displayName>' '{print $2}')
echo "displayName=$displayName"
fi
# Extract the <comment> value
if [[ $line == "<comment"* ]]; then
comment=$(echo "$line" | awk -F'<comment>|</comment>' '{print $2}')
echo "comment=$comment"
fi
# Extract the <userName> value
if [[ $line == "<userName>"* ]]; then
userName=$(echo "$line" | awk -F'<userName>|</userName>' '{print $2}')
echo "userName=$userName"
fi
# End of server record: Create the RDP file using the extracted values
if [[ $line == "</server>"* ]]; then
# Form the filename from displayName and comment
filename="$(echo "$displayName $comment" | sed 's/[ ]*$//').rdp"
# Write out the RDP file with the captured values
cat > "$filename" <<EOF++
armpath:s:
targetisaadjoined:i:0
hubdiscoverygeourl:s:
redirected video capture encoding quality:i:0
camerastoredirect:s:
gatewaybrokeringtype:i:0
use redirection server name:i:0
alternate shell:s:
disable themes:i:0
disable cursor setting:i:1
remoteapplicationname:s:
resourceprovider:s:
disable menu anims:i:1
remoteapplicationcmdline:s:
promptcredentialonce:i:0
gatewaycertificatelogonauthority:s:
audiocapturemode:i:0
prompt for credentials on client:i:1
gatewayhostname:s:
remoteapplicationprogram:s:
gatewayusagemethod:i:2
screen mode id:i:2
use multimon:i:0
authentication level:i:2
desktopwidth:i:0
desktopheight:i:0
redirectsmartcards:i:0
redirectclipboard:i:1
forcehidpioptimizations:i:0
full address:s:$name
drivestoredirect:s:
loadbalanceinfo:s:
networkautodetect:i:1
enablecredsspsupport:i:1
redirectprinters:i:0
autoreconnection enabled:i:1
session bpp:i:32
administrative session:i:0
audiomode:i:0
bandwidthautodetect:i:1
authoring tool:s:
connection type:i:7
remoteapplicationmode:i:0
disable full window drag:i:0
gatewayusername:s:
shell working directory:s:
wvd endpoint pool:s:
remoteapplicationappid:s:
username:s:$userName
allow font smoothing:i:1
connect to console:i:0
disable wallpaper:i:0
gatewayaccesstoken:s:
EOF++
echo "Created: $filename"
fi
done < "${input_file}"
#######################################
# Optional: Bash completion snippet
#
# To enable completion for this script, save the following into a file
# (e.g., /etc/bash_completion.d/rdg_to_rdp) and then source it or restart your shell.
#
# _rdg_to_rdp_completions() {
# local cur prev opts
# COMPREPLY=()
# cur="${COMP_WORDS[COMP_CWORD]}"
# prev="${COMP_WORDS[COMP_CWORD-1]}"
# opts="-f -o -h"
#
# if [[ ${cur} == -* ]]; then
# COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
# return 0
# fi
# }
# complete -F _rdg_to_rdp_completions rdg_to_rdp.sh
#
#######################################
# End of script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment