Function Logging_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        :   Logging_Services

    Description :   Handler program for all module related services.

    Notes       :   The generic parameters should contain all the necessary information to process the services. Often
                    this will be information like the data Record and Key ID.

    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

                 

    History     :   (Date, Initials, Notes)
        08/30/17    dmb     Original programmer.
        02/17/18    dmb     [SRPFW-225] Use the new named cache feature of Memory_Services so logging data is 
                            protected when other processes release a cache table.
        05/07/18    sgb     [SRPFW-225] Fix bug in NewLog service by using the LogFullPath variable instead of the
        04/24/20    gac     Modified the AppendLog service to refresh the FielSize if the ColumnHeaders are added.
        05/09/20    dmb     [SRPFW-313] Merged with other versions.
        08/28/24    djm     Add CreateDirectory argument to NewLog service. If set to true, non-existent directories
							will be created if necessary to save the log.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$insert LOGICAL
$insert SERVICE_SETUP
$insert SRPMail_Inserts

Equ     CRLF$       to \0D0A\
Equ     CR$         to \0D\
Equ     LF$         to \0A\
Equ     TAB$        to \09\
Equ     COMMA$      to ','

Common /LoggingServices/ Unused1@, Unused2@, Unused3@, Unused4@, Unused5@, Unused6@, Unused7@, Unused8@

Declare function    Logging_Services, Memory_Services, SRP_Hash, SRP_Path, SRP_Send_Mail, Environment_Services
Declare function	RTI_OS_Directory
Declare subroutine  Logging_Services, Memory_Services,  SetInitDirOptions

GoToService else
	Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end

Return Response OR ''


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN     = True$, False$


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//----------------------------------------------------------------------------------------------------------------------
// NewLog
//
// LogPath          - Path to where the log file is located. - [Required]
// LogFileName      - Name of the log file. - [Required]
// RowDelimiter     - Delimiter used to separate each log row. Default is CR/LF. - [Optional]
// ColumnDelimiter  - Delimiter used to separate each column value. If ColumnWidths is empty then this will default to a
//                    comma. - [Optional]
// ColumnHeaders    - @FM list of Column headers to use in the log file. Default is no column headers will be used.
//                    - [Optional]
// ColumnWidths     - @FM list of Column widths for each column data value. If empty then the entire column value will
//                    be stored. - [Optional]
// QuoteValues      - Boolean flag to indicate if column values should be quoted. Default is false. - [Optional]
// ClearLog         - Boolean flag to indicate if any existing log file should be cleared. Default is false.
//                    - [Optional]
// CreateDirectory    - Boolean flag to indicate if dependent directories should be created. Default is false.
//                    - [Optional]
//
// Returns an object handle to a log file.
//----------------------------------------------------------------------------------------------------------------------
Service NewLog(LogPath, LogFileName, RowDelimiter, ColumnDelimiter, ColumnHeaders, ColumnWidths, QuoteValues=BOOLEAN, ClearLog=BOOLEAN, CreateDirectory=BOOLEAN)
	
	DirectoryCreated = '' 
	objLog           = ''
	If CreateDirectory EQ '' then CreateDirectory = TRUE$ 
	
	If (LogPath NE '') AND (LogFileName NE '') then
		If (SRP_Path('Exists', LogPath) EQ False$) AND (CreateDirectory EQ TRUE$) then
			GoSub CreateDependentDirectories
		end
		If SRP_Path('Exists', LogPath) then
			LogFullPath = SRP_Path('Combine', LogPath, LogFileName)
			If LogFullPath[1, 1] EQ '\' AND LogFullPath[2, 1] NE '\' then LogFullPath = '\' : LogFullPath                                                                                             
			objLog      = SRP_Hash(LogFullPath, 'SHA-1', 'BASE32')
			Memory_Services('SetValue', objLog : '*LogPath', LogPath, ServiceModule)
			Memory_Services('SetValue', objLog : '*LogFileName', LogFileName, ServiceModule)
			Memory_Services('SetValue', objLog : '*LogFullPath', LogFullPath, ServiceModule)
			If Dir(LogFullPath) NE '' then
				If ClearLog then
					Logging_Services('CreateLogFile', objLog)
				end
			end else
				Logging_Services('CreateLogFile', objLog)
			end
			If Error_Services('NoError') then
				If RowDelimiter EQ '' then RowDelimiter = CRLF$
				Memory_Services('SetValue', objLog : '*RowDelimiter', RowDelimiter, ServiceModule)
				If (ColumnDelimiter EQ '') AND (ColumnWidths EQ '') then ColumnDelimiter = COMMA$
				Memory_Services('SetValue', objLog : '*ColumnDelimiter', ColumnDelimiter, ServiceModule)
				Memory_Services('SetValue', objLog : '*ColumnHeaders', ColumnHeaders, ServiceModule)
				Memory_Services('SetValue', objLog : '*ColumnWidths', ColumnWidths, ServiceModule)
				If QuoteValues NE True$ then QuoteValues = False$
				Memory_Services('SetValue', objLog : '*QuoteValues', QuoteValues, ServiceModule)
				If Dir(LogFullPath)<1> EQ 0 AND ColumnHeaders NE '' then
					// Add the column headers since this is a new log file.
					Logging_Services('AppendLog', objLog, ColumnHeaders, '', @FM, True$)
				end
			end
			
		end else
			If CreateDirectory EQ False$ then
				Error_Services('Add', LogPath : ' does not exist.')
			end else
				If (CreateDirectory EQ True$) and (DirectoryCreated EQ False$) then
					Error_Services('Add', LogPath : ' could not be created.')
				end
			end
		end
	end else
		Error_Services('Add', 'LogPath or LogFileName argument was missing from the ' : Service : ' service.')
	end
	
	Response    = objLog
	
end service


//----------------------------------------------------------------------------------------------------------------------
// AppendLog
//
// objLog                   - Object handle to the log file. - [Required]
// LogData                  - Data to be appended to the log file. - [Required]
// IncomingRowDelimiter     - Delimiter used to separate each log row coming in. This allows incoming log data to have
//                            a different delimiter than what will be used in the log file. Default is the RowDelimiter
//                            used for appending the log data. - [Optional]
// IncomingColumnDelimiter  - Delimiter used to separate each column value in the log data. This allows incoming log
//                            data to have a different delimiter than what will be used in the log file. Default is the
//                            column delimiter used to separate the log data or a comma if fixed widths only are
//                            indicated. - [Optional]
// IgnoreColumnHeaders      - Boolean flag to indicate if the service should attempt to add column headers to an empty
//                            log file. Default is false. - [Optional]
// EmailAddresses           - Comma delimited list of email addresses that should be notified when this log is appended.
//                            - [Optional]
// EmailMessage             - Message to be sent to the email addresses.                                                                      
//
// Appends data to the log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service AppendLog(objLog, LogData, IncomingRowDelimiter, IncomingColumnDelimiter, IgnoreColumnHeaders, EmailAddresses, EmailMessage)
	
	If (objLog NE '') AND (LogData NE '') then
		If IgnoreColumnHeaders NE True$ then IgnoreColumnHeaders = False$
		LogFullPath     = Logging_Services('GetLogFullPath', objLog)
		ColumnDelimiter = Logging_Services('GetColumnDelimiter', objLog)
		LenColDel       = Len(ColumnDelimiter)
		ColumnHeaders   = Logging_Services('GetColumnHeaders', objLog)
		ColumnWidths    = Logging_Services('GetColumnWidths', objLog)
		QuoteValues     = Logging_Services('GetQuoteValues', objLog)
		RowDelimiter    = Logging_Services('GetRowDelimiter', objLog)
		If IncomingRowDelimiter EQ '' then IncomingRowDelimiter = RowDelimiter
		If (IncomingColumnDelimiter EQ '') AND (ColumnWidths EQ '') then IncomingColumnDelimiter = ColumnDelimiter
		LenRowDel       = Len(RowDelimiter)
		FileInfo        = Dir(LogFullPath)
		FileSize        = FileInfo<1>
		Status()        = 0
		OutData         = ''
		OSOpen LogFullPath to hFile then
			If (FileSize EQ 0) AND (ColumnHeaders NE '') AND (Not(IgnoreColumnHeaders)) then
				Logging_Services('AppendLog', objLog, ColumnHeaders, @RM, @FM, True$)
				// Need to refresh FileSize to prevent the Column Headers being overwritten - gac 04/24/20
				FileInfo = Dir(LogFullPath)
				FileSize = FileInfo<1>
			end
			For Each RowData in LogData using IncomingRowDelimiter
				If RowData NE '' then
					For Each ColumnData in RowData using IncomingColumnDelimiter setting cPos
						If ColumnWidths NE '' then
							ColumnWidth = ColumnWidths<cPos>
							ColumnData  = ColumnData[1, ColumnWidth] : Str(' ', ColumnWidth - Len(ColumnData))
						end
						If QuoteValues then
							Swap '"' with '""' in ColumnData    ; // Encode the quotes properly.
							ColumnData  = Quote(ColumnData)
						end
						OutData    := ColumnData : ColumnDelimiter
					Next ColumnData
					OutData[Neg(LenColDel), LenColDel]  = ''            ; // Strip off the last column delimiter.
					OutData                            := RowDelimiter  ; // Append a row delimiter.
				end
			Next RowData
			OutData[Neg(LenRowDel), LenRowDel]  = ''    ; // Strip off the last row delimiter.
			If (FileSize NE 0) then OutData = RowDelimiter : OutData    ; // Prepend a row delimiter since there is existing data.
			OSBWrite OutData to hFile at FileSize
			OSError = Status()
			If OSError then
				Error_Services('Add', 'OSBWrite error code ' : OSError : ' in the ' : Service : ' service.')
			end
			OSClose hFile
		end else
			OSError = Status()
			Error_Services('Add', 'OSOpen error code ' : OSError : ' in the ' : Service : ' service.')
		end
		
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	If EmailAddresses NE '' then
		GoSub EmailMessage
	end      
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetLogPath
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the path for the log file associated with the indicated log object handle. This will not include the name of
// the log file itself.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogPath(objLog)
	
	LogPath = ''
	
	If objLog NE '' then
		LogPath = Memory_Services('GetValue', objLog : '*LogPath', '', '', ServiceModule)
		If LogPath EQ '' then
			Error_Services('Add', 'Log path not found in the ' : Service : ' service.')
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = LogPath
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetLogFileName
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the file name for the log file associated with the indicated log object handle. This will not include the
// path to where the log file is located.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogFileName(objLog)
	
	LogFileName = ''
	
	If objLog NE '' then
		LogFileName = Memory_Services('GetValue', objLog : '*LogFileName', '', '', ServiceModule)
		If LogFileName EQ '' then
			Error_Services('Add', 'Log file name not found in the ' : Service : ' service.')
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = LogFileName
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetLogFullPath
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the full path for the log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogFullPath(objLog)
	
	LogFullPath = ''
	
	If objLog NE '' then
		LogFullPath = Memory_Services('GetValue', objLog : '*LogFullPath', '', '', ServiceModule)
		If LogFullPath EQ '' then
			Error_Services('Add', 'Log full path not found in the ' : Service : ' service.')
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = LogFullPath
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetRowDelimiter
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the delimiter to use to separate each row in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetRowDelimiter(objLog)
	
	RowDelimiter    = ''
	
	If objLog NE '' then
		RowDelimiter    = Memory_Services('GetValue', objLog : '*RowDelimiter', '', '', ServiceModule)
		If RowDelimiter EQ '' then
			Error_Services('Add', 'Row delimiter not found in the ' : Service : ' service.')
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = RowDelimiter
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetColumnDelimiter
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the delimiter to use to separate each column in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnDelimiter(objLog)
	
	ColumnDelimiter = ''
	
	If objLog NE '' then
		ColumnDelimiter = Memory_Services('GetValue', objLog : '*ColumnDelimiter', '', '', ServiceModule)
		If ColumnDelimiter EQ '' then
			Error_Services('Add', 'Column delimiter not found in the ' : Service : ' service.')
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = ColumnDelimiter
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetColumnHeaders
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the column headers that should be in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnHeaders(objLog)
	
	ColumnHeaders   = ''
	
	If objLog NE '' then
		ColumnHeaders   = Memory_Services('GetValue', objLog : '*ColumnHeaders', '', '', ServiceModule)
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = ColumnHeaders
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetColumnWidths
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the column widths that should be used to truncate or pad each column in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnWidths(objLog)
	
	ColumnWidths    = ''
	
	If objLog NE '' then
		ColumnWidths    = Memory_Services('GetValue', objLog : '*ColumnWidths', '', '', ServiceModule)
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = ColumnWidths
	
end service


//----------------------------------------------------------------------------------------------------------------------
// GetQuoteValues
//
// objLog   - Object handle to the log file. - [Required]
//
// Returns the flag to indicate whether column values should be quoted or not.
//----------------------------------------------------------------------------------------------------------------------
Service GetQuoteValues(objLog)
	
	QuoteValues = ''
	
	If objLog NE '' then
		QuoteValues = Memory_Services('GetValue', objLog : '*QuoteValues', '', '', ServiceModule)
		If QuoteValues NE True$ then QuoteValues = False$
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
	Response    = QuoteValues
	
end service


//----------------------------------------------------------------------------------------------------------------------
// CreateLogFile
//
// objLog   - Object handle to the log file. - [Required]
//
// Creates (or clears out) a log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service CreateLogFile(objLog)
	
	If objLog NE '' then
		LogFullPath = Logging_Services('GetLogFullPath', objLog)
		If Error_Services('NoError') then
			Status()    = 0
			OSWrite '' to LogFullPath
			Status      = Status()
			If Status GT 0 then
				Error_Services('Add', 'Unable to clear ' : LogFullPath : ' in the ' : Service : ' service.')
			end
		end
	end else
		Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
	end
	
End Service


Service CleanLogFolders(NumDays)
	
	FileExclusionList   = 'Canary.txt':@VM:'Canary.vbs'
	AppRootPath         = Environment_Services('GetApplicationRootPath')
	LogPath             = AppRootPath : '\LogFiles\'
	SetInitDirOptions("D")
	InitDir LogPath:'*'
	FolderList  = DirList()
	// Remove . directory listing
	FolderList  = Delete(FolderList, 1, 0, 0)
	// Remove .. directory listing
	FolderList  = Delete(FolderList, 1, 0, 0)
	Today       = Date()
	SetInitDirOptions("")
	For each Folder in FolderList
		FolderPath = LogPath:Folder:'\'
		InitDir FolderPath:'*'
		FileList   = DirList()
		If FileList NE '' then
			For each Filename in FileList
				Locate FileName in FileExclusionList using @VM setting vPos else
					FilePath      = FolderPath:Filename
					FileInfo      = Dir(FilePath)
					LastWriteDate = FileInfo<2>
					FileAge       = Today - LastWriteDate
					If FileAge GT NumDays then
						OSDelete FilePath
					end
				end
			Next Filename
		end
	Next Folder
	
end service


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

EmailMessage:
	
	Done            = False$
	Error           = False$
	MsgSent         = ''
	
	ConfigFile      = ''
	ConfigFile<1>   = SendUsing_Port$
	ConfigFile<2>   = ''
	ConfigFile<3>   = 25                        ; // Server port
	*ConfigFile<4>   = 'appmail.eu.infineon.com' ; // Mail server
	ConfigFile<4>   = 'mailrelay-external.infineon.com' ; // Mail server
	ConfigFile<5>   = True$                     ; // Authenticate
	ConfigFile<6>   = 'oinotify@infineon.com'   ; // Username
	ConfigFile<7>   = 'oinotify1'               ; // Password
	ConfigFile<8>   = False$                    ; // Use SSL
	
	If EmailMessage EQ '' then
		EmailMessage    = LogData : \0D0A0D0A\ : RetStack()<2>
	end else
		EmailMessage   := \0D0A0D0A\ : LogData : \0D0A0D0A\ : RetStack()<2>
	end
	
	SentFrom    = ''
	SentTo      = ''
	Message     = ''
	Message<1>  = 'AppendLog Message'                   ; // Subject
	Message<2>  = 'oinotify@infineon.com'               ; // From (email address)
	Message<3>  = EmailAddresses                        ; // Send to (email address)
	Message<5>  = ''                                    ; // Blind Carbon Copy (email address)
	Message<6>  = ''                                    ; // Reply To (email address)
	Message<7>  = 'TEXT'                                ; // Content Type (TEXT or HTML)
	Message<8>  = EmailMessage                          ; // Content / Body
	Message<9>  = ''                                    ; // Attachment(s) (path to file name(s))
	
	Result      = SRP_Send_Mail(Message, ConfigFile)
	
return

CreateDependentDirectories:
	
	CreatePath       = True$
	DirectoryCreated = RTI_OS_Directory( 'CREATE', LogPath, CreatePath)
	
return



