# $language = "Python" # $interface = "1.0" # SaveSelectedTextToFile.py # # Last Modified: # 20 Jan, 2023: # - Initial revision in python # # Description: # If non-whitespace text is selected within the terminal screen, the user # will be prompted for a location + filename in which to store the selected # text as a CSV file. # # This script uses the crt.Dialog.FileSaveDialog method, which was first # available in SecureCRT version 8.5 - therefore the minimum version with # which this script will work: 8.5 # # Demonstrates: # - How to use the Screen.Selection property to access text selected # within the terminal window. # - Using SecureCRT's FileSaveDialog() method to display a file "Save As" # chooser interface. # - One way to use python's csv module to write CSV data to a file, when # using python 3 as the script engine. import os, re, datetime, sys # g_strMode is used only if the user specifies a file that already exists, in # which case the user will be prompted to overwrite the existing file, append # to the existing file, or cancel the operation. g_strMode = "" # Be "tab safe" by getting a reference to the tab in which this script is # running: g_objTab = crt.GetScriptTab() # --------------------------------------------------------------------- def SaveSelectedTextToCSVFile(): global g_objTab, g_strMode # Capture the selected text into a variable. The 'Selection' property # is available in SecureCRT 6.1 and later. This line of code will cause # an error if launched in a version of SecureCRT prior to v6.1. strSelection = g_objTab.Screen.Selection # Check to see if the selection really has any text to save... we don't # usually want to write out an empty file. if strSelection.strip() == "": crt.Dialog.MessageBox("Nothing to save!") return strTimeDate = datetime.datetime.now().strftime("%Y%m%d_%H%M%S.%f")[:19] strBasename = g_objTab.Session.RemoteAddress if g_objTab.Session.RemoteAddress == "": strBasename = "{}_{}.csv".format( g_objTab.Session.Config.GetOption("Protocol Name"), strTimeDate) else: strBasename = "{}_{}.csv".format( g_objTab.Session.RemoteAddress, strTimeDate) strFilename = os.path.join(os.path.expanduser("~"), "Documents", strBasename) BUTTON_YESNOCANCEL = 3 IDYES = 6 IDNO = 7 BUTTON_RETRYCANCEL = 5 IDRETRY = 4 while True: strFilename = crt.Dialog.FileSaveDialog( "Save as CSV File", "Save", strFilename, "CSV Files (*.csv)|*.csv|Text Files (*.txt)|*.txt||") if strFilename == "": return # Do some sanity checking if the file specified by the user already # exists... if os.path.isfile(strFilename): nResult = crt.Dialog.MessageBox( "Do you want to replace the contents of \"" + strFilename + "\" with the selected text?\n\n" + "\tYes = overwrite\n\n" + "\tNo = append\n\n" + "\tCancel = end script", "Replace Existing File?", BUTTON_YESNOCANCEL) if nResult == IDYES: g_strMode = "w" break elif nResult == IDNO: g_strMode = "a" break else: return else: g_strMode = "w" break # Automatically append a .csv if the filename supplied doesn't include # any extension. if os.path.splitext(strFilename)[1] == "": strFilename += ".csv" import codecs # open the file with "utf-8-sig" as the encoding, since # this is what most spreadsheet apps like Excel, etc. # expect. with codecs.open(strFilename, g_strMode, "utf-8-sig") as file: if sys.version.split(".")[0] == "2": # With python 2, we roll our own csv writer to avoid encoding # errors should the selected text contain any UNICODE characters. # Replace instances of one or more space characters with a comma. # Use a regular expression sub() method to perform this task. The # pattern below means "one or more sequential space characters". strPattern = "[ ]+" strCSVData = re.sub(strPattern, ",", strSelection) for strRow in strCSVData.splitlines(): if not "\n" in strRow: strRow += "\n" file.write(strRow) else: # With python 3, use python's built-in csv.writer object import csv objCSVWriter = csv.writer(file, lineterminator="\n") for strRow in strSelection.splitlines(): objCSVWriter.writerow(strRow.split()) strMode = "Wrote" if g_strMode == "a": strMode = "Appended" # Get information about the file we just wrote # so we can report how many bytes were written: objStatInfo = os.stat(strFilename) crt.Dialog.MessageBox( "{} {} bytes to file: {}".format( strMode, objStatInfo.st_size, strFilename)) # Now open the CSV file in the default .csv file application # handler... OpenPathInDefaultApp(strFilename) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def OpenPathInDefaultApp(strFile): global g_objTab import subprocess strPlatform = sys.platform g_objTab.Session.SetStatusText("Platform: {0}".format(strPlatform)) crt.Sleep(200) try: if sys.platform.startswith('darwin'): subprocess.call(('open', strFile)) elif strPlatform == "win32": os.startfile(strFile) elif sys.platform.startswith('linux'): subprocess.call(('xdg-open', strFile)) else: crt.Dialog.MessageBox( "Unknown operating system: {0}".format(os.name)) except Exception as objErr: crt.Dialog.MessageBox( ("Failed to open {0} with the default app.\n\n" + str(objErr).replace('\\\\', '\\').replace('u\'', '\'')).format(strFile)) SaveSelectedTextToCSVFile()