
' // ***************************************************************************
' // 
' // Copyright (c) Microsoft Corporation.  All rights reserved.
' // 
' // Microsoft Deployment Toolkit Solution Accelerator
' //
' // File:      ZTIDataAccess.vbs
' // 
' // Version:   6.3.8456.1000
' // 
' // Purpose:   Common Routines for Database Access
' // 
' // Usage:     
' // 
' // ***************************************************************************

option Explicit


Class Database

	Private sIniFile
	Private sSection
	Private dicSQLData
	Private oConn

	Private Sub Class_Initialize

		Dim sFoundIniFile
		Dim iRetVal


		' Create a dictionary object to hold the SQL info and initialize it

		Set dicSQLData = CreateObject("Scripting.Dictionary")
		dicSQLData.CompareMode = TextCompare

		dicSQLData("Order") = Array()
		dicSQLData("Parameters") = Array()

		Set oConn = Nothing

	End Sub


	Public Property Let IniFile(sIni)

		Dim sFoundIniFile
		Dim iRetVal


		' Figure out where the CustomSettings.ini file is

		sIniFile = sIni
		If Len(sIniFile) = 0 then
			iRetVal = oUtility.FindFile("CustomSettings.ini", sIniFile)
			If iRetVal <> Success then
				oLogging.CreateEntry "Unable to find CustomSettings.ini, rc = " & iRetVal, LogTypeError
				Exit Property
			End If
			oLogging.CreateEntry "Using DEFAULT VALUE: Ini file = " & sIniFile, LogTypeInfo
		Else
			If not oFSO.FileExists(sIniFile) then
				iRetVal = oUtility.FindFile(sIniFile, sFoundIniFile)
				If iRetVal = Success then
					sIniFile = sFoundIniFile
				End If
			End If
			oLogging.CreateEntry "Using specified INI file = " & sIniFile, LogTypeInfo
		End If

		If Not oFSO.FileExists(sIniFile) then
			oLogging.CreateEntry "Specified INI file does not exist (" & sIniFile & ").", LogTypeError
			Exit Property
		End If

	End Property


	Public Property Let SectionName(sSect)

		Dim iRetVal, re, sElement
		Dim arrSQLDataKeys, sTmpVal
		Dim arrParameters

		iRetVal = Failure
		Set re = new regexp
		re.IgnoreCase = True
		re.Global = True



		' Substitute for any variables in the section name

		sSection = oEnvironment.Substitute(sSect)
		oLogging.CreateEntry "CHECKING the [" & sSection & "] section", LogTypeInfo


		' Get the "normal" values

		dicSQLData("Table") = ""
		dicSQLData("StoredProcedure") = ""
		arrSQLDataKeys = Array("SQLServer", "Instance", "Port", "Database", "Netlib", "Table", "StoredProcedure", "DBID", "DBPwd", "SQLShare", "ParameterCondition")
		for each sElement in arrSQLDataKeys
			sTmpVal = oUtility.ReadIni(sIniFile, sSection, sElement)
			if Len(sTmpVal) = 0 then
				oLogging.CreateEntry sElement & " key not defined in the section [" & sSection & "]", LogTypeInfo
			else
				dicSQLData(sElement) = oEnvironment.Substitute(sTmpVal)
				if Instr(UCase(sElement),"PWD") > 0 then
					oLogging.CreateEntry "Using from [" & sSection & "]: " & sElement & " = ********", LogTypeInfo
				else
					oLogging.CreateEntry "Using from [" & sSection & "]: " & sElement & " = " & sTmpVal, LogTypeInfo
				end if
			end if
		next


		' Handle "Parameters" differently

		sTmpVal = oUtility.ReadIni(sIniFile, sSection, "Parameters")
		If Len(sTmpVal) = 0 then
			oLogging.CreateEntry "No parameters to include in the SQL call were specified", LogTypeInfo
			arrParameters = Array()
		Else
			arrParameters = Split(sTmpVal, ",")
		End If
		dicSQLData("Parameters") = arrParameters


		' Handle "Order" differently

		sTmpVal = oUtility.ReadIni(sIniFile, sSection, "Order")
		If Len(sTmpVal) = 0 then
			arrParameters = Array()
		Else
			arrParameters = Split(sTmpVal, ",")
		End If
		dicSQLData("Order") = arrParameters


		' Make sure required values were specified

		If Len(dicSQLData("SQLServer")) = 0 then
			oLogging.CreateEntry "ERROR - SQLServer NOT defined in the section [" & sSection & "]", LogTypeError
			Exit Property
		End If

		If Len(dicSQLData("Database")) = 0 then
			oLogging.CreateEntry "Database not defined in the section [" & sSection & "]. Using default (BDDAdminDB).", LogTypeInfo
			dicSQLData("Database") = "BDDAdminDB"
		End If
		If Len(dicSQLData("Table")) = 0 and Len(dicSQLData("StoredProcedure")) = 0 then
			oLogging.CreateEntry "Warning - Neither Table or StoredProcedure defined in the section [" & sSection & "]. Using default Table = BDDAdminCore", LogTypeWarning
			dicSQLData("Table") = "BDDAdminCore"
		End If
		If Len(dicSQLData("Netlib")) = 0 then
			oLogging.CreateEntry "Default Netlib of DBNMPNTW (named pipes) will be used for connecting to SQL Server.", LogTypeInfo
			dicSQLData("Netlib") = "DBNMPNTW"
		End If
		If Len(dicSQLData("ParameterCondition")) = 0 then
			oLogging.CreateEntry "Default ParameterCondition 'AND' will be used for building queries with multiple parameters.", LogTypeInfo
			dicSQLData("ParameterCondition") = "AND"
		End If
		If Len(dicSQLData("SQLShare")) = 0 and UCase(dicSQLData("Netlib")) = "DBNMPNTW" then
			oLogging.CreateEntry "SQLShare NOT defined in the section [" & sSection & "], trusted connection may fail if there is not already a connection to the SQL Server.", LogTypeInfo
		End If



		' Was an instance name specified with the SQLServer name?  If so, split them apart

		If Instr(dicSQLData("SQLServer"), "\") > 0 then
			dicSQLData("Instance") = Mid(dicSQLData("SQLServer"), Instr(dicSQLData("SQLServer"), "\") + 1)
			dicSQLData("SQLServer") = Left(dicSQLData("SQLServer"), Instr(dicSQLData("SQLServer"), "\") - 1)
		End If

	End Property


	' SQLServer property

	Public Property Get SQLServer
		If dicSQLData.Exists("SQLServer") then
			SQLServer = dicSQLData("SQLServer")
		Else
			SQLServer = ""
		End if
	End Property

	Public Property Let SQLServer(sSQLServer)
		dicSQLData("SQLServer") = sSQLServer
	End Property


	' Instace property

	Public Property Get Instance
		If dicSQLData.Exists("Instance") then
			Instance = dicSQLData("Instance")
		Else
			Instance = ""
		End if
	End Property

	Public Property Let Instance(sInstance)
		dicSQLData("Instance") = sInstance
	End Property


	' Port property

	Public Property Get Port
		If dicSQLData.Exists("Port") then
			Port = dicSQLData("Port")
		Else
			Port = ""
		End if
	End Property

	Public Property Let Port(sPort)
		dicSQLData("Port") = sPort
	End Property


	' Database property

	Public Property Get Database
		If dicSQLData.Exists("Database") then
			Database = dicSQLData("Database")
		Else
			Database = ""
		End if
	End Property

	Public Property Let Database(sDatabase)
		dicSQLData("Database") = sDatabase
	End Property


	' Netlib property

	Public Property Get Netlib
		If dicSQLData.Exists("Netlib") then
			Netlib = dicSQLData("Netlib")
		Else
			Netlib = ""
		End if
	End Property

	Public Property Let Netlib(sNetlib)
		dicSQLData("Netlib") = sNetlib
	End Property


	' Table property

	Public Property Get Table
		If dicSQLData.Exists("Table") then
			Table = dicSQLData("Table")
		Else
			Table = ""
		End if
	End Property

	Public Property Let Table(sTable)
		dicSQLData("Table") = sTable
	End Property


	' StoredProcedure property

	Public Property Get StoredProcedure
		If dicSQLData.Exists("StoredProcedure") then
			StoredProcedure = dicSQLData("StoredProcedure")
		Else
			StoredProcedure = ""
		End if
	End Property

	Public Property Let StoredProcedure(sStoredProcedure)
		dicSQLData("StoredProcedure") = sStoredProcedure
	End Property


	' DBID property

	Public Property Get DBID
		If dicSQLData.Exists("DBID") then
			DBID = dicSQLData("DBID")
		Else
			DBID = ""
		End if
	End Property

	Public Property Let DBID(sDBID)
		dicSQLData("DBID") = sDBID
	End Property


	' DBPwd property

	Public Property Get DBPwd
		If dicSQLData.Exists("DBPwd") then
			DBPwd = dicSQLData("DBPwd")
		Else
			DBPwd = ""
		End if
	End Property

	Public Property Let DBPwd(sDBPwd)
		dicSQLData("DBPwd") = sDBPwd
	End Property


	' SQLShare property

	Public Property Get SQLShare
		If dicSQLData.Exists("SQLShare") then
			SQLShare = dicSQLData("SQLShare")
		Else
			SQLShare = ""
		End if
	End Property

	Public Property Let SQLShare(sSQLShare)
		dicSQLData("SQLShare") = sSQLShare
	End Property


	' ParameterCondition property

	Public Property Get ParameterCondition
		If dicSQLData.Exists("ParameterCondition") then
			ParameterCondition = dicSQLData("ParameterCondition")
		Else
			ParameterCondition = ""
		End if
	End Property

	Public Property Let ParameterCondition(sParameterCondition)
		dicSQLData("ParameterCondition") = sParameterCondition
	End Property


	' Parameters property

	Public Property Get Parameters
		If dicSQLData.Exists("Parameters") then
			Parameters = Join(dicSQLData("Parameters"), ",")
		Else
			Parameters = ""
		End if
	End Property

	Public Property Let Parameters(sParameters)
		If sParameters = "" then
			dicSQLData("Parameters") = Array()
		Else
			dicSQLData("Parameters") = Split(sParameters, ",")
		End if
	End Property


	' Order property

	Public Property Get Order 
		If dicSQLData.Exists("Order") then
			Order = Join(dicSQLData("Order"), ",")
		Else
			Order = ""
		End if
	End Property

	Public Property Let Order(sOrder)
		If sOrder = "" then
			dicSQLData("Order") = Array()
		Else
			dicSQLData("Order") = Split(sOrder, ",")
		End if
	End Property


	Public Function Connect

		Dim sDSNRef
		Dim sMsg


		' Create a new ADO connection object

		On Error Resume Next
		Set oConn = CreateObject("ADODB.Connection")
		If Err then
			oLogging.CreateEntry "ERROR - Unable to create ADODB.Connection object, impossible to query SQL Server: " & Err.Description & " (" & Err.Number & ")", LogTypeError
			Set Connect = Nothing
			Exit Function
		End If
		On Error Goto 0


		' If a SQLShare value is specified, try to establish a connection

		If Len(dicSQLData("DBID")) = 0 or Len(dicSQLData("DBPwd")) = 0 then
			If Len(dicSQLData("SQLShare")) > 0 then
				oUtility.ValidateConnection "\\" & dicSQLData("SQLServer") & "\" & dicSQLData("SQLShare")
			Else
				oLogging.CreateEntry "No SQLShare value was specified, not possible to establish a secure connection.", LogTypeInfo
			End If
		End If


		' Build the connect string

		sDSNRef = "Provider=SQLOLEDB;OLE DB Services=0;Data Source=" & dicSQLData("SQLServer")

		If Len(dicSQLData("Instance")) > 0 then
			sDSNRef = sDSNRef & "\" & dicSQLData("Instance")
		End If
		If Len(dicSQLData("Port")) > 0 then
			sDSNRef = sDSNRef & "," & dicSQLData("Port")
		End If

		sDSNRef = sDSNRef & ";Initial Catalog=" & dicSQLData("Database") & ";Network Library=" & dicSQLData("Netlib")

		If len(dicSQLData("DBID")) = 0 OR len(dicSQLData("DBPwd")) = 0 then
			oLogging.CreateEntry "OPENING TRUSTED SQL CONNECTION to server " & dicSQLData("SQLServer") & ".", LogTypeInfo
			sDSNRef = sDSNRef & ";Integrated Security=SSPI"
		Else
			oLogging.CreateEntry "OPENING STANDARD SECURITY SQL CONNECTION to server " & dicSQLData("SQLServer") & " using login " & dicSQLData("DBID") & ".", LogTypeInfo
			sDSNRef = sDSNRef & ";User ID=" & dicSQLData("DBID") & ";Password=" & dicSQLData("DBPwd")
		End If


		' Connect to the database

		oLogging.CreateEntry "Connecting to SQL Server using connect string: " & sDSNref, LogTypeInfo
		On Error Resume Next
		oConn.Open sDSNref
		If Err then
			sMsg = Err.Description & " (" & Err.Number & ")"

			CreateEvent 41013, LogTypeError, "ZTI error opening SQL connection: " & sMsg

			iRetVal = Failure
			oLogging.CreateEntry "ZTI error opening SQL Connection: " & sMsg, LogTypeError
			For each objErr in oConn.Errors
				oLogging.CreateEntry "  ADO error: " & objErr.Description & " (Error #" & objErr.Number & "; Source: " & objErr.Source & "; SQL State: " & objErr.SQLState & "; NativeError: " & objErr.NativeError & ")", LogTypeError
			Next
			Err.Clear
			Set Connect = Nothing
			Exit Function
		End If
		On Error Goto 0

		oLogging.CreateEntry "Successfully opened connection to database.", LogTypeInfo



		' Return the connection to the caller

		Set Connect = oConn

	End Function


	Public Property Get Connection

		Set Connection = oConn

	End Property


	Public Function Query

		Dim oRS
		Dim sErrMsg, sSelect, sElement, sColumn, objTmp, bFoundColumn, bFirst
		Dim tmpValue, tmpArray, tmpClause, v, bClauseFirst, objErr
		Dim sMsg
		Dim bValueFound


		' Create ADO recordset object

		On Error Resume Next
		Set oRS = CreateObject("ADODB.Recordset")
		If Err then
			Set Query = Nothing
			oLogging.CreateEntry "ERROR - Unable to create ADODB.Recordset object, impossible to query SQL Server: " & Err.Description & " (" & Err.Number & ")", LogTypeError
			Exit Function
		End If
		On Error Goto 0


		' Build the SQL statement

		If dicSQLData("Table") <> "" then


			sSelect = "SELECT * FROM " & dicSQLData("Table") & " WHERE "
			bFirst = True
			For each sElement in dicSQLData("Parameters")

				sElement = UCase(trim(sElement))

				' Find the column ID to use

				sColumn = TranslateToColumnID(sElement)


				' Find the value to work with

				bValueFound = False
				If oEnvironment.ListItem(sElement).Count > 0 then
					Set tmpValue = oEnvironment.ListItem(sElement)
					For each v in tmpValue.Keys
						If v <> "" then
							bValueFound = true
							Exit For
						End If
					Next
				ElseIf oEnvironment.Item(sElement) <> "" then
					tmpValue = oEnvironment.Item(sElement)
					bValueFound = true
				Else
					tmpValue = ""
				End If

				If bValueFound then

					' Check if an AND/OR is needed

					If not bFirst then
						sSelect = sSelect & " " & dicSQLData("ParameterCondition") & " "
					Else
						bFirst = False
					End If


					' Handle it appropriately

					If IsObject(tmpValue) then  ' It must be a dictionary object
						tmpClause = sColumn & " IN ("
						bClauseFirst = True
						For each v in tmpValue.Keys
							If not bClauseFirst then
								tmpClause = tmpClause & ","
							Else
								bClauseFirst = False
							End If
							tmpClause = tmpClause & "'" & v & "'"
						Next
						sSelect = sSelect & tmpClause & ")"
					Else
						sSelect = sSelect & sColumn & " = '" & tmpValue & "'"

					End If

				End If

			Next

			If bFirst then

				oLogging.CreateEntry "No parameters had non-blank values, adding dummy query clause to force no records.", LogTypeInfo
				sSelect = sSelect & "0=1"

			End If


			' See if we need to sort the results

			If UBound(dicSQLData("Order")) >= 0 then

				sSelect = sSelect & " ORDER BY "

				For each sElement in dicSQLData("Order")

					sElement = Trim(sElement)


					' Find the column ID to use

					sColumn = TranslateToColumnID(sElement)


					' Add the clause

					sSelect = sSelect & sColumn & ", "

				Next


				' Trim the last comma/space

				sSelect = Left(sSelect, Len(sSelect)-2)

			End If

		Else

			' Stored procedure to be added

			sSelect = "EXECUTE " & dicSQLData("StoredProcedure") & " "
			bFirst = True
			For each sElement in dicSQLData("Parameters")

				sElement = UCase(trim(sElement))

				' Find the value to work with

				If oEnvironment.ListItem(sElement).Count > 0 then
					Set tmpValue = oEnvironment.ListItem(sElement)
				ElseIf oEnvironment.Item(sElement) <> "" then
					tmpValue = oEnvironment.Item(sElement)
				Else
					oLogging.CreateEntry "No value specified for parameter '" & sElement & "', stored procedure may return no records.", LogTypeInfo
					tmpValue = ""
				End If


				' Check if an AND is needed

				If not bFirst then
					sSelect = sSelect & ", "
				Else
					bFirst = False
				End If


				' Handle it appropriately

				If IsObject(tmpValue) then
					oLogging.CreateEntry "Only the first " & sElement & " value will be used in the stored procedure call.", LogTypeInfo
					tmpArray = tmpValue.Keys
					sSelect = sSelect & "'" & tmpArray(0) & "'"
				Else
					sSelect = sSelect & "'" & tmpValue & "'"
				End If

			Next

		End If


		' Issue the SQL statement

		oLogging.CreateEntry "About to issue SQL statement: " & sSelect, LogTypeInfo
		On Error Resume Next
		oRS.Open sSelect, oConn, adOpenStatic, adLockReadOnly
		If Err then
			Set Query = Nothing
			oLogging.CreateEntry "ERROR - Opening Record Set (Error Number = " & Err.Number & ") (Error Description: " & Err.Description & ").", LogTypeError
			For each objErr in oConn.Errors
				oLogging.CreateEntry "  ADO error: " & objErr.Description & " (Error #" & objErr.Number & "; Source: " & objErr.Source & "; SQL State: " & objErr.SQLState & "; NativeError: " & objErr.NativeError & ")", LogTypeError
			Next
			oRS.Close
			Err.Clear
			Exit Function
		End If
		On Error Goto 0

		oLogging.CreateEntry "Successfully queried the database.", LogTypeInfo

		Set Query = oRS

	End Function

	Public Function TranslateToColumnID(sElement)

		Dim sColumn

		sColumn = oUtility.ReadIni(sIniFile, sSection, sElement)
		If sColumn = "" then
			sColumn = sElement
		End If

		TranslateToColumnID = sColumn

	End Function

End Class


Class WebService

	Private sIniFile
	Private sSection
	Private sURL
	Private sMethod
	Private arrParameters
	Private bQuiet

	Private Sub Class_Initialize

		' Initialize variables

		arrParameters = Array()
		sMethod = "POST"

	End Sub


	Public Property Let IniFile(sIni)

		Dim sFoundIniFile
		Dim iRetVal


		' Figure out where the CustomSettings.ini file is

		sIniFile = sIni
		If Len(sIniFile) = 0 then
			iRetVal = oUtility.FindFile("CustomSettings.ini", sIniFile)
			If iRetVal <> Success then
				oLogging.CreateEntry "Unable to find CustomSettings.ini, rc = " & iRetVal, LogTypeError
				Exit Property
			End If
			oLogging.CreateEntry "Using DEFAULT VALUE: Ini file = " & sIniFile, LogTypeInfo
		Else
			If not oFSO.FileExists(sIniFile) then
				iRetVal = oUtility.FindFile(sIniFile, sFoundIniFile)
				If iRetVal = Success then
					sIniFile = sFoundIniFile
				End If
			End If
			oLogging.CreateEntry "Using specified INI file = " & sIniFile, LogTypeInfo
		End If

		If Not oFSO.FileExists(sIniFile) then
			oLogging.CreateEntry "Specified INI file does not exist (" & sIniFile & ").", LogTypeError
			Exit Property
		End If

	End Property


	Public Property Let SectionName(sSect)

		Dim sTmpVal



		' Substitute for any variables in the section name

		sSection = oEnvironment.Substitute(sSect)
		oLogging.CreateEntry "CHECKING the [" & sSection & "] section", LogTypeInfo


		' Get the URL

		sURL = oUtility.ReadIni(sIniFile, sSection, "WebService")


		' Get "Parameters"

		sTmpVal = oUtility.ReadIni(sIniFile, sSection, "Parameters")
		If Len(sTmpVal) = 0 then
			oLogging.CreateEntry "No parameters to include in the web service call were specified", LogTypeInfo
			arrParameters = Array()
		Else
			arrParameters = Split(sTmpVal, ",")
		End If

		' Get the Method

		sTmpVal = oUtility.ReadIni(sIniFile, sSection, "Method")
		If Len(sTmpVal) <> 0 then
			sMethod = sTmpVal
		End if


	End Property


	' WebService property

	Public Property Get WebService
		WebService = sURL
	End Property

	Public Property Let WebService(sWebService)
		sURL = sWebService
	End Property


	' Parameters property

	Public Property Get Parameters
		Parameters = Join(arrParameters, ",")
	End Property

	Public Property Let Parameters(sParameters)
		If sParameters = "" then
			arrParameters = Array()
		Else
			arrParameters = Split(sParameters, ",")
		End if
	End Property


	' Method property

	Public Property Get Method
		Method = sMethod
	End Property

	Public Property Let Method(sVal)
		sMethod = UCase(sVal)
	End Property


	' Quiet property

	Public Property Get Quiet
		Quiet = bQuiet
	End Property

	Public Property Let Quiet(bVal)
		bQuiet = bVal
	End Property

	Public Function Query

		Dim oHTTP
		Dim sEnvelope
		Dim sReturn
		Dim oReturn
		Dim oNode
		Dim sElement, sColumn
		Dim tmpValue, tmpArray
		Dim sUserID, sPassword
		Dim iSeverity


		Set oHTTP = CreateObject("MSXML2.ServerXMLHTTP")
		Set oReturn = oUtility.GetMSXMLDOMDocument
		oReturn.setProperty "SelectionLanguage", "XPath"
		If sMethod = "REST" then
			oReturn.setProperty "SelectionNamespaces", "xmlns:d='http://schemas.microsoft.com/ado/2007/08/dataservices'"
		End if
		Set Query = oReturn


		If bQuiet then
			iSeverity = LogTypeInfo
		Else
			iSeverity = LogTypeError
		End if


		' Set timeouts to infinite for name resolution, 60 seconds for connect, send, and receive

		oHTTP.setTimeouts 0, 60000, 60000, 60000


		' Ignore SSL errors (avoids having to deal with certificates)

		oHTTP.SetOption 2, 13056


		' Build the envelope

		For each sElement in arrParameters

			sElement = Trim(sElement)


			' Find the column ID to use

			sColumn = TranslateToColumnID(sElement)
			sElement = UCase(sElement)


			' Find the value to work with

			If oEnvironment.ListItem(sElement).Count > 0 then
				Set tmpValue = oEnvironment.ListItem(sElement)
			ElseIf oEnvironment.Item(sElement) <> "" then
				tmpValue = oEnvironment.Item(sElement)
			Else
				oLogging.CreateEntry "No value specified for parameter '" & sElement & "', web service results could be unpredictable.", LogTypeInfo
				tmpValue = ""
			End If


			' Handle it appropriately

			If IsObject(tmpValue) then
				oLogging.CreateEntry "Only the first " & sElement & " value will be used in the web service call.", LogTypeInfo
				tmpArray = tmpValue.Keys
				If UCase(sMethod) = "REST" then
					sEnvelope = sEnvelope & sColumn & " eq '" & tmpArray(0) & "' and "
				Else
					sEnvelope = sEnvelope & sColumn & "=" & tmpArray(0) & "&"
				End if
			Else
				If UCase(sMethod) = "REST" then
					sEnvelope = sEnvelope & sColumn & " eq '" & tmpValue & "' and "
				Else
					sEnvelope = sEnvelope & sColumn & "=" & tmpValue & "&"
				End If
			End If

		Next

		If Len(sEnvelope) > 0 then

			' For REST, remove the final " and ".  Otherwise, just drop the trailing comma.

			If sMethod = "REST" then
				sEnvelope = Left(sEnvelope, Len(sEnvelope) - 5)
			Else
				sEnvelope = Left(sEnvelope, Len(sEnvelope) - 1)
			End if


			' Attach a suffix to the URL for GET and REST requests

			If UCase(sMethod) = "GET" then
				sURL = sURL & "?" & sEnvelope
			ElseIf UCase(sMethod) = "REST" then
				sURL = sURL & "?$filter=" & sEnvelope & ""
			End if

		End If


		' Issue the web service call
		Dim bNAACred
		Dim iTryIteration
		
		iTryIteration = 0
		bNAACred = oUtility.GetNextNAACred(0)
		
		If Not bNAACred Then
			oLogging.CreateEntry "No NAA credentials specified. Using default.", LogTypeVerbose
		Else
			oLogging.CreateEntry "NAA credentials have been specified.", LogTypeVerbose
		End if
				
		Do While (iTryIteration = 0 Or bNAACred)
		
			sUserID = oEnvironment.Item("UserDomain") & "\" & oEnvironment.Item("UserID")
			sPassword = oEnvironment.Item("UserPassword")

			If UCase(sMethod) = "POST" then
				oLogging.CreateEntry "About to execute web service call using method " & sMethod & " to " & sURL & ": " & sEnvelope, LogTypeVerbose
				oHTTP.open "POST", sURL, False, sUserID, sPassword
				oHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
				On Error Resume Next
				oHTTP.send sEnvelope
			Else
				oLogging.CreateEntry "About to execute web service call using method " & sMethod & " to " & sURL, LogTypeVerbose
				oHTTP.open "GET", sURL, False, sUserID, sPassword
				On Error Resume Next
				oHTTP.send
			End if
			oLogging.CreateEntry " --Attempt #" & CStr(iTryIteration + 1), LogTypeVerbose

			If Err then
				oLogging.CreateEntry "Error executing web service " & sURL & ": " & Err.Description & " (" & Err.Number & ")", iSeverity
				Set Query = Nothing
				Exit Function
			End If
			On Error Goto 0

			iTryIteration = iTryIteration + 1
			
			If oHTTP.status = 200 then
				oLogging.CreateEntry "Response from web service: " & oHTTP.status & " " & oHTTP.StatusText, LogTypeVerbose
				Exit Do
			ElseIf oHTTP.status = 401 And bNAACred Then
				oLogging.CreateEntry "Web service returned unauthorized: " & oHTTP.status & " " & oHTTP.StatusText & vbCrLf & oHTTP.responseText, LogTypeWarning
				bNAACred = oUtility.GetNextNAACred(iTryIteration)
				If bNAACred Then 
					' We will try another account
					Continue
				Else
					' All accounts have been tried and been denied
					oLogging.CreateEntry "All network access accounts failed to be authorized.", LogTypeError
					Set Invoke = Nothing
					Exit Function
				End If
			Else
				oLogging.CreateEntry "Unexpected response from web service: " &	 oHTTP.status & " " & oHTTP.StatusText & vbCrLf & oHTTP.responseText, iSeverity
				Set Query = Nothing
				Exit Function
			End If
		Loop

		' Process the results

		oReturn.loadXML oHTTP.responseText

		oLogging.CreateEntry "Successfully executed the web service.", LogTypeVerbose

	End Function

	Public Function TranslateToColumnID(sElement)

		Dim sColumn

		sColumn = oUtility.ReadIni(sIniFile, sSection, UCase(sElement))
		If sColumn = "" then
			sColumn = sElement
		End If

		TranslateToColumnID = sColumn

	End Function

End Class
