open-insight/LSL2/STPROC/FTP_SERVICES.txt
Infineon\Mitchem d32b4b6e82 Add logging of raw PSFTP output for missing file
detections. Changed error parsing to be based on
'ftpadmin' rather than 'ssh_init'
2025-01-27 17:50:38 +01:00

908 lines
48 KiB
Plaintext

Function FTP_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : FTP_Services
Description : Handler program for all FTP services.
Notes : See the following URLs for a list of FTP/SFTP commands:
- http://www.nsftools.com/tips/MSFTP.htm
- https://the.earth.li/~sgtatham/putty/0.70/puttydoc.txt
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
07/10/18 dmb Original programmer.
11/13/24 djm Add ListDirectory service.
01/08/24 djm Changed ListDirectory to preserve host error message and set Error_Services.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert FTP_REQUESTS_EQUATES
$insert NOTIFICATION_EQUATES
Equ CRLF$ to \0D0A\
Equ Tab$ to Char(9)
Declare function FTP_Services, Memory_Services, Logging_Services, SRP_Path, SRP_Decode, RTI_CreateGUID
Declare function Environment_Services, Database_Services, Utility, SRP_Run_Command
Declare subroutine FTP_Services, Memory_Services, Logging_Services, SRP_Run_Command, GetTempPath, GetTempFileName
Declare subroutine Database_Services, RList, Obj_Notes, Shipment_Services
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\FTP'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : '.log'
Headers = 'Logging DTM' : @FM : 'Activity' : @FM : 'Host' : @FM : 'FTP Request ID or Local/Remote File' : @FM : 'Remote Directory' : @FM : 'Error'
ColumnWidths = 20 : @FM : 20 : @FM : 30 : @FM : 75 : @FM : 50 : @FM : 100
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, False$, False$)
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options HOSTS = '10.131.104.18', 'ftp3.vis.com.tw', 'ftp1.towersemi.com', '10.72.176.48', '172.23.28.185', '172.28.150.80'
Options COMMANDS = 'put', 'append', 'get'
Options SERVERS = 'MESSA005', 'MESSA01EC'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SendFile
//
// Host - FTP server name or IP. - [Required]
// LocalFile - Local file to send to the FTP server. - [Required if EncodedData is empty]
// EncodedData - Base64 encoded to send to the FTP server. - [Required if LocalFile is empty]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalDirectory - Required working directory of the local computer. Used with the "lcd" FTP command. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// RemoteFile - Remote file that will be created on the FTP server. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Sends the indicated local file or encoded data to the indicated host.
//----------------------------------------------------------------------------------------------------------------------
Service SendFile(Host=HOSTS, LocalFile, EncodedData, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If (Host NE '') AND ((LocalFile NE '') OR (EncodedData NE '')) then
If LocalFile EQ '' then
// Data to send to the FTP server is coming in as Base64 string rather than a path to a local file. Decode the
// string and create a temp file.
LocalFile = FTP_Services('ConvertEncodedData', EncodedData)
end
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, 'put', SSH)
If Error_Services('NoError') then
FTP_Services('RunScript', ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
end
If EncodedData NE '' then
OSDelete LocalFile
end
end else
Error_Services('Add', 'Host, LocalFile, or EncodedData argument was missing from the ' : Service : ' service.')
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end service
//----------------------------------------------------------------------------------------------------------------------
// AppendFile
//
// Host - FTP server name or IP. - [Required]
// LocalFile - Local file to send to the FTP server. - [Required if EncodedData is empty]
// EncodedData - Base64 encoded to send to the FTP server. - [Required if LocalFile is empty]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalDirectory - Required working directory of the local computer. Used with the "lcd" FTP command. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// RemoteFile - Remote file that will be appended on the FTP server. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Appends the indicated local file or encoded data to the indicated host.
//----------------------------------------------------------------------------------------------------------------------
Service AppendFile(Host=HOSTS, LocalFile, EncodedData, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If (Host NE '') AND ((LocalFile NE '') OR (EncodedData NE '')) then
If LocalFile EQ '' then
// Data to send to the FTP server is coming in as Base64 string rather than a path to a local file. Decode the
// string and create a temp file.
LocalFile = FTP_Services('ConvertEncodedData', EncodedData)
end
If SSH EQ True$ then
// SFTP does not support the append command. To simulate, the file must first be retrieved using the get
// command and then appended locally. The resulting file is then sent back using the put command.
TempFile = FTP_Services('GetTempFile')
If TempFile NE '' then
// Use a temp file to hold the file from the host.
TempFileName = SRP_Path('GetFilename', TempFile)
TempFilePath = SRP_Path('GetDirectory', TempFile)
// The name of the remote file is indicated in the append command or it simply defaults to the local file.
If RemoteFile NE '' then
TempRemoteFile = RemoteFile
end else
TempRemoteFile = LocalFile
end
// Perform the get command. This will put any remote file retrieved into the temp file location.
FTP_Services('GetFile', Host, TempRemoteFile, TempFileName, Username, Password, TempFilePath, RemoteDirectory, '', True$, SSH)
If Error_Services('NoError') then
// Read the remote file and the local file data and append.
OSRead OrigFile from TempFile else OrigFile = ''
OSRead AppendFile from LocalFile else AppendFile = ''
OrigFile := AppendFile
OSWrite OrigFile to LocalFile
// Delete the temp file.
OSDelete TempFile
// Put the newly appended local file to the host server.
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, 'put', SSH)
If Error_Services('NoError') then
FTP_Services('RunScript', ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
end
end
end else
Error_Services('Add', 'Error getting a temp file in the ' : Service : ' service.')
end
end else
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, 'append', SSH)
If Error_Services('NoError') then
FTP_Services('RunScript', ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
end
end
If EncodedData NE '' then
OSDelete LocalFile
end
end else
Error_Services('Add', 'Host, LocalFile, or EncodedData argument was missing from the ' : Service : ' service.')
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end service
//----------------------------------------------------------------------------------------------------------------------
// GetFile
//
// Host - FTP server name or IP. - [Required]
// RemoteFile - Remote file that will be retrieved from the FTP server. - [Required]
// LocalFile - Local file to direct the remote file to. - [Optional]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalDirectory - Required working directory of the local computer. Used with the "lcd" FTP command. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Gets the indicated remote file from the indicated host.
//----------------------------------------------------------------------------------------------------------------------
Service GetFile(Host=HOSTS, RemoteFile, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If (Host NE '') AND (RemoteFile NE '') then
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, 'get', SSH)
If Error_Services('NoError') then
FTP_Services('RunScript', ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
end
end else
Error_Services('Add', 'Host or RemoteFile argument was missing from the ' : Service : ' service.')
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = LocalFile
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end service
//----------------------------------------------------------------------------------------------------------------------
// DeleteFile
//
// Host - FTP server name or IP. - [Required]
// RemoteFile - Remote file that will be retrieved from the FTP server. - [Required]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Deletes the indicated remote file from the indicated host.
//----------------------------------------------------------------------------------------------------------------------
Service DeleteFile(Host=HOSTS, RemoteFile, Username, Password, RemoteDirectory, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = RemoteFile
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If (Host NE '') AND (RemoteFile NE '') then
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, '', Username, Password, '', RemoteDirectory, RemoteFile, 'delete', SSH)
If Error_Services('NoError') then
FTP_Services('RunScript', ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
end
end else
Error_Services('Add', 'Host or RemoteFile argument was missing from the ' : Service : ' service.')
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = RemoteFile
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end service
//----------------------------------------------------------------------------------------------------------------------
// RunScript
//
// ScriptPath - Local directory and/or file name to use for the script file. - [Required]
// Host - FTP server name or IP. Used only for error reporting. - [Optional]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalFile - Local file to direct the remote file to. Used only for error reporting. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. Used only for
// error reporting. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. Used only for error
// reporting. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Runs the indicated FTP script.
//----------------------------------------------------------------------------------------------------------------------
Service RunScript(ScriptPath, Host, Username, Password, LocalFile, RemoteDirectory, DeleteScript, SSH)
If ScriptPath NE '' then
Output = 'VAR' ; // Use when running in production.
* Output = 'DOSOPEN' ; // Use only for debugging the console.
If SSH EQ True$ then
Command = 'psftp'
If Username NE '' then
If Host NE '' then Command := ' ' : Username : '@' : Host
end else
If Host NE '' then Command := ' ' : Host
end
If Password NE '' then
Command := ' -pw ' : Password
end
Command := ' -b ' : ScriptPath
end else
Command = 'ftp -i -n -s:' : ScriptPath
end
SRP_Run_Command(Command, Output, '', '')
If DeleteScript EQ True$ then
OSDelete ScriptPath
end
If Output NE 'DOSOPEN' then
Swap \0D0A\ with @FM in Output
Begin Case
Case IndexC(Output, 'Connection timed out', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Connection timed out: ' : Quote(Host) : '.')
Case IndexC(Output, 'Connection refused', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Connection refused at host: ' : Quote(Host) : '.')
Case IndexC(Output, 'Server unexpectedly closed network connection', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Connection refused at host: ' : Quote(Host) : '.')
Case IndexC(Output, 'File not found', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Local file not found: ' : Quote(LocalFile) : '.')
Case IndexC(Output, 'User cannot log in', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Username or password invalid.')
Case IndexC(Output, 'The system cannot find the file specified', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Remote file cannot be found: ' : Quote(RemoteDirectory) : '.')
Case IndexC(Output, 'No such file or folder', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Remote file cannot be found: ' : Quote(RemoteDirectory) : '.')
Case IndexC(Output, 'open for read: failure', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Remote file cannot be found: ' : Quote(RemoteDirectory) : '.')
Case IndexC(Output, 'unrecognised option', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Unrecognised option.')
Case IndexC(Output, 'The parameter is incorrect', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. A parameter is incorrect.')
Case IndexC(Output, 'failure', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Unknown failure.')
Case IndexC(Output, 'unable to open', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. Local file not found: ' : Quote(LocalFile) : '.')
Case IndexC(Output, 'FATAL ERROR', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. FATAL ERROR: ' : Quote(LocalFile) : '.')
Case IndexC(Output, 'Access Denied', 1) ; Error_Services('Add', 'Error in ' : Service : ' service. FATAL ERROR: ' : Quote(LocalFile) : '.')
End Case
end
end else
Error_Services('Add', 'ScriptPath argument was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// CreateScript
//
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// Host - FTP server name or IP. - [Optional]
// LocalFile - Local file to send to the FTP server. - [Optional]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalDirectory - Required working directory of the local computer. Used with the "lcd" FTP command. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// RemoteFile - Remote file that will be created on the FTP server. - [Optional]
// Command - FTP file command. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
//
// Creates a script file based on the indicated arguments. This will be writen to the resulting script path.
//----------------------------------------------------------------------------------------------------------------------
Service CreateScript(ScriptPath, Host, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, Command=COMMANDS, SSH)
// First, create the script list of commands based on the indicated arguments.
Script = ''
If SSH EQ True$ then
// PSFTP requires credentials to be entered in the command line rather than in the script.
end else
If Host NE '' then Script := 'open ' : Host : @FM
If Username NE '' then
Script := 'user' : @FM
Script := Username : @FM
end
If Password NE '' then
Script := Password : @FM
end
end
If LocalDirectory NE '' then
Script := 'lcd ' : LocalDirectory : @FM
end
If RemoteDirectory NE '' then
Script := 'cd ' : RemoteDirectory : @FM
end
Begin Case
Case Command _EQC 'put' OR Command _EQC 'append'
If SSH EQ True$ then
Script := 'put'
If Command _EQC 'append' then
Script := ' -append'
end
Script := ' ' : LocalFile
end else
Script := command : ' ' : LocalFile
end
If RemoteFile NE '' then
Script := ' ' : RemoteFile
end
Case Command _EQC 'get'
Script := command : ' ' : RemoteFile
If LocalFile NE '' then
Script := ' ' : LocalFile
end
Case Command _EQC 'delete'
If SSH EQ True$ then
Script := 'del ' : RemoteFile
end else
Script := command : ' ' : RemoteFile
end
Case Command _EQC 'list'
Script := 'ls '
If RemoteFile NE '' then
Script := ' ' : RemoteFile
end
End Case
Script := @FM
Script := 'quit'
Swap @FM with CRLF$ in Script
// Second, validate the script path. Use the specific directory and/or filename provided in the ScriptPath argument
// if possible. Otherwise use temp names.
ScriptDirectory = ''
ScriptFile = ''
If ScriptPath NE '' then
If SRP_Path('IsDirectory', ScriptPath) then
// Directory is valid, which means no filename.
ScriptDirectory = ScriptPath
end else
// Check to see if there is a directory with a filename.
ScriptDirectory = SRP_Path('GetDirectory', ScriptPath)
If SRP_Path('IsDirectory', ScriptDirectory) then
ScriptFile = SRP_Path('GetFilename', ScriptPath)
end else
ScriptDirectory = ''
ScriptFile = ScriptPath
end
end
end
If ScriptDirectory EQ '' then
ScriptDirectory = Str(\00\, 1024)
GetTempPath(Len(ScriptDirectory), ScriptDirectory)
Convert \00\ to '' in ScriptDirectory
end
If ScriptFile EQ '' then
ScriptFile = Str(\00\, 1024)
GetTempFileName(ScriptDirectory : \00\, \00\, 0, ScriptFile)
OSDelete ScriptFile
ScriptPath = SRP_Path('RenameExtension', ScriptFile, 'scr')
end else
ScriptPath = SRP_Path('Combine', ScriptDirectory, ScriptFile)
end
// Finally, create the script file in the indicated ScriptPath.
Status() = 0
OSWrite Script to ScriptPath
If Status() then
Error_Services('Add', 'Error creating ' : ScriptPath : ' in the ' : Service : ' service. Description: ' : Field('Bad OS filename.,Access denied by operating system.,Disk or directory full.,File does not exist.,Unknown error.,Attempt to write to a read-only file.', ',', Status()))
end
Response = ScriptPath
end service
//----------------------------------------------------------------------------------------------------------------------
// ConvertEncodedData
//
// EncodedData - Base64 encoded data. - [Required]
//
// Converts Base64 encoded data to plaint text and writes to a temporary file.
//----------------------------------------------------------------------------------------------------------------------
Service ConvertEncodedData(EncodedData)
LocalFile = ''
If EncodedData NE '' then
Data = SRP_Decode(EncodedData, 'BASE64')
If Data NE '' then
LocalFile = FTP_Services('GetTempFile')
If LocalFile NE '' then
OSWrite Data to LocalFile
If Status() then
Error_Services('Add', 'Error creating ' : LocalFile : ' in the ' : Service : ' service. Description: ' : Field('Bad OS filename.,Access denied by operating system.,Disk or directory full.,File does not exist.,Unknown error.,Attempt to write to a read-only file.', ',', Status()))
end
end else
Error_Services('Add', 'Error getting a temp file in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'Error decoding the EncodedData argument in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'EncodedData argument was missing from the ' : Service : ' service.')
end
Response = LocalFile
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTempFile
//
// Returns the path to a newly created temporary file.
//----------------------------------------------------------------------------------------------------------------------
Service GetTempFile()
TempFile = ''
TempDirectory = Str(\00\, 1024)
GetTempPath(Len(TempDirectory), TempDirectory)
Convert \00\ to '' in TempDirectory
TempFile = Str(\00\, 1024)
GetTempFileName(TempDirectory : \00\, \00\, 0, TempFile)
Response = TempFile
end service
//----------------------------------------------------------------------------------------------------------------------
// PostRequest
//
// Command - FTP file command. - [Required]
// Host - FTP server name or IP. - [Required]
// Server - Name of the local server responsible for processing this FTP request. - [Required]
// LocalFile - Local file to send to the FTP server. - [Required if EncodedData is empty]
// EncodedData - Base64 encoded to send to the FTP server. - [Required if LocalFile is empty]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// LocalDirectory - Required working directory of the local computer. Used with the "lcd" FTP command. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// RemoteFile - Remote file that will be created on the FTP server. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
// ProcessDirectory - Local direcotry to move the local file into after it has been sent to the FTP server. - [Optional]
// NumberAttempts - Number of attempts that should be made to process this request before quitting. Default is 1.
// - [Optional]
// DeleteLocalFile - Boolean flag to indicate if the local file should be deleted after the request has been processed.
// Default is False. - [Optional]
//
// Posts the FTP request into the FTP_REQUESTS database table for future processing.
//----------------------------------------------------------------------------------------------------------------------
Service PostRequest(Command=COMMANDS, Host=HOSTS, Server=SERVERS, LocalFile, EncodedData, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN, ProcessDirectory, NumberAttempts, DeleteLocalFile)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = Command : ' ' : LocalFile
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
FTPRequestID = ''
If (Command NE '') AND (Host NE '') AND (Server NE '') AND ((LocalFile NE '') OR (EncodedData NE '')) then
RequestDate = Date()
RequestTime = Time()
FTPRequestID = RequestDate : '-' : RequestTime : '-'
SeqCounter = 1 ; // Start the counter always at 1
Loop
HaveLock = Database_Services('GetKeyIDLock', 'FTP_REQUESTS', FTPRequestID : SeqCounter, False$)
If HaveLock EQ True$ then
FTPRequest = Database_Services('ReadDataRow', 'FTP_REQUESTS', FTPRequestID : SeqCounter)
If Error_Services('NoError') then
// FTP request already exists. Unlock the Key ID and attempt the next sequential counter.
Database_Services('ReleaseKeyIDLock', 'FTP_REQUESTS', FTPRequestID : SeqCounter)
HaveLock = False$
end else
// Clear the error as this means the FTP request does not exist.
Error_Services('Clear')
end
end
Until HaveLock OR Error_Services('HasError')
SeqCounter += 1
Repeat
If Error_Services('NoError') then
FTPRequestID := SeqCounter
FTPRequestRow = ''
FTPRequestRow<FTP_REQUESTS.REQUEST_DATE$> = RequestDate
FTPRequestRow<FTP_REQUESTS.REQUEST_TIME$> = RequestTime
FTPRequestRow<FTP_REQUESTS.FTP_COMMAND$> = Command
FTPRequestRow<FTP_REQUESTS.HOST$> = Host
FTPRequestRow<FTP_REQUESTS.LOCAL_FILE$> = LocalFile
FTPRequestRow<FTP_REQUESTS.ENCODED_DATA$> = EncodedData
FTPRequestRow<FTP_REQUESTS.USERNAME$> = Username
FTPRequestRow<FTP_REQUESTS.PASSWORD$> = Password
FTPRequestRow<FTP_REQUESTS.LOCAL_DIRECTORY$> = LocalDirectory
FTPRequestRow<FTP_REQUESTS.REMOTE_DIRECTORY$> = RemoteDirectory
FTPRequestRow<FTP_REQUESTS.REMOTE_FILE$> = RemoteFile
FTPRequestRow<FTP_REQUESTS.SCRIPT_PATH$> = ScriptPath
FTPRequestRow<FTP_REQUESTS.DELETE_SCRIPT$> = DeleteScript
FTPRequestRow<FTP_REQUESTS.SSH$> = SSH
FTPRequestRow<FTP_REQUESTS.PROCESS_DIRECTORY$> = ProcessDirectory
FTPRequestRow<FTP_REQUESTS.SERVER$> = Server
If NumberAttempts LE 0 then NumberAttempts = 1
FTPRequestRow<FTP_REQUESTS.NUMBER_OF_ATTEMPTS$> = NumberAttempts
If DeleteLocalFile NE True$ then DeleteLocalFile = False$
FTPRequestRow<FTP_REQUESTS.DELETE_LOCAL_FILE$> = DeleteLocalFile
Database_Services('WriteDataRow', 'FTP_REQUESTS', FTPRequestID, FTPRequestRow, True$, False$, True$)
If Error_Services('NoError') then
Database_Services('ReleaseKeyIDLock', 'FTP_REQUESTS', FTPRequestID)
end
end
end else
Error_Services('Add', 'Command, Host, Server, LocalFile, or EncodedData argument was missing from the ' : Service : ' service.')
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = Command : ' ' : LocalFile : ' : ' : FTPRequestID
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
Response = FTPRequestID
end service
//----------------------------------------------------------------------------------------------------------------------
// ProcessRequest
//
// FTPRequestID - Key ID to the FTP_REQUESTS database table. - [Required]
//
// Processes the FTP request specified by the FTPRequestID.
//----------------------------------------------------------------------------------------------------------------------
Service ProcessRequest(FTPRequestID)
If (FTPRequestID NE '') then
FTPRequestRow = Database_Services('ReadDataRow', 'FTP_REQUESTS', FTPRequestID)
If Error_Services('NoError') then
Server = FTPRequestRow<FTP_REQUESTS.SERVER$>
* If Server EQ 'MESSA01EC' THEN Debug
ThisServer = Environment_Services('GetServer')
If Server _EQC ThisServer then
// This is the designated server to process this request.
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = ''
LogData<4> = FTPRequestID
LogData<5> = ''
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
RequestDate = FTPRequestRow<FTP_REQUESTS.REQUEST_DATE$>
RequestTime = FTPRequestRow<FTP_REQUESTS.REQUEST_TIME$>
Command = FTPRequestRow<FTP_REQUESTS.FTP_COMMAND$>
Host = FTPRequestRow<FTP_REQUESTS.HOST$>
LocalFile = FTPRequestRow<FTP_REQUESTS.LOCAL_FILE$>
EncodedData = FTPRequestRow<FTP_REQUESTS.ENCODED_DATA$>
Username = FTPRequestRow<FTP_REQUESTS.USERNAME$>
Password = FTPRequestRow<FTP_REQUESTS.PASSWORD$>
LocalDirectory = FTPRequestRow<FTP_REQUESTS.LOCAL_DIRECTORY$>
RemoteDirectory = FTPRequestRow<FTP_REQUESTS.REMOTE_DIRECTORY$>
RemoteFile = FTPRequestRow<FTP_REQUESTS.REMOTE_FILE$>
ScriptPath = FTPRequestRow<FTP_REQUESTS.SCRIPT_PATH$>
DeleteScript = FTPRequestRow<FTP_REQUESTS.DELETE_SCRIPT$>
SSH = FTPRequestRow<FTP_REQUESTS.SSH$>
ProcessDirectory = FTPRequestRow<FTP_REQUESTS.PROCESS_DIRECTORY$>
DeleteLocalFile = FTPRequestRow<FTP_REQUESTS.DELETE_LOCAL_FILE$>
Begin Case
Case Command _EQC 'put'
FTP_Services('SendFile', Host, LocalFile, EncodedData, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, ScriptPath, DeleteScript, SSH)
Case Command _EQC 'append'
FTP_Services('AppendFile', Host, LocalFile, EncodedData, Username, Password, LocalDirectory, RemoteDirectory, RemoteFile, ScriptPath, DeleteScript, SSH)
Case Command _EQC 'get'
FTP_Services('GetFile', Host, RemoteFile, LocalFile, Username, Password, LocalDirectory, RemoteDirectory, ScriptPath, DeleteScript, SSH)
Case Command _EQC 'delete'
FTP_Services('DeleteFile', Host, RemoteFile, Username, Password, RemoteDirectory, ScriptPath, DeleteScript, SSH)
End Case
If Error_Services('NoError') then
Result = 'Success'
Shipment_Services('ClearMONACritical', 'FILE_TRANSMISSION')
If (ProcessDirectory NE '') AND (LocalFile NE '') then
// Move the local file to the process directory.
ProcessFile = SRP_Path('Combine', ProcessDirectory, SRP_Path('GetFilename', LocalFile))
// Work around for the Combine service. This has been fixed, but not yet installed at Infineon.
If ProcessFile[1, 1] EQ '\' And ProcessFile[1, 2] NE '\' then ProcessFile = '\' : ProcessFile
Success = Utility('COPYFILE', LocalFile, ProcessFile)
If (Success EQ True$) AND (DeleteLocalFile EQ True$) then
OSDelete LocalFile
end
end else
If DeleteLocalFile EQ True$ then
OSDelete LocalFile
end
end
end else
Result = Error_Services('GetMessage')
Shipment_Services('SetMONACritical', 'FILE_TRANSMISSION', Result)
Recipients = XLATE('NOTIFICATION','COC_DELIVERY',NOTIFICATION_USER_ID$,'X')
SendFrom = 'System'
Subject = 'COC FTP Delivery Failue.'
AttachWindow = ''
AttachKey = ''
SendToGroup = ''
MessageParms = Recipients:@RM:SendFrom:@RM:Subject:@RM:Result:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',MessageParms)
end
// Update the FTP request with the latest attempt details.
AttemptCount = FTPRequestRow<FTP_REQUESTS.ATTEMPT_COUNT$>
AttemptCount += 1
FTPRequestRow<FTP_REQUESTS.ATTEMPT_COUNT$> = AttemptCount
FTPRequestRow<FTP_REQUESTS.ATTEMPT_DATE$, AttemptCount> = Date()
FTPRequestRow<FTP_REQUESTS.ATTEMPT_TIME$, AttemptCount> = Time()
FTPRequestRow<FTP_REQUESTS.RESULT$, AttemptCount> = Result
Database_Services('WriteDataRow', 'FTP_REQUESTS', FTPRequestID, FTPRequestRow, True$, False$, True$)
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = ''
LogData<4> = FTPRequestID
LogData<5> = ''
LogData<6> = Result
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end
end
end else
Error_Services('Add', 'FTPRequestID argument was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ProcessRequests
//
// Processeses the pending FTP requests.
//----------------------------------------------------------------------------------------------------------------------
Service ProcessRequests()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
rv = Set_Status(0)
RowCount = 0
// 11/02/18 - djs
// Use new select statement when deploying new OBJ_SAP build, which uses FTP_SERVICES
// to ensure that we process the FTP requests in chronological order.
SelectStatement = 'SELECT FTP_REQUESTS WITH STATUS EQ "Pending" BY REQUEST_ID'
*SelectStatement = 'SELECT FTP_REQUESTS WITH STATUS EQ "Pending"'
RList(SelectStatement, 5)
If (@List_Active EQ 3) AND (@RecCount GT 0) then
EOF = False$
Loop
ReadNext FTPRequestID else EOF = True$
Until EOF EQ True$
FTP_Services('ProcessRequest', FTPRequestID)
Repeat
end
ClearSelect 0
Unlock hSysLists, ServiceKeyID else Null
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ListDirectory
//
// Host - FTP server name or IP. - [Required]
// Query - Specify wildcard query. - [Optional]
// Username - Username to authenticate against the FTP server. - [Optional]
// Password - Password to authenticate against the FTP server. - [Optional]
// RemoteDirectory - Required working directory of the remote computer. Used with the "cd' FTP command. - [Optional]
// ScriptPath - Local directory and/or file name to use for the script file. - [Optional]
// DeleteScript - Boolean flag to indicate if the script file should be deleted after being ran. - [Optional]
// SSH - Boolean flag to indicate if SSH (Secure FTP) is required. Default is False. - [Optional]
// OutputPath - Path to output file list to file. - [Optional]
//
// Gets the indicated remote file from the indicated host. Functions as 'mls' command.
//----------------------------------------------------------------------------------------------------------------------
Service ListDirectory(Host=HOSTS, Username, Password, RemoteDirectory, Query, ScriptPath, DeleteScript=BOOLEAN, SSH=BOOLEAN, OutputPath)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = 'Start ' : Service
LogData<3> = Host
LogData<4> = ''
LogData<5> = RemoteDirectory
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If (Host NE '') AND (RemoteDirectory NE '') then
ScriptPath = FTP_Services('CreateScript', ScriptPath, Host, '', Username, Password, '', RemoteDirectory, Query, 'list', SSH)
If Error_Services('NoError') then
If SSH EQ True$ then
Command = 'psftp'
If Username NE '' then
If Host NE '' then Command := ' ' : Username : '@' : Host
end else
If Host NE '' then Command := ' ' : Host
end
If Password NE '' then
Command := ' -pw ' : Password
end
Command := ' -b ' : ScriptPath
end else
Command = 'ftp -i -n -s:' : ScriptPath
end
DirectoryList = SRP_Run_Command(Command, 'VAR')
If Count(DirectoryList, 'ftpadmin') NE 0 then
Gosub LsToMls
end else
Error_Services('Add', DirectoryList)
end
Response = DirectoryList
If OutputPath NE '' then
OutputDirectoryList = DirectoryList
Swap @FM with CRLF$ in OutputDirectoryList
OSWrite OutputDirectoryList to OutputPath
end
end
end else
Error_Services('Add', 'Host or RemoteFile argument was missing from the ' : Service : ' service.')
end
If DeleteScript EQ True$ then
OSDelete ScriptPath
end
ServiceError = Error_Services('GetMessage')
LogData<1> = LoggingDTM
LogData<2> = 'Stop ' : Service
LogData<3> = Host
LogData<4> = ''
LogData<5> = RemoteDirectory
LogData<6> = Error_Services('GetMessage')
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Error_Services('Set', ServiceError)
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// LsToMls
//
// Parse output of ls command to remove directory paths and other unneccessary metadata. Functions as mls command.
//----------------------------------------------------------------------------------------------------------------------
LsToMls:
OldDirectoryList = DirectoryList
DirectoryList = ''
// Skip the first period because it is related to username.
FileCount = Count(OldDirectoryList, '.') - 1
// Index starts at 5 because that CRLF$ Field is the first containing a file name.
FieldIndex = 5
For FileIndex = 1 to FileCount
FileName = Field(OldDirectoryList, CRLF$, FieldIndex)
SpaceCount = DCount(FileName, ' ')
FileName = Field(FileName, ' ', SpaceCount)
DirectoryList<-1> = FileName
FieldIndex += 1
Next FileIndex
return