﻿'$$$GSEScript$$$
'Version: 6.20.0.35

Dim szScriptVersion
szScriptVersion = "6.20.0.35"

Dim szCRMVersion
szCRMVersion = "unknown"

' new outputs for 4.31
Dim gseStateExecuted
Dim gseStateNotDelivered
' new outputs for 6.00 queuing
Dim gseStateCreated
Dim gseStateExists
Dim gseStateOk
Dim gseStateSizeExceeded
Dim gseStateDestinationUnreachable
Dim gseStateQueueTimeout
' new output for 6.11 Get DTMF String
Dim gseStateOnlyStopChar

gseStateExecuted                = "49"
gseStateNotDelivered            = "50"
' new outputs for 6.00 queuing
gseStateCreated                 = "51"
gseStateExists                  = "52"
gseStateOk                      = "53"
gseStateSizeExceeded            = "54"
gseStateDestinationUnreachable  = "55"
gseStateQueueTimeout            = "56"
' new output for 6.11 Get DTMF String
gseStateOnlyStopChar            = "57"

Dim tCallStarted
Dim g_bCallAlerted
Dim bCallConnected

Dim g_bStdRiEnabledEx

Dim g_bUseInputVariable             ' If TRUE, gseGetDTMFChar uses the contents of the variable "save input in variable"
g_bUseInputVariable = False         ' instead of the real DTMF input of the phone.

Dim g_ConnectToLastCause            ' This variable to store last PBXCall.ConnectTo
g_ConnectToLastCause = PBXSuccess   ' value.

Dim g_bIsOnHold         ' This variable is used to store call state
g_bIsOnHold = False     ' "True" means that call in "OnHold" state, "False" othervise

g_bCallAlerted = False  ' This variable will set to 'true' if call to destination call was sucessfull
bCallConnected = False

Dim g_PBXConfig
Set g_PBXConfig = PBXScript.CreateObject("IpPbxSrv.PBXConfig")

' associate PBXConfig object with the user Id of the script user, whom script was started
g_PBXConfig.Initialize(PBXUser)

' 5.00: supporting old scripts
Dim g_bUseFromCriteria
g_bUseFromCriteria              = False

' 6.00: supporting old scripts (Parallel Calls)
Dim g_bEnableParallelCalls, g_szParallelNumbers
g_bEnableParallelCalls          = False
g_szParallelNumbers             = ""

' 6.00: QueueManager return codes
Dim QueueManagerResultCreated
Dim QueueManagerResultAlreadyExists
Dim QueueManagerResultNotCreated
Dim QueueManagerResultOK
Dim QueueManagerResultNotOK
Dim QueueManagerResultSizeExceeded

QueueManagerResultCreated        = 0
QueueManagerResultAlreadyExists  = 1
QueueManagerResultNotCreated     = 2
QueueManagerResultOK             = 3
QueueManagerResultNotOK          = 4
QueueManagerResultSizeExceeded   = 5

' COM object for accesing call queuea
Dim g_QueueAccess
g_QueueAccess = Null

' A flag which define if One Way Conference is active or not
Dim g_OneWayConferenceFlag, szOneWayConferenceSuffix
g_OneWayConferenceFlag = False
szOneWayConferenceSuffix = "#owc#"


' Trace levels for PBXScript.OutputTraceEx
const PBXTraceLevelFatal =  1
const PBXTraceLevelError =  2
const PBXTraceLevelWarn  =  3
const PBXTraceLevelInfo  =  4
const PBXTraceLevelInfo2 =  5
const PBXTraceLevelInfo3 =  6

' Device type constants
const PBXDeviceTypeSoftClient  = 1
const PBXDeviceTypePhoneLxxx   = 2
const PBXDeviceTypePhoneSxxx   = 4
const PBXDeviceTypeSIPClient   = 8
const PBXDeviceTypeMobile      = 16
const PBXDeviceTypeH323Client  = 32
const PBXDeviceTypeAll         = &hffffffff


'#include "rulePreProcessing.vbs"
'#include "rulePostProcessing.vbs"
'#include "Functions.vbs"

' **** GSE rule/action parametrization ****

'
' a parameter class
'
Class GSEParameter
    Private m_Name
    Private m_Value
  
    Public Property Let Name(n)
        m_Name = n
    End Property
    
    Public Property Get Name
        Name = m_Name
    End Property

    Public Property Let Value(v)
        m_Value = v
    End Property
    
    Public Property Get Value
        Value = m_Value
    End Property
End Class

'
' a class to encapsulate GSE function params
'
Class GSEParamList
  ' number of parameters
  Private m_Count
  Private m_Current
  
  ' parameter list
  Private m_Params()

  ' return value
  Public m_FunctionResult

  Private Sub Class_Initialize
    ' constructor
    m_FunctionResult = "0" ' use default output
    m_ReservedRef = Null
  End Sub

  ' reserved field to pass any object reference
  ' initialized by Null
  ' could be used by user
  Public m_ReservedRef
  
  Public Property Let Count(n)
    m_Count = n
    m_Current = 1
    ReDim m_Params(n)
  End Property

  Public Property Get Count()
    Count = m_Count
  End Property
  
  Public Property Set Param(idx,v)
    Set m_Params(idx) = v
  End Property

  Public Property Get Param(idx)
    Set Param = m_Params(idx)
  End Property

  ' add parameter
  Public Sub AddParam(name, value)
    Dim newP
    Set newP = new GSEParameter
    newP.Name = name
    newP.Value = value
    Set m_Params(m_Current) = newP
    m_Current = m_Current + 1
  End Sub
  
  ' get parameter value for variable
  Public Function GetParamValueByName(ByVal szParamName, ByVal szDefaultValue)
    Dim nIdx

    nIdx = 1

    Do While (nIdx <= m_Count)
      If (UCase(szParamName) = UCase(m_Params(nIdx).Name)) Then
        ' get parameter value
        Dim szValue, ValType, DefValType
        szValue = m_Params(nIdx).Value
        ValType = VarType(szValue)
        DefValType = VarType(szDefaultValue)
        If ValType <> DefValType Then
          If DefValType = vbBoolean Then
            'if here, so szValue is expected as bool, but was created as string, so adjust it for new script compatibility
            AdjustBoolean szValue
          ElseIf (ValType = vbBoolean) And (szDefaultValue = "True" Or szDefaultValue = "False") Then
            'if here, so szValue is expected as string, but was created as bool, so adjust it for old script compatibility
            szValue = CStr(szValue)
          End If
        End If 
        GetParamValueByName = szValue
        Exit Function
      End If
      nIdx = nIdx + 1
    Loop

    ' use default value for parameter
    GetParamValueByName = szDefaultValue
  End Function

  ' update parameter value
  Public Sub UpdateParamValue(ByVal szParamName, ByVal szNewValue)   
    Dim nIdx

    nIdx = 1

    Do While (nIdx <= m_Count)
      If (UCase(szParamName) = UCase(m_Params(nIdx).Name)) Then
        m_Params(nIdx).Value = szNewValue
        Exit Sub
      End If
      nIdx = nIdx + 1
    Loop
  End Sub

End Class



Sub AdjustBoolean(ByRef bVar)
    If VarType(bVar) = vbString Then
       If bVar = "True" Then
          bVar = True
       Else
          bVar = False
       End If
    End If
End Sub


' Wrapper for some server functions used in callrouting.vbs and GSE rulexxx.vbs/actionxxx.vbs
Function PBXUserIsBusy()
  PBXUserIsBusy = PBXUser.IsBusy
End Function

Sub PBXScriptOutputTrace(szTrace)
  PBXScript.OutputTrace szTrace
End Sub

Function PBXUserLanguageID()
  PBXUserLanguageID = PBXUser.LanguageID
End Function

Function PBXUserDataFolder()
  PBXUserDataFolder = PBXUser.DataFolder
End Function



''''''''''''''
'' Function:
''   PBXCallConnectToWrapper()
'' Description:
''   Wrapper function for all PBXCall.ConnectTo(Ex) calls
'' Parameters:
''   szDestinationAddresses: destination address
''   nTimeOut: timeout
''   bProceedWithDestinationScript: start destination script or not
''   szUserDefinedAlertTone: user-defined alert tone
''   nAbortDTMFDigits: list of supported DTMF digits
''   rDetectedDigit: a varible for storing detected DTMF digits
''   bDeflectionSupport: Support call deflection or not
''   nTimeOutDeflection: timeout (deflection)
''   bProceedWithDestinationScriptDeflection: destination script or not (deflection)
''   szUserDefinedAlertToneDeflection: user-defined alert tone (deflection)
''   nAbortDTMFDigitsDeflection: list of supported DTMF digits (deflection)
''   bWasDeflectionToVoicemail: was deflection to voicemail attempt
''   bTerminateIfProceedWithDeflectionScript: terminate this script if call procced with deflected destination script
'' Return value:
''   PBXCall.ConnectToEx return value
Function PBXCallConnectToWrapper(ByVal szDestinationAddresses, ByVal nTimeOut, ByVal bProceedWithDestinationScript, _
                                 ByVal szUserDefinedAlertTone, ByVal nAbortDTMFDigits, ByRef rDetectedDigit, _
                                 ByVal bDeflectionSupport, _
                                 ByVal nTimeOutDeflection, ByVal bProceedWithDestinationScriptDeflection, _
                                 ByVal szUserDefinedAlertToneDeflection, ByVal nAbortDTMFDigitsDeflection, _
                                 ByRef bWasDeflectionToVoicemail, _
                                 ByVal bTerminateIfProceedWithDeflectionScript, _
                                 ByVal bIncludeMobileDevices)
  Dim retVal
  
  ' paralell calls: add paralell call numbers if we are calling to original destination
  If ( szDestinationAddresses = PBXCall.CalledPartyNumber ) Then
    If (( g_bEnableParallelCalls = True ) And ( Len(g_szParallelNumbers) > 0 ) ) Then
      szDestinationAddresses = szDestinationAddresses & ";" & g_szParallelNumbers
    End If
  End If
  
  ' one way conferece: add suffix if user set one way conference flag
  If ( g_OneWayConferenceFlag ) Then
    szDestinationAddresses = szDestinationAddresses & szOneWayConferenceSuffix
  End If
  
  Dim enumAllowedDeviceType
  
  If bIncludeMobileDevices = True Then enumAllowedDeviceType = PBXDeviceTypeAll Else enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypeMobile

  If InStr(szDestinationAddresses, "NOMEM") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypeMobile: szDestinationAddresses = Replace(szDestinationAddresses, "NOMEM", ""): PBXScript.OutputTrace "Device type changed to: NOMEM"
  If InStr(szDestinationAddresses, "NOH323") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypeH323Client: szDestinationAddresses = Replace(szDestinationAddresses, "NOH323", ""): PBXScript.OutputTrace "Device type changed to: NOH323"
  If InStr(szDestinationAddresses, "NOSWYXIT") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypeSoftClient: szDestinationAddresses = Replace(szDestinationAddresses, "NOSWYXIT", ""): PBXScript.OutputTrace "Device type changed to: NOSWYXIT"
  If InStr(szDestinationAddresses, "NOLxxx") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypePhoneLxxx: szDestinationAddresses = Replace(szDestinationAddresses, "NOLxxx", ""): PBXScript.OutputTrace "Device type changed to: NOLxxx"
  If InStr(szDestinationAddresses, "NOSxxx") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypePhoneSxxx: szDestinationAddresses = Replace(szDestinationAddresses, "NOSxxx", ""): PBXScript.OutputTrace "Device type changed to: NOSxxx"
  If InStr(szDestinationAddresses, "NOSIP") Then enumAllowedDeviceType = PBXDeviceTypeAll And Not PBXDeviceTypeSIPClient: szDestinationAddresses = Replace(szDestinationAddresses, "NOSIP", ""): PBXScript.OutputTrace "Device type changed to: NOSIP"

  If InStr(szDestinationAddresses, "MEMONLY") Then enumAllowedDeviceType = PBXDeviceTypeMobile: szDestinationAddresses = Replace(szDestinationAddresses, "MEMONLY", ""): PBXScript.OutputTrace "Device type changed to: MEMONLY"
  If InStr(szDestinationAddresses, "H323ONLY") Then enumAllowedDeviceType = PBXDeviceTypeH323Client: szDestinationAddresses = Replace(szDestinationAddresses, "H323ONLY", ""): PBXScript.OutputTrace "Device type changed to: H323ONLY"
  If InStr(szDestinationAddresses, "SWYXITONLY") Then enumAllowedDeviceType = PBXDeviceTypeSoftClient: szDestinationAddresses = Replace(szDestinationAddresses, "SWYXITONLY", ""): PBXScript.OutputTrace "Device type changed to: SWYXITONLY"
  If InStr(szDestinationAddresses, "LxxxONLY") Then enumAllowedDeviceType = PBXDeviceTypePhoneLxxx: szDestinationAddresses = Replace(szDestinationAddresses, "LxxxONLY", ""): PBXScript.OutputTrace "Device type changed to: LxxxONLY"
  If InStr(szDestinationAddresses, "SxxxONLY") Then enumAllowedDeviceType = PBXDeviceTypePhoneSxxx: szDestinationAddresses = Replace(szDestinationAddresses, "SxxxONLY", ""): PBXScript.OutputTrace "Device type changed to: SxxxONLY"
  If InStr(szDestinationAddresses, "SIPONLY") Then enumAllowedDeviceType = PBXDeviceTypeSIPClient: szDestinationAddresses = Replace(szDestinationAddresses, "SIPONLY", ""): PBXScript.OutputTrace "Device type changed to: SIPONLY"

  szDestinationAddresses = Replace(szDestinationAddresses, "&", "")
  szDestinationAddresses = Replace(szDestinationAddresses, " ", "")
  
  retVal = PBXCall.ConnectToEx(szDestinationAddresses, nTimeOut, bProceedWithDestinationScript, szUserDefinedAlertTone, nAbortDTMFDigits, rDetectedDigit, CLng(enumAllowedDeviceType))
  PBXScript.OutputTrace "PBXCall.ConnectToEx(" & szDestinationAddresses & "), retVal = " & retVal & " (" & ExtractReturnValue(retVal) & "), rDetectedDigit=[" & rDetectedDigit & "], AllowedDevTypes=" & CLng(enumAllowedDeviceType) & ")"
  
  If ( bDeflectionSupport = True ) And (retVal = PBXCallTermDeflected) Then
    If ( PBXCall.DeflectionAddress = "voicemail" ) Then
      bWasDeflectionToVoicemail = True
    Else
      bWasDeflectionToVoicemail = False
    End If
    retVal = ConnectToDeflectionAddress(nTimeOutDeflection, bProceedWithDestinationScriptDeflection, szUserDefinedAlertToneDeflection, nAbortDTMFDigitsDeflection, rDetectedDigit)
    If ( retVal = PBXDestinationScriptStarted ) Then
      If ( bTerminateIfProceedWithDeflectionScript = True) Then
         PBXScript.OutputTrace "Script terminated because it call proceed by deflection script"
         PBXCallConnectToWrapper = retVal
         PBXScript.EndScript()
         Exit Function
      End If
    End If
    PBXScript.OutputTrace "PBXCall.ConnectToEx (deflection), retVal = " & retVal & " (" & ExtractReturnValue(retVal) & "), rDetectedDigit=[" & rDetectedDigit & "]"
  End If

  g_ConnectToLastCause = retVal
  
  ' Bugfix 2348: Script post processing support
  If (retVal = PBXSuccess) Then
    bCallConnected = True
  End If
  
  PBXCallConnectToWrapper = retVal
End Function

''''''''''''''
'' Function:
''   ConnectToDeflectionAddress()
'' Description:
''   Connect the call to deflection address
'' Parameters:
''   nTimeOut: timeout
''   bProceedWithDestScript: start destination script or not
''   szAnnouncementSound: user-defined alert tone
''   szAbortDTMFDigits: list of supported DTMF digits
''   rszDetectedDigit: a varible for storing detected DTMF digits
'' Return value:
''   PBXCall.ConnectToEx return value
Function ConnectToDeflectionAddress(ByVal nTimeout, ByVal bProceedWithDestScript, ByVal szAnnouncementSound, _
                                    ByVal szAbortDTMFDigits, ByRef rszDetectedDigit)
  Dim retVal
  Dim retDummy

  TraceFunction "ConnectToDeflectionAddress", PBXCall.DeflectionAddress & ", " & nTimeout & ", " & _
                 bProceedWithDestScript & ", " & szAnnouncementSound   & ", " & szAbortDTMFDigits
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If
  
  If PBXCall.DeflectionAddress = "voicemail" Then
	Set retDummy = new GSEParamList
	
	retDummy.Count = 0
	actionStandardVoicemail retDummy
	
    PBXScript.OutputTrace "Raw return value: " & retDummy.m_FunctionResult

    Select Case retDummy.m_FunctionResult
      Case gseStateTrue
        retVal = PBXSuccess
      Case gseStateTimeout
        retVal = PBXTimeout
      Case gseStateNoAnswer
        retVal = PBXCallTermDestinationBusy
      Case gseStateNotDelivered
        retVal = PBXCallTermConnectToCallerImpossible
      Case gseStateDisconnected
        retVal = PBXCallTermOriginatorDisconnected
      Case Else
        retVal = PBXFailure
    End Select

    PBXScript.OutputTrace "ConnectToDeflectionAddress (voicemail), retVal = " & retVal & " (" & ExtractReturnValue(retVal) & ")"

    ConnectToDeflectionAddress = retVal
    Exit Function
  End If

  If szAnnouncementSound = "*hold*" Then
    retVal = PBXCall.ConnectToEx(PBXCall.DeflectionAddress, nTimeout, bProceedWithDestScript, "##holdmusic#", szAbortDTMFDigits, rszDetectedDigit)
  Else
    retVal = PBXCall.ConnectToEx(PBXCall.DeflectionAddress, nTimeout, bProceedWithDestScript, szAnnouncementSound, szAbortDTMFDigits, rszDetectedDigit)
  End If

  If (retVal = PBXSuccess) Then
    bCallConnected = True
  End If

  PBXScript.OutputTrace "ConnectToDeflectionAddress, retVal = " & retVal & " (" & ExtractReturnValue(retVal) & ")"

  ConnectToDeflectionAddress = retVal
End Function



' **** Standard handling for incoming calls ****
Function CheckAndHandleSpecialCall(ByRef bSkipPostProcessing)

  Dim szMagicStringRIPhone, szMagicStringConf, szMagicStringCFU, szMagicStringRI, szMagicStringCallVMToNum
  Dim szMagicStringCallIntrusion1, szMagicStringCallIntrusion2, szMagicStringCallIntrusion3
  Dim szMagicStringDirCall
  Dim szFeatureCodeRI, szFeatureCodeCallMyself, szFeatureCodeCallVMDirect
  Dim szFeatureCodeCFUon, szFeatureCodeCFBSon, szFeatureCodeCFNRon
  Dim szFeatureCodeCFUoff1, szFeatureCodeCFBSoff1, szFeatureCodeCFNRoff1
  Dim szFeatureCodeCFUoff2, szFeatureCodeCFBSoff2, szFeatureCodeCFNRoff2
  Dim szFeatureCodeCFUotherUser, szFeatureCodeRIotherUser, szFeatureCodePrefix
  Dim szDialedNumber, retDummy, pDummy, pDummyV, szDestination, nCount, nPos, szPIN, szNumber

  tCallStarted = PBXUser.Now
  
  ' trace script version
  PBXScript.OutputTrace "Template.vbs version: " & szScriptVersion & _
                        ", Functions.vbs version: " & szFunctionsVersion & _
                        ", CRM version: " & szCRMVersion
  
  ' load remote inquiry and parallel call paramers from server
  If (szCRMVersion <> "unknown") Then
    ' script created with new version of CRM/GSE - load parameters from server
    g_bStdRiEnabledEx = PBXUser.RIEnabled
    ' leave string value for old script compatibility
    If (g_bStdRiEnabledEx) Then
      g_bStdRiEnabled = "True"
    Else
      g_bStdRiEnabled = "False"
    End If
    g_szStdRiServerName = PBXUser.RIServername
    g_szStdRiUserName = PBXUser.RIUsername
    g_szStdRiPassword = PBXUser.RIPassword
    g_szStdRiMailFolder = PBXUser.RIFolder
    If (PBXUser.RIUseSSL) Then
      g_bStdRiUseSSL = True
    Else
      g_bStdRiUseSSL = False
    End If
    If (PBXUser.RIUsePIN) Then
      g_bStdRiUsePINPrompt = True
    Else
      g_bStdRiUsePINPrompt = False
    End If
    g_szStdRiPIN = PBXUser.RIPIN
    If (PBXUser.RIUseFromAddress) Then
      g_bUseFromCriteria = True
    Else
      g_bUseFromCriteria = False
    End If
    If (PBXUser.EnableParallelCall) Then
      g_bEnableParallelCalls = True
    Else
      g_bEnableParallelCalls = False
    End If
    g_szParallelNumbers = PBXUser.ParallelCallNumbers
    PBXScript.OutputTrace "RI/PL parameters loaded: " & _
                            g_bStdRiEnabledEx & "," & _
                            g_szStdRiServerName & "," & _
                            g_szStdRiUserName & "," & _
                            "XXX" & "," & _
                            g_szStdRiMailFolder & "," & _
                            g_bStdRiUseSSL & "," & _
                            g_bStdRiUsePINPrompt & "," & _
                            "XXX" & "," & _
                            g_bUseFromCriteria & "," & _
                            g_bEnableParallelCalls & "," & _
                            g_szParallelNumbers
  Else
    ' parameters are from older version
    AdjustBoolean g_bStdRiUseSSL
    AdjustBoolean g_bStdRiUsePINPrompt
    AdjustBoolean g_bUseFromCriteria
    AdjustBoolean g_bEnableParallelCalls
  End If

  szMagicStringRIPhone        = "##remoteinquiry#"&PBXCall.CalledPartyNumber
  szMagicStringConf           = "##conference#"
  szMagicStringCallIntrusion1 = "*24*1#"
  szMagicStringCallIntrusion2 = "*24*2#"
  szMagicStringCallIntrusion3 = "*24*3#"
  szMagicStringCFU            = "*8*"
  szMagicStringRI             = "*9*"
  szMagicStringCallVMToNum    = "*71*"
  szMagicStringDirCall        = "*72*"
  
  ' ##10	    	Remote Inquiry	
  ' ##20nnn#		Call Forwarding unconditional to n	If nnn is missing, CFU is deactivated, 
  '                     		                        if nnn = *, CFU to Voicemail is activated
  ' ##21nnn#		Call Forwarding busy to n	        If nnn is missing, CFBS is deactivated, 
  '                      		                        if nnn = *, CFBS to Voicemail is activated
  ' ##22nnn#		Call Forwarding no reply to n	    	If nnn is missing, CFNR is deactivated, 
  '                                                 		if nnn = *, CFNR to Voicemail is activated
  ' ##23	    	Deactivate Call Forwarding unconditional
  ' ##24	    	Deactivate Call Forwarding busy
  ' ##25	    	Deactivate Call Forwarding no reply
  ' ##8nnn*ppp#    	CFU to calling extension for user with extension nnn and PIN ppp	
  ' ##9nnn#	    	Remote Inquiry for user with extension nnn	

  szFeatureCodePrefix       = "##"
  szFeatureCodeRI           = "##10"
  szFeatureCodeCFUon        = "##20"
  szFeatureCodeCFBSon       = "##21"
  szFeatureCodeCFNRon       = "##22"
  szFeatureCodeCFUoff1      = "##20#"
  szFeatureCodeCFBSoff1     = "##21#"
  szFeatureCodeCFNRoff1     = "##22#"
  szFeatureCodeCFUoff2      = "##23"
  szFeatureCodeCFBSoff2     = "##24"
  szFeatureCodeCFNRoff2     = "##25"
  szFeatureCodeCallMyself   = "##70"    ' ##70*
  szFeatureCodeCallVMDirect = "##71"    ' ##71*
  szFeatureCodeCFUotherUser = "##8"
  szFeatureCodeRIotherUser  = "##9"

  bSkipPostProcessing = False
  CheckAndHandleSpecialCall = True
  
  szDialedNumber = PBXCall.DialedNumber
  
  If ( _ 
      (Right(CStr(szDialedNumber), Len(szMagicStringCallIntrusion1)) = szMagicStringCallIntrusion1) Or _
      (Right(CStr(szDialedNumber), Len(szMagicStringCallIntrusion2)) = szMagicStringCallIntrusion2) Or _
      (Right(CStr(szDialedNumber), Len(szMagicStringCallIntrusion3)) = szMagicStringCallIntrusion3) ) Then
    PBXScript.OutputTrace "Call intrusion (mode=" & Mid(CStr(szDialedNumber), Len(CStr(szDialedNumber))-1, 1) & ") is starting..."
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retDummy = PBXCall.ConnectToEx(szDialedNumber, 15, false, "", "", pDummy)
    ' delete caller list entry
    PBXCall.PhoneCallListEntry.Delete
    bSkipPostProcessing = True
    Exit Function
  End If

  If (PBXCall.CallType = "Direct") Then
    PBXScript.OutputTrace "Direct call..."
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retDummy = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, false, 0, false, "", "", pDummyV, true, true)
    bSkipPostProcessing = True
    Exit Function
  End If

  If (PBXCall.CallingPartyNumber = szMagicStringRIPhone) Then
    PBXCall.CallingPartyNumber = CallerID() 'remove magic string
    PBXCall.SkipAlerting
    PBXScript.OutputTrace "Remote Inquiry from SwyxPhone L4xx/L5xx or SwyxIt! is starting..."
    retDummy = RemoteInquiryEx4("Voicemail.True", g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, False, g_szStdRiPIN, g_bUseFromCriteria)
    Exit Function
  End If

  If (Right(CStr(szDialedNumber), Len(szMagicStringCFU)) = szMagicStringCFU) Then
    PBXScript.OutputTrace "CFU from other (nnn*ppp*8*) is starting..."
    PBXCall.SkipAlerting
    ' check PIN ppp
    nPos = InStr(szDialedNumber, "*")
    szPIN = Mid(CStr(szDialedNumber), nPos+1, Len(szDialedNumber)-Len(szFeatureCodeCFUon)-nPos+1)
    PBXScript.OutputTrace "activate CFU from other PIN: XXX" '& szPIN
    If (PBXScript.CheckPIN(szPIN, g_szStdRiPIN) = PBXCheckPinResultOk) Then
        ' set redirection number
        PBXUser.UnconditionalRedirectNumber=PBXCall.CallingPartyNumber
        PBXUser.UnconditionalRedirect=vbTrue
        PBXScript.OutputTrace "activate CFU from other to: " & PBXUser.UnconditionalRedirectNumber
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
    Else
        PBXScript.OutputTrace "PIN is incorrect"
        PBXCall.PlayMessage("Announcements/FC_not_confirm.wav")
    End If
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        Exit Function
  End If

  If (Right(CStr(szDialedNumber), Len(szMagicStringRI)) = szMagicStringRI) Then
    PBXScript.OutputTrace "Remote inquire from other (nnn*9*) is starting..."
    PBXCall.PostDialingDigits = ""
    PBXCall.SkipAlerting
    retDummy = RemoteInquiryEx4("Voicemail.True", g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, True, g_szStdRiPIN, g_bUseFromCriteria)
    bSkipPostProcessing = True
    Exit Function
  End If
  
  If (Right(CStr(szDialedNumber), Len(szMagicStringCallVMToNum)) = szMagicStringCallVMToNum) Then
    PBXScript.OutputTrace "VM for user nnn is starting via " + szMagicStringCallVMToNum
    PBXCall.SkipAlerting
    StandardVoicemailEx()
    bSkipPostProcessing = True
    Exit Function
  End If

  If (Left(CStr(PBXCall.CallingPartyNumber), Len(szMagicStringConf)) = szMagicStringConf) Then
    PBXScript.OutputTrace "Conference call is starting..."
    PBXCall.SkipAlerting
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retDummy = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 15, false, "", "", pDummy, false, 0, false, "", "", pDummyV, true, true)
    bSkipPostProcessing = True
    Exit Function
  End If
  
  If (Right(CStr(szDialedNumber), Len(szMagicStringDirCall)) = szMagicStringDirCall) Then
    PBXScript.OutputTrace "Direct Call via " + szMagicStringDirCall + " is starting..."
    PBXCall.CallType = "Direct"
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retDummy = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, false, 0, false, "", "", pDummyV, true, true)
    bSkipPostProcessing = True
    Exit Function
  End If

  If (Left(CStr(szDialedNumber), Len(szFeatureCodePrefix)) = szFeatureCodePrefix) Then
      ' it is a Feature Code ##
      PBXCall.SkipAlerting
    
      nCount = 0
      While ((Len(PBXCall.PostDialingDigits) < 2) And (nCount<20))
        PBXScript.OutputTrace "Function Code is too short, waiting for additional digits: " & PBXCall.PostDialingDigits
        PBXScript.Sleep(200)
        nCount = nCount + 1
      Wend
      szDialedNumber = PBXCall.CalledPartyNumber + PBXCall.PostDialingDigits

      PBXScript.OutputTrace "Function Code: " & szDialedNumber

      If (Left(szDialedNumber, Len(szFeatureCodeRI)) = szFeatureCodeRI) Then
        PBXScript.OutputTrace "Remote Inquiry via " + szFeatureCodeRI + " is starting..."
        'before calling the RI, the Post Dialing Digits must be set to empty or appended with digits following after feature code
        PBXCall.PostDialingDigits = Mid(szDialedNumber, Len(szFeatureCodeRI)+1)
        retDummy = RemoteInquiryEx4("Voicemail.True", g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, False, g_szStdRiPIN, g_bUseFromCriteria)
        bSkipPostProcessing = True
        Exit Function        
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCallMyself)) = szFeatureCodeCallMyself) Then
        szDialedNumber = CollectPostDialDigits("*")
        If ((szFeatureCodeCallMyself + "*") = (szFeatureCodePrefix + szDialedNumber)) Then
          PBXScript.OutputTrace "Call myself via feature code  is starting..."
          PBXCall.PostDialingDigits = ""
          retDummy = PBXCall.ConnectToEx(szFeatureCodePrefix, 60, false, "", "", pDummy, CLng(PBXDeviceTypeAll and not PBXDeviceTypeMobile))
          PBXCall.PhoneCallListEntry.Delete
          bSkipPostProcessing = True
          Exit Function
        Else
          szDialedNumber = ""
        End If
      End If

      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCallVMDirect)) = szFeatureCodeCallVMDirect) Then
        szDialedNumber = CollectPostDialDigits("*")
        If ((szFeatureCodeCallVMDirect + "*") = (szFeatureCodePrefix + szDialedNumber)) Then
          PBXScript.OutputTrace "VM Direct via " + szFeatureCodeCallVMDirect + " is starting..."
          StandardVoicemailEx()
          PBXCall.PhoneCallListEntry.Delete
          bSkipPostProcessing = True
          Exit Function
        Else
          szDialedNumber = ""
        End If
      End If

      If (szDialedNumber = szFeatureCodeCFUoff1) or (szDialedNumber = szFeatureCodeCFUoff2) Then
        PBXScript.OutputTrace "deactivate CFU via " & szDialedNumber
        PBXUser.UnconditionalRedirect=vbFalse
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If

      If (szDialedNumber = szFeatureCodeCFBSoff1) or (szDialedNumber = szFeatureCodeCFBSoff2) Then
        PBXScript.OutputTrace "deactivate CFBS via " & szDialedNumber
        PBXUser.BusyRedirect=vbFalse
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If
    
      If (szDialedNumber = szFeatureCodeCFNRoff1) or (szDialedNumber = szFeatureCodeCFNRoff2) Then
        PBXScript.OutputTrace "deactivate CFNR via " & szDialedNumber
        PBXUser.DelayedRedirect=vbFalse
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCFUon)) = szFeatureCodeCFUon) Then
        PBXScript.OutputTrace "activate CFU via ##20"
        szDialedNumber = CollectPostDialDigits("#")
        If (Mid(CStr(szDialedNumber), Len(szFeatureCodeCFUon)+1-Len(szFeatureCodePrefix), 1) = "*") Then
          PBXScript.OutputTrace "activate CFU to voicemail"
          PBXUser.UnconditionalRedirectNumber="voicemail"
          PBXUser.UnconditionalRedirect=vbTrue
        Else
          szNumber = Mid(CStr(szDialedNumber), Len(szFeatureCodeCFUon)+1-Len(szFeatureCodePrefix), Len(szDialedNumber)-Len(szFeatureCodeCFUon)-1+Len(szFeatureCodePrefix))
          If ( Len(szNumber) = 0 ) Then
            PBXUser.UnconditionalRedirect=vbFalse
            PBXScript.OutputTrace "deactivate CFU because no number is given"
          Else
            PBXUser.UnconditionalRedirectNumber=szNumber
            PBXUser.UnconditionalRedirect=vbTrue
            PBXScript.OutputTrace "activate CFU to: " & PBXUser.UnconditionalRedirectNumber
          End If
        End If
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCFBSon)) = szFeatureCodeCFBSon) Then
        PBXScript.OutputTrace "activate CFBS via ##21"
        szDialedNumber = CollectPostDialDigits("#")
        If (Mid(CStr(szDialedNumber), Len(szFeatureCodeCFBSon)+1-Len(szFeatureCodePrefix), 1) = "*") Then
          PBXScript.OutputTrace "activate CFBS to voicemail"
          PBXUser.BusyRedirectNumber="voicemail"
          PBXUser.BusyRedirect=vbTrue
        Else
          szNumber = Mid(CStr(szDialedNumber), Len(szFeatureCodeCFBSon)+1-Len(szFeatureCodePrefix), Len(szDialedNumber)-Len(szFeatureCodeCFBSon)-1+Len(szFeatureCodePrefix))
          If ( Len(szNumber) = 0 ) Then
            PBXUser.BusyRedirect=vbFalse
            PBXScript.OutputTrace "deactivate CFBS because no number is given"
          Else
            PBXUser.BusyRedirectNumber=szNumber
            PBXUser.BusyRedirect=vbTrue
            PBXScript.OutputTrace "activate CFBS to: " & PBXUser.BusyRedirectNumber
          End If
        End If
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCFNRon)) = szFeatureCodeCFNRon) Then
        PBXScript.OutputTrace "activate CFNR via ##22"
        szDialedNumber = CollectPostDialDigits("#")
        If (Mid(CStr(szDialedNumber), Len(szFeatureCodeCFNRon)+1-Len(szFeatureCodePrefix), 1) = "*") Then
          PBXScript.OutputTrace "activate CFNR to voicemail"
          PBXUser.DelayedRedirectNumber="voicemail"
          PBXUser.DelayedRedirect=vbTrue
        Else
          szNumber = Mid(CStr(szDialedNumber), Len(szFeatureCodeCFNRon)+1-Len(szFeatureCodePrefix), Len(szDialedNumber)-Len(szFeatureCodeCFNRon)-1+Len(szFeatureCodePrefix))
          If ( Len(szNumber) = 0 ) Then
            PBXUser.DelayedRedirect=vbFalse
            PBXScript.OutputTrace "deactivate CFNR because no number is given"
          Else
            PBXUser.DelayedRedirectNumber=szNumber
            PBXUser.DelayedRedirect=vbTrue
            PBXUser.DelayedRedirectTimeout=15
            PBXScript.OutputTrace "activate CFNR to: " & PBXUser.DelayedRedirectNumber & "after sec: " & PBXUser.DelayedRedirectTimeout
          End If
        End If
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        PBXCall.PlayMessage("Announcements/FC_confirm.wav")
        Exit Function
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeCFUotherUser)) = szFeatureCodeCFUotherUser) Then
        szDialedNumber = CollectPostDialDigits("#")
        PBXScript.OutputTrace "activate CFU to calling extension for other users via ##8"
        szDestination=Mid(CStr(szDialedNumber), Len(szFeatureCodeCFUotherUser)+1-Len(szFeatureCodePrefix), Len(szDialedNumber)-Len(szFeatureCodeCFUotherUser)-1+Len(szFeatureCodePrefix))
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        retDummy = PBXCallConnectToWrapper(szDestination&szMagicStringCFU, 15, true, "", "", pDummy, false, 0, false, "", "", pDummyV, true, true)
        Exit Function
      End If
    
      If (Left(CStr(szDialedNumber), Len(szFeatureCodeRIotherUser)) = szFeatureCodeRIotherUser) Then
        szDialedNumber = CollectPostDialDigits("#")
        PBXScript.OutputTrace "activate RI for other users via ##9"
        szDialedNumber = CollectPostDialDigits("#")
        szDestination=Mid(CStr(szDialedNumber), Len(szFeatureCodeRIotherUser)+1-Len(szFeatureCodePrefix), Len(szDialedNumber)-Len(szFeatureCodeRIotherUser)-1+Len(szFeatureCodePrefix))
        ' delete caller list entry
        PBXCall.PhoneCallListEntry.Delete
        bSkipPostProcessing = True
        retDummy = PBXCallConnectToWrapper(szDestination&szMagicStringRI, 15, true, "", "", pDummy, false, 0, false, "", "", pDummyV, true, true)
        Exit Function
      End If
    
      bSkipPostProcessing = True
      ' delete caller list entry
      PBXCall.PhoneCallListEntry.Delete
      PBXCall.PlayMessage("Announcements/FC_not_confirm.wav")
      Exit Function
  End If

  If (PreProcessing()) Then
    PBXScript.OutputTrace "Call is handled by PreProcessing rule"
    Exit Function
  End If

  CheckAndHandleSpecialCall = False
End Function

' **** special calls handling ****
Function IsSpecialCall(ByRef bSkipPostProcessing)
  IsSpecialCall = CheckAndHandleSpecialCall(bSkipPostProcessing)
End Function


' **** DEBUG FUNCTIONS BEGIN *****
Function ExtractReturnValue(ByVal nRetVal)
  Dim szRetVal
  Select Case nRetVal
    Case PBXSuccess                             szRetVal = "PBXSuccess" '(0)
    Case PBXFailure                             szRetVal = "PBXFailure" '(1)
    Case PBXTimeout                             szRetVal = "PBXTimeout" '(2)
    Case PBXCallTermNormalCallClearing          szRetVal = "PBXCallTermNormalCallClearing" '(3)
    Case PBXCallTermDestinationBusy             szRetVal = "PBXCallTermDestinationBusy" '(4)
    Case PBXCallTermReject                      szRetVal = "PBXCallTermReject" '(5)
    Case PBXCallTermCancelled                   szRetVal = "PBXCallTermCancelled" '(6)
    Case PBXCallTermTransferred                 szRetVal = "PBXCallTermTransferred" '(7)
    Case PBXCallTermJoinedConference            szRetVal = "PBXCallTermJoinedConference" '(8)
    Case PBXCallTermNoAnswer                    szRetVal = "PBXCallTermNoAnswer" '(9)
    Case PBXCallTermToLate                      szRetVal = "PBXCallTermToLate" '(10)
    Case PBXCallTermDirectCallImpossible        szRetVal = "PBXCallTermDirectCallImpossible" '(11)
    Case PBXCallTermWrongNumber                 szRetVal = "PBXCallTermWrongNumber" '(12)
    Case PBXCallTermConnectToCallerImpossible   szRetVal = "PBXCallTermConnectToCallerImpossible" '(13)
    Case PBXCallTermDestinationUnreachable      szRetVal = "PBXCallTermDestinationUnreachable" '(14)
    Case PBXInvalidDTMFDigitReceived            szRetVal = "PBXInvalidDTMFDigitReceived" '(15)
    Case PBXCallTermRedirectionNotPossible      szRetVal = "PBXCallTermRedirectionNotPossible" '(16)
    Case PBXCallTermIgnoreCall                  szRetVal = "PBXCallTermIgnoreCall" '(17)
    Case PBXCallTermNoChannelAvailable          szRetVal = "PBXCallTermNoChannelAvailable" '(18)
    Case PBXCallTermNetworkCongestion           szRetVal = "PBXCallTermNetworkCongestion" '(19)
    Case PBXCallTermIncompatibleDestination     szRetVal = "PBXCallTermIncompatibleDestination" '(20)
    Case PBXCallTermNumberChanged               szRetVal = "PBXCallTermNumberChanged" '(21)
    Case PBXCallTermOriginatorDisconnected      szRetVal = "PBXCallTermOriginatorDisconnected" '(22)
    Case PBXDestinationScriptStarted            szRetVal = "PBXDestinationScriptStarted" '(23)
    Case PBXCallTermDeflected                   szRetVal = "PBXCallTermDeflected" '(24)
    Case PBXCallTermPermissionDenied            szRetVal = "PBXCallTermPermissionDenied" '(25)
    Case Else:                                  szRetVal = nRetVal
  End Select
  ExtractReturnValue = szRetVal
End Function


Function ExtractGseStateValue(ByVal nRetVal)
  Dim szRetVal
  Select Case nRetVal
    Case gseStateStarted:               szRetVal = "gseStateStarted"
    Case gseStateTrue:                  szRetVal = "gseStateTrue"
    Case gseStateFalse:                 szRetVal = "gseStateFalse"
    Case gseStateTerminated:            szRetVal = "gseStateTerminated"
    Case gseStateConnected:             szRetVal = "gseStateConnected"
    Case gseStateNoAnswer:              szRetVal = "gseStateNoAnswer"
    Case gseStateDisconnected:          szRetVal = "gseStateDisconnected"
    Case gseStatePlayed:                szRetVal = "gseStatePlayed"
    Case gseStateNoPlayed:              szRetVal = "gseStateNoPlayed"
    Case gseStateDTMFKeyPressed:        szRetVal = "gseStateDTMFKeyPressed"
    Case gseStateSent:                  szRetVal = "gseStateSent"
    Case gseStateFollowMeNext:          szRetVal = "gseStateFollowMeNext"
    Case gseStateKey0:                  szRetVal = "gseStateKey0"
    Case gseStateKey1:                  szRetVal = "gseStateKey1"
    Case gseStateKey2:                  szRetVal = "gseStateKey2"
    Case gseStateKey3:                  szRetVal = "gseStateKey3"
    Case gseStateKey4:                  szRetVal = "gseStateKey4"
    Case gseStateKey5:                  szRetVal = "gseStateKey5"
    Case gseStateKey6:                  szRetVal = "gseStateKey6"
    Case gseStateKey7:                  szRetVal = "gseStateKey7"
    Case gseStateKey8:                  szRetVal = "gseStateKey8"
    Case gseStateKey9:                  szRetVal = "gseStateKey9"
    Case gseStateKey10:                 szRetVal = "gseStateKey10"
    Case gseStateKey11:                 szRetVal = "gseStateKey11"
    Case gseStateMonday:                szRetVal = "gseStateMonday"
    Case gseStateTuesday:               szRetVal = "gseStateTuesday"
    Case gseStateWednesday:             szRetVal = "gseStateWednesday"
    Case gseStateThursday:              szRetVal = "gseStateThursday"
    Case gseStateFriday:                szRetVal = "gseStateFriday"
    Case gseStateSaturday:              szRetVal = "gseStateSaturday"
    Case gseStateSunday:                szRetVal = "gseStateSunday"
    Case gseStateDTMFStringCollected:   szRetVal = "gseStateDTMFStringCollected"
    Case gseStateSetVariableNext:       szRetVal = "gseStateSetVariableNext"
    Case gseStateEvaluateMatch:         szRetVal = "gseStateEvaluateMatch"
    Case gseStateEvaluateNoMatch:       szRetVal = "gseStateEvaluateNoMatch"
    Case gseStateTimeout:               szRetVal = "gseStateTimeout"
    Case gseStateDisconnection:         szRetVal = "gseStateDisconnection"
    Case gseStateRecorded:              szRetVal = "gseStateRecorded"
    Case gseStateFailed:                szRetVal = "gseStateFailed"
    Case gseStateIMAP4Error:            szRetVal = "gseStateIMAP4Error"
    Case gseStateIMAP4Success:          szRetVal = "gseStateIMAP4Success"
    Case gseStateIMAP4Failed:           szRetVal = "gseStateIMAP4Failed"
    Case gseStateIMAP4True:             szRetVal = "gseStateIMAP4True"
    Case gseStateIMAP4False:            szRetVal = "gseStateIMAP4False"
    Case gseStateOnHold:                szRetVal = "gseStateOnHold"
    Case gseStateActivated:             szRetVal = "gseStateActivated"
    Case gseStateProceedWDstScr:        szRetVal = "gseStateProceedWDstScr"
    Case gseStateSilenceDetected:       szRetVal = "gseStateSilenceDetected"
    Case gseStateExecuted:              szRetVal = "gseStateExecuted"
    Case gseStateNotDelivered:          szRetVal = "gseStateNotDelivered"
    Case gseStateCreated:               szRetVal = "gseStateCreated"
    Case gseStateExists:                szRetVal = "gseStateExists"
    Case gseStateOk:                    szRetVal = "gseStateOk"
    Case gseStateSizeExceeded:          szRetVal = "gseStateSizeExceeded"
    Case gseStateDestinationUnreachable:szRetVal = "gseStateDestinationUnreachable"
    Case gseStateQueueTimeout:          szRetVal = "gseStateQueueTimeout"
    Case gseStateOnlyStopChar:          szRetVal = "gseStateOnlyStopChar"
    Case Else:                          szRetVal = "Unknown"
  End Select
  ExtractGseStateValue = szRetVal
End Function


Sub TraceFunctionResult(ByVal szFnName, ByVal szState)
  PBXScript.OutputTrace "<-- " & szFnName & ", rc = " & szState & " [" & ExtractGseStateValue(szState) & "]"
End Sub

Sub TraceSubResult(ByVal szFnName)
  PBXScript.OutputTrace "<-- " & szFnName
End Sub

Sub TraceError(ByVal szFnName, ByVal szText, ByVal nRetVal)
  PBXScript.OutputTrace "callrouting.vbs (" & szFnName & "): " & szText & " [retVal = """ & ExtractReturnValue(nRetVal) & """]"
End Sub

Sub TraceInfo(ByVal szFnName, ByVal szText)
  PBXScript.OutputTrace "callrouting.vbs (" & szFnName & "): " & szText
End Sub

Sub TraceFunction(ByVal szFnName, ByVal szParams)
  PBXScript.OutputTrace "--> " & szFnName & "(" & szParams & ")"
End Sub
' **** DEBUG FUNCTIONS END *******


'#include "actionStandardVoicemail.vbs"

Sub StandardVoicemailEx()
  Dim retDummy
  Set retDummy = new GSEParamList
  retDummy.Count = 0
  actionStandardVoicemail retDummy
End Sub

Sub StandardVoicemail()
  'Start voicemail with playing welcome message
  'Note: Check if filename is empty, because the user may switch off playing a welcome message
  '      In this case the filename is an empty string

  Dim retVal, retDummy

  ' set connected flag to true to skip post processing
  bCallConnected = true

  if (PBXUser.VoicemailWelcomeMessage <> "") Then

    If PBXUser.VoicemailWelcomeMessage="*hold*" Then
      retVal = PBXCall.PlayMessage("")
    Else
      retVal = PBXCall.PlayMessage(PBXUser.VoicemailWelcomeMessage)
    End If

    If (retVal = PBXFailure) Then
      retDummy = PBXScript.EndScript()
    End If
  End If

  'Record message if enabled and recording timeout is set
  If ((PBXUser.VoicemailRecording <> 0) and (PBXUser.VoicemailRecordingTimeout > 0)) Then
    retVal = PBXCall.PlayMessage("Beep.wav")
    If (retVal = PBXFailure) Then
      retDummy = PBXScript.EndScript()
    End If
    retVal = PBXCall.RecordMessage(PBXUser.VoicemailRecordingTimeout)
    If (retVal = PBXFailure) Then
      retDummy = PBXScript.EndScript()
    End If
    If (retVal = PBXTimeout) Then
      retDummy = PBXCall.PlayMessage("Beep.wav")
      retDummy = PBXCall.SendEMail(PBXUser.VoicemailEMailAddress, g_resStandardVoicemailSubject, g_resStandardVoicemailBody, True)
      Exit Sub
    Else
      retVal = PBXCall.SendEMail(PBXUser.VoicemailEMailAddress, g_resStandardVoicemailSubject, g_resStandardVoicemailBody, True)
    End If
  End If

  retDummy = PBXCall.Disconnect(0)
  retDummy = PBXScript.EndScript()
End Sub

Function UnconditionalCallForwarding()
  Dim bResponse, retVal, pDummy, bDeflectToVoicemail
  
  bDeflectToVoicemail = False

  PBXScript.OutputTrace "UnconditionalCallForwarding"
  bResponse = true  

  If (PBXUser.UnconditionalRedirect <> 0) Then
    If (PBXUser.UnconditionalRedirectNumber = "voicemail") Then
      StandardVoicemail()
    Else  
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXUser.UnconditionalRedirectNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)
      
      If (retVal = PBXCallTermConnectToCallerImpossible) Then
        ' Hotfix for unreachable condition (19.6.01)
        PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)
      End If
      'Such condition is needed to prevent voicemail from starting for the second time
      If (retVal <> PBXSuccess) AND (NOT bDeflectToVoicemail) Then
        ' Hotfix for unreachable condition (19.6.01)
        StandardVoiceMail()
      End If
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  UnconditionalCallForwarding = bResponse
End Function

Function UnconditionalCallForwardingEx()
  Dim bResponse, retVal, pDummy, pDummyV

  bResponse = true  

  If (PBXUser.UnconditionalRedirect <> 0) Then
    PBXScript.OutputTrace "UnconditionalCallForwardingEx() started"
    If (PBXUser.UnconditionalRedirectNumber = "voicemail") Then
      StandardVoicemailEx()
    Else  
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      pDummy = ""
      retVal = PBXCallConnectToWrapper(PBXUser.UnconditionalRedirectNumber, 60, 1, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
      If (retVal = PBXDestinationScriptStarted) Then
        PBXScript.EndScript()
        Exit Function
      End If
      If (retVal = PBXCallTermConnectToCallerImpossible) Then
        ' Hotfix for unreachable condition (19.6.01)
        PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
      End If
      If (retVal = PBXSuccess) Or (retVal = PBXCallTermOriginatorDisconnected) Or (retVal = PBXTimeout) Or (retVal = PBXCallTermDestinationBusy) Or (retVal = PBXCallTermReject) Then
        PBXScript.OutputTrace "UnconditionalCallForwardingEx() skip next rules"
        ' Skip next rules.
        bResponse = True
      Else
        PBXScript.OutputTrace "UnconditionalCallForwardingEx() unsuccessful - proceed script with next rule"
        ' Start next rule.
        bResponse = false
      End If
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  UnconditionalCallForwardingEx = bResponse
End Function

Function BusyCallForwarding(ByVal bUserBusy)
  Dim bResponse, retVal, pDummy, bDeflectToVoicemail
  
  bDeflectToVoicemail = False
  bResponse = true  

  If ((PBXUser.BusyRedirect <> 0) and (bUserBusy = true)) Then
    If (PBXUser.BusyRedirectNumber = "voicemail") Then
      StandardVoicemail()
    Else  
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXUser.BusyRedirectNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)
      If (retVal = PBXCallTermConnectToCallerImpossible) Then
        ' Hotfix for unreachable condition (19.6.01)
        PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)
      End If
      'Such condition is needed to prevent voicemail from starting for the second time
      If (retVal <> PBXSuccess) AND (retVal <> PBXCallTermNormalCallClearing) AND (NOT bDeflectToVoicemail) Then
        ' Hotfix for unreachable condition (19.6.01)
        StandardVoiceMail()
      End If
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  BusyCallForwarding = bResponse
End Function

Function BusyCallForwardingEx(ByVal bUserBusy)
  Dim bResponse, retVal, pDummy, pDummyV

  bResponse = true  

  PBXScript.OutputTrace "BusyCallForwardingEx"
  If ((PBXUser.BusyRedirect <> 0) and (bUserBusy = true)) Then
    PBXScript.OutputTrace "BusyCallForwardingEx() started"
    If (PBXUser.BusyRedirectNumber = "voicemail") Then
      StandardVoicemailEx()
    Else  
      pDummy = ""
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXUser.BusyRedirectNumber, 60, 1, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
      If (retVal = PBXDestinationScriptStarted) Then
        PBXScript.EndScript()
        Exit Function
      End If
      If (retVal = PBXCallTermConnectToCallerImpossible) Then
        ' Hotfix for unreachable condition (19.6.01)
        PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
      ElseIf (retVal = PBXCallTermOriginatorDisconnected) Then
        PBXScript.OutputTrace "BusyCallForwardingEx() originator disconnected -> skip next rules"
        ' Skip next rules.
        bResponse = True
      ElseIf (retVal <> PBXSuccess) and (retVal <> PBXCallTermNormalCallClearing) Then
        ' Start next rule.
        bResponse = false
      End If
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  BusyCallForwardingEx = bResponse
End Function

Function DelayCallForwarding(ByVal bUserBusy)
  Dim bResponse, retVal, pDummy, bDeflectToVoicemail, pDummyV
  
  bDeflectToVoicemail = False
  bResponse = true

  If ((bUserBusy = false) and (PBXUser.DelayedRedirect <> 0) and (PBXUser.IsLoggedIn <> 0) and (PBXUser.DelayedRedirectTimeout > 0)) Then
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, PBXUser.DelayedRedirectTimeout, false, "", "", pDummy, true, PBXUser.DelayedRedirectTimeout, true, "", "", bDeflectToVoicemail, true, true)
    If (retVal = PBXSuccess) Then
      ' to do nothing bCallConnected will be set to "True" within PBXCallConnectToWrapper
    ElseIf (retVal <> PBXCallTermOriginatorDisconnected) Then
      If (PBXUser.DelayedRedirectNumber = "voicemail") Then
        StandardVoicemail()
      Else  
        ' Hotfix for unreachable condition (19.6.01)
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXUser.DelayedRedirectNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)
        'Such condition is needed to prevent voicemail from starting for the second time
        If (retVal <> PBXSuccess) AND (NOT bDeflectToVoicemail) Then
          ' Hotfix for unreachable condition (19.6.01)
          StandardVoiceMail()
        End If
      End If
    Else
      PBXScript.OutputTrace "DelayCallForwarding() originator disconnected -> skip next rules"
      ' Skip next rules.
      bResponse = True
    End If
  ElseIf ((bUserBusy = false) and (PBXUser.DelayedRedirect <> 0) and (PBXUser.IsLoggedIn = 0)) Then
    If (PBXUser.DelayedRedirectNumber = "voicemail") Then
      StandardVoicemail()
    Else  
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXUser.DelayedRedirectNumber, 60, false, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  DelayCallForwarding = bResponse
End Function

Function DelayCallForwardingEx(ByVal bUserBusy)
  Dim bResponse, retVal, pDummy, pDummyV

  bResponse = true

  PBXScript.OutputTrace "DelayCallForwardingEx"
  If ((bUserBusy = false) and (PBXUser.DelayedRedirect <> 0) and (PBXUser.DelayedRedirectTimeout > 0)) Then
    PBXScript.OutputTrace "DCFex (user logged in) started"
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, PBXUser.DelayedRedirectTimeout, false, "", "", pDummy, true, PBXUser.DelayedRedirectTimeout, true, "", "", pDummyV, true, true)
    
    ' Bugfix for H323 devices
    If (retVal = PBXCallTermDestinationBusy) Then
      PBXScript.OutputTrace "PBXCallTermDestinationBusy in DelayedCallFwd"
      If (PBXUser.BusyRedirect <> 0) Then
        PBXScript.OutputTrace "redirect call to BusyCallFwd"
        DelayCallForwardingEx = BusyCallForwardingEx(true)
        Exit Function
      Else
        PBXScript.OutputTrace "return busy tone"
        PBXCall.Disconnect(PBXCallTermDestinationBusy)
        DelayCallForwardingEx = true
        Exit Function
      End If
    End If

    If (retVal = PBXSuccess) Then
      'continue
    ElseIf (retVal <> PBXCallTermOriginatorDisconnected) Then
      If (PBXUser.DelayedRedirectNumber = "voicemail") Then
        StandardVoicemailEx()
      Else  
        ' Hotfix for unreachable condition (19.6.01)
        pDummy = ""
        If (Not bCallConnected) Then
          ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
          PBXCall.CallProceeding
        End If
        retVal = PBXCallConnectToWrapper(PBXUser.DelayedRedirectNumber, 60, 1, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
        If (retVal = PBXDestinationScriptStarted) Then
          PBXScript.EndScript()
          DelayCallForwardingEx = true
          Exit Function
        End If
        ' Bugfix for H323 devices
        If (retVal = PBXCallTermDestinationBusy) Then
          PBXScript.OutputTrace "PBXCallTermDestinationBusy in DelayedCallFwd"
          If (PBXUser.BusyRedirect <> 0) Then
            PBXScript.OutputTrace "redirect call to BusyCallFwd"
            DelayCallForwardingEx = BusyCallForwardingEx(true)
            Exit Function
          Else
            PBXScript.OutputTrace "return busy tone"
            PBXCall.Disconnect(PBXCallTermDestinationBusy)
            DelayCallForwardingEx = true
            Exit Function
          End If
        End If

        If (retVal = PBXSuccess) Then
          ' to do nothing
        Else
          ' Start next rule.
          bResponse = false
        End If
      End If
    Else
      PBXScript.OutputTrace "DelayCallForwardingEx() originator disconnected -> skip next rules"
      ' Skip next rules.
      bResponse = True
    End If
  Else
    'Skip this rule. Start next rule.
    bResponse = false
  End If
  
  DelayCallForwardingEx = bResponse
End Function

Function StandardRedirectionRules()
  Dim bResponse, bUserBusy

  bResponse = false
  
  ' Save call strarting time
  tCallStarted = PBXUser.Now 

  ' Bugfix #2647 check if user is busy before executing busy and delayed call forwarding
  bUserBusy = (PBXUser.IsBusy <> 0)
  
  If (UnconditionalCallForwarding()) Then
    bResponse = true
  ElseIf (BusyCallForwarding(bUserBusy)) Then
    bResponse = true
  ElseIf (DelayCallForwarding(bUserBusy)) Then
    bResponse = true
  End If

  StandardRedirectionRules = bResponse
End Function

Function StandardRedirectionRulesEx()
  Dim bResponse, bUserBusy

  bResponse = false
  
  ' Save call strarting time
  'tCallStarted = PBXUser.Now 

  ' Bugfix #2647 check if user is busy before executing busy and delayed call forwarding
  bUserBusy = (PBXUser.IsBusy <> 0)
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  If (UnconditionalCallForwardingEx()) Then
    bResponse = true
  ElseIf (BusyCallForwardingEx(bUserBusy)) Then
    bResponse = true
  ElseIf (DelayCallForwardingEx(bUserBusy)) Then
    bResponse = true
  End If

  StandardRedirectionRulesEx = bResponse
End Function

Sub StandardCallActions()
  Dim retVal, bDeflectToVoicemail, pDummy
  
  bDeflectToVoicemail = False

  If (Not bCallConnected) Then
    ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
    PBXCall.CallProceeding
  End If
  retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", bDeflectToVoicemail, true, true)

  If (retVal = PBXCallTermDestinationBusy) Or (retVal = PBXCallTermReject) then
    PBXCall.Disconnect(retVal)
  'Such condition is needed to prevent voicemail from starting for the second time
  ElseIf (retVal <> PBXSuccess) AND (NOT bDeflectToVoicemail) then
    ' Hotfix for unreachable condition (19.6.01)
    StandardVoiceMail()
  End If
End Sub

Sub StandardCallActionsEx()
  Dim retVal, retDummy, pDummy, pDummyV

  PBXScript.OutputTrace "StandardCallActionsEx"

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  If (Not bCallConnected) Then
    ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
    PBXCall.CallProceeding
    retVal = PBXCallTermDestinationBusy
    If (PBXUser.IsBusy = 0) Then
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 60, false, "", "", pDummy, true, 60, true, "", "", pDummyV, true, true)
    End If
  Else
    retVal = PBXSuccess
  End If
  
  If (retVal = PBXTimeout)  Or (retVal = PBXCallTermReject) Then
    PBXCall.Disconnect(retVal)
  ElseIf (retVal = PBXCallTermDestinationBusy) Then
    
    ' Bugfix for H323 devices
    If (retVal = PBXCallTermDestinationBusy) Then
      PBXScript.OutputTrace "PBXCallTermDestinationBusy in StdCallActionsEx"
      If (PBXUser.BusyRedirect <> 0) Then
        PBXScript.OutputTrace "redirect call to BusyCallFwd"
        retDummy = BusyCallForwardingEx(true)
      Else
        PBXScript.OutputTrace "return busy tone"
        PBXCall.Disconnect(PBXCallTermDestinationBusy)
      End If
    End If


  End If
End Sub

' Connect to specified dialnumber. If dialnumber = "myself" connect to
' CalledPartyNumber
Function ConnectToNumberOrMySelf(ByVal szDialNumber, ByVal nTimeout)
  Dim retVal, pDummy, pDummyV

  If (szDialNumber = "myself") Then
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    If (PBXUser.IsBusy = 0) Then
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nTimeout, false, "", "", pDummy, true, nTimeout, true, "", "", pDummyV, true, true)
    Else
      retVal = PBXCallTermDestinationBusy
    End If
  Else
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(szDialNumber, nTimeout, false, "", "", pDummy, true, nTimeout, true, "", "", pDummyV, true, true)
    If (retVal = PBXCallTermConnectToCallerImpossible) Then
      PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nTimeout, false, "", "", pDummy, true, nTimeout, true, "", "", pDummyV, true, true)
    End If
  End If

  ConnectToNumberOrMySelf = retVal
End Function

' GSE >= 4.2.0.50
' Connect to specified dialnumber. If dialnumber = "myself" connect to
' CalledPartyNumber
Function ConnectToNumberOrMySelfEx(ByVal szDialNumber, ByVal nTimeout, _
                 ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                 ByVal bPlayAlertSound, ByVal szAlertSound, _
                 ByVal bProceedWithDestinationScript)                 
  ConnectToNumberOrMySelfEx = ConnectToNumberOrMySelfEx2(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                                     bPlayAlertSound, szAlertSound, bProceedWithDestinationScript, True)
End Function

' GSE >= 6.12.0.15
' Connect to specified dialnumber. If dialnumber = "myself" connect to
' CalledPartyNumber
Function ConnectToNumberOrMySelfEx2(ByVal szDialNumber, ByVal nTimeout, _
                 ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                 ByVal bPlayAlertSound, ByVal szAlertSound, _
                 ByVal bProceed, _
                 ByVal bIncludeMEMDev)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayAlertSound
  AdjustBoolean bProceed
  AdjustBoolean bIncludeMEMDev
  
  ConnectToNumberOrMySelfEx2 = ConnectToNumberOrMySelfEx3(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                 bPlayAlertSound, szAlertSound, bProceed, bIncludeMEMDev)    
End Function

' GSE >= 6.20.0.17
' Connect to specified dialnumber. If dialnumber = "myself" connect to
' CalledPartyNumber
Function ConnectToNumberOrMySelfEx3(ByVal szDialNumber, ByVal nTimeout, _
                 ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                 ByVal bPlayAlertSound, ByVal szAlertSound, _
                 ByVal bProceed, _
                 ByVal bIncludeMEMDev)
  Dim retVal, szDtmfDigit, szAlertSoundNew, pDummyV

  If (bPlayAlertSound = False) Then
    szAlertSound = ""
  End If

  If szAlertSound = "*hold*" Then
    szAlertSoundNew = "##holdmusic#"
  Else
    szAlertSoundNew = szAlertSound
  End If

  szDtmfDigit = ""

  If ((bPlayAlertSound = True) Or (Len(fMask) > 0)) And (Not bCallConnected) Then
    ' Accept call automatically
    retVal = PBXCall.PlayMessage("Announcements/Silence_200ms.wav")
    bCallConnected = True
  End If

  If (szDialNumber = "myself") Then
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    If (PBXUser.IsBusy = 0) Or (bProceed) Then
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, CInt(nTimeout), bProceed, szAlertSoundNew, fMask, szDtmfDigit, true, CInt(nTimeout), bProceed, szAlertSound, fMask, pDummyV, false, bIncludeMEMDev)
    Else
      retVal = PBXCallTermDestinationBusy
    End If
    
    If (retVal = PBXDestinationScriptStarted) Then
      'PBXScript.EndScript() '4.31: Do not terminate script in case if destination script started
      bCallConnected = True
      ConnectToNumberOrMySelfEx3 = retVal
      Exit Function
    End If
  Else
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    
    retVal = PBXCallConnectToWrapper(szDialNumber, CInt(nTimeout), bProceed, szAlertSoundNew, fMask, szDtmfDigit, true, CInt(nTimeout), bProceed, szAlertSound, fMask, pDummyV, false, bIncludeMEMDev)

    If (retVal = PBXDestinationScriptStarted) Then
      'PBXScript.EndScript() '4.31: Do not terminate script in case if destination script started
      bCallConnected = True
      ConnectToNumberOrMySelfEx3 = retVal
      Exit Function
    End If
    
    ' Bugfix for connect to caller impossible
    If (retVal = PBXCallTermConnectToCallerImpossible) Then
      PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If

      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, CInt(nTimeout), bProceed, szAlertSoundNew, fMask, szDtmfDigit, true, CInt(nTimeout), bProceed, szAlertSound, fMask, pDummyV, false, bIncludeMEMDev)
    End If
  End If

  If (bStoreToVariable = True) Then
    If (bResetVariableContent = True) Then
      rVariableName = ""
    End If
    If (retVal = PBXCallTermCancelled) Then
      rVariableName = rVariableName & szDtmfDigit
    End If
  End If

  ConnectToNumberOrMySelfEx3 = retVal
End Function

' obsolete
' This function is used inside the FollowMe action
' Return values:
' 0 - continue
' 1 - exit FollowMe action
' 2 - connect successful
' 3 - Voicemail (timeout)
' 4 - Voicemail (disconnect)
Function ConnectToSpecifiedNumber(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec)
  Dim retVal, retState, pDtmfDigit, pDummy, pDummyV
  
  AdjustBoolean bPreFwd
  AdjustBoolean bActivate
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement

  ConnectToSpecifiedNumber = 0

  'Play sound if "pre-forwarding announcement" selected
  If (bPreFwd = True) Then
    If (bActivate = True) Then
      'If the "activate the voicemail with #-key" is selected, play sound
      'using "GetDTMFInput" function. In this case the sound will be terminated if the
      'user hit the #-key
      retVal = PBXCallGetDtmfInputEx(szPreFwdSound, 0, 0, "#", 0, pDtmfDigit)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      If (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
        'Something wrong or call disconnected by caller. End this action
        ConnectToSpecifiedNumber = 1
        Exit Function
      End If
      If (pDtmfDigit = "#") Then
        'Start voicemail
        retState = gseVoicemail(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound)
        
        If (retState = gseStateTimeout) Then
          ConnectToSpecifiedNumber = 3
        ElseIf (retState = gseStateRecorded) Then
          ConnectToSpecifiedNumber = 4
        Else
          ConnectToSpecifiedNumber = 1
        End If
        
        Exit Function
      End If
    Else
      'In other case play sound with "PlayMessage" function. In this case
      'sound will not be terminated if the user press #-key
      retVal = PBXCallPlayMessageEx(szPreFwdSound)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      If (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
        'Something wrong or call disconnected by caller. End this action
        ConnectToSpecifiedNumber = 1
        Exit Function
      End If
    End If
  End If

  'Try connect to specified number
  If (Not bCallConnected) Then
    ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
    PBXCall.CallProceeding
  End If
  retVal = PBXCallConnectToWrapper(szCallFwdTo, nCallFwdSec, false, "", "", pDummy, true, nCallFwdSec, true, "", "", pDummyV, true, true)
  ' Bugfix for connect to caller impossible
  If (retVal = PBXCallTermConnectToCallerImpossible) Then
    PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nCallFwdSec, false, "", "", pDummy, true, nCallFwdSec, true, "", "", pDummyV, true, true)
  End If

  'Check return value
  If (retVal = PBXSuccess) Then
    'ConnectTo successful. Leave this function.
    ConnectToSpecifiedNumber = 2
  ElseIf (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
    'Something wrong. End script action
    ConnectToSpecifiedNumber = 1
  Else
    'No response. Try next calllerid.
    ConnectToSpecifiedNumber = 0
  End If

End Function

' obsolete
Function ConnectToSpecifiedNumberEx(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  Dim VarDummy

  ConnectToSpecifiedNumberEx = ConnectToSpecifiedNumberEx2(bPreFwd, bActivate, szPreFwdSound, _
                                  bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                                  bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                                  szCallFwdTo, nCallFwdSec, _
                                  bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  False, VarDummy)
End Function

' obsolete - for compatibility with 4.00
Function ConnectToSpecifiedNumberEx2(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo)
  ConnectToSpecifiedNumberEx2 = ConnectToSpecifiedNumberEx3(bPreFwd, bActivate, szPreFwdSound, _
                                  bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                                  bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                                  szCallFwdTo, nCallFwdSec, _
                                  bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  bUseResultOfLastConnectTo, rResultOfLastConnectTo, _
                                  g_szStdRiPIN, True)
End Function


Function ConnectToSpecifiedNumberEx3(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo, _
                                  ByVal szPIN, ByVal bUseStdRI)
  ConnectToSpecifiedNumberEx3 = ConnectToSpecifiedNumberEx4(bPreFwd, bActivate, szPreFwdSound, _
                              bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                              bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, False, szSound, _
                              szCallFwdTo, nCallFwdSec, _
                              bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                              bUseResultOfLastConnectTo, rResultOfLastConnectTo, _
                              szPIN, bUseStdRI, False)
End Function


Function ConnectToSpecifiedNumberEx4(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo, _
                                  ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  
  ConnectToSpecifiedNumberEx4 = ConnectToSpecifiedNumberEx5(bPreFwd, bActivate, szPreFwdSound, _
                                  bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                                  bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                                  szCallFwdTo, nCallFwdSec, _
                                  bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  bUseResultOfLastConnectTo, rResultOfLastConnectTo, _
                                  szPIN, bUseStdRI, bStdRIWithoutPIN)
End Function


Function ConnectToSpecifiedNumberEx5(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo, _
                                  ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
                                  
  ConnectToSpecifiedNumberEx5 = ConnectToSpecifiedNumberEx6(bPreFwd, bActivate, szPreFwdSound, _
                                  bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                                  bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                                  szCallFwdTo, nCallFwdSec, _
                                  bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  bUseResultOfLastConnectTo, rResultOfLastConnectTo, _
                                  szPIN, bUseStdRI, bStdRIWithoutPIN, False)
End Function


' 5.00
Function ConnectToSpecifiedNumberEx6(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo, _
                                  ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  AdjustBoolean bPreFwd
  AdjustBoolean bActivate
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement
  AdjustBoolean bUseStdVM
  AdjustBoolean bEnabled
  AdjustBoolean bPasswordEncoded
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseResultOfLastConnectTo
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
  
  ConnectToSpecifiedNumberEx6 = ConnectToSpecifiedNumberEx7(bPreFwd, bActivate, szPreFwdSound, _
                                  bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                                  bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                                  szCallFwdTo, nCallFwdSec, _
                                  bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  bUseResultOfLastConnectTo, rResultOfLastConnectTo, _
                                  szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
End Function                                 

' 6.20
' This function is used inside the FollowMe action
' Return values:
' 0 - continue
' 1 - exit FollowMe action
' 2 - connect successful
' 3 - Voicemail (timeout)
' 4 - Voicemail (disconnect)
' 5 - gseStateIMAP4Success
' 6 - gseStateIMAP4Error
Function ConnectToSpecifiedNumberEx7(ByVal bPreFwd, ByVal bActivate, ByVal szPreFwdSound, _
                                  ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                                  ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, ByVal szSound, _
                                  ByVal szCallFwdTo, ByVal nCallFwdSec, _
                                  ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                                  ByVal bUseResultOfLastConnectTo, ByRef rResultOfLastConnectTo, _
                                  ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)

  Dim retVal, retState, pDtmfDigit, szDigitMask, rVarToSaveTmpFileNameDummy, pDummyV

  ConnectToSpecifiedNumberEx7 = 0
  szDigitMask = ""

  nRecordMessage = CInt(nRecordMessage)
  nCallFwdSec = CInt(nCallFwdSec)

  'Play sound if "pre-forwarding announcement" selected

  If (bPreFwd = True) And _
     ( (bUseResultOfLastConnectTo = False) Or _
       (rResultOfLastConnectTo = PBXTimeout) Or _
       (rResultOfLastConnectTo = PBXCallTermReject)) Then
    If (bActivate = True) Then
      'If the "activate the voicemail with #-key" is selected, play sound
      'using "GetDTMFInput" function. In this case the sound will be terminated if the
      'user hit the #-key
      szDigitMask = "#"
      If (bEnabled = True) Then
        ' enable RI
        szDigitMask = szDigitMask & "*"
      End If
      PBXScript.OutputTrace "bActivate=True, szDigitMask=" & szDigitMask
      retVal = PBXCallGetDtmfInputEx(szPreFwdSound, 0, 0, szDigitMask, 0, pDtmfDigit)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      If (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
        'Something wrong or call disconnected by caller. End this action
        ConnectToSpecifiedNumberEx7 = 1
        Exit Function
      End If
      If (pDtmfDigit = "#") Then
        'Start voicemail
        retState = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                                  False, rVarToSaveTmpFileNameDummy, bUseStdVM, _
                                  bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                                  szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
        
        If (retState = gseStateTimeout) Then
          ConnectToSpecifiedNumberEx7 = 3
        ElseIf (retState = gseStateRecorded) Then
          ConnectToSpecifiedNumberEx7 = 4
        Else
          ConnectToSpecifiedNumberEx7 = 1
        End If
        Exit Function
      End If

      If (pDtmfDigit = "*") Then
        ' User activates RI
        If (bUseStdVM = True) Then
          retState = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, True, bStdRIWithoutPIN, bUseFromCriteria)
        Else
          retState = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
        End If

        If (retState = gseStateIMAP4Success) Then
          ConnectToSpecifiedNumberEx7 = 5
        ElseIf (retState = gseStateIMAP4Error) Then
          ConnectToSpecifiedNumberEx7 = 6
        Else
          ConnectToSpecifiedNumberEx7 = 1
        End If
        Exit Function
      End If
    Else
      If (bEnabled = True) Then
        ' enable RI
        szDigitMask = "*"
      End If
      'In other case play sound with "PlayMessage" function. In this case
      'sound will not be terminated if the user press #-key
      PBXScript.OutputTrace "bActivate=False, szDigitMask=" & szDigitMask
      retVal = PBXCallGetDtmfInputEx(szPreFwdSound, 0, 0, szDigitMask, 0, pDtmfDigit)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      If (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
        'Something wrong or call disconnected by caller. End this action
        ConnectToSpecifiedNumberEx7 = 1
        Exit Function
      End If
      If (pDtmfDigit = "*") Then
        ' User activates RI
        If (bUseStdVM = True) Then
          retState = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, True, bStdRIWithoutPIN, bUseFromCriteria)
        Else
          retState = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
        End If
        If (retState = gseStateIMAP4Success) Then
          ConnectToSpecifiedNumberEx7 = 5
        ElseIf (retState = gseStateIMAP4Error) Then
          ConnectToSpecifiedNumberEx7 = 6
        Else
          ConnectToSpecifiedNumberEx7 = 1
        End If
        Exit Function
      End If
    End If
  End If

  'Try connect to specified number
  If (bActivate = True) Then
    szDigitMask = "#"
    If (Not bCallConnected) Then
      ' Accept call automatically to allow DTMF detection to run!
      retVal = PBXCall.PlayMessage("Announcements/Silence_200ms.wav")
      bCallConnected = True
    End If
  Else
    szDigitMask = ""
  End If
  pDtmfDigit = ""
  If (Not bCallConnected) Then
    ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
    PBXCall.CallProceeding
  End If
  retVal = PBXCallConnectToWrapper(szCallFwdTo, nCallFwdSec, 0, "", szDigitMask, pDtmfDigit, true, nCallFwdSec, true, "", szDigitMask, pDummyV, true, true)

  ' Bugfix for connect to caller impossible
  If (retVal = PBXCallTermConnectToCallerImpossible) Then
    PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nCallFwdSec, 0, "", szDigitMask, pDtmfDigit, true, nCallFwdSec, true, "", szDigitMask, pDummyV, true, true)
  End If

  If (bUseResultOfLastConnectTo = True) Then
    rResultOfLastConnectTo = retVal
  End If
  
  If (pDtmfDigit = "#") Then
    'Start voicemail
    retState = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                              False, rVarToSaveTmpFileNameDummy, bUseStdVM, _
                              bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                              szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    
    If (retState = gseStateTimeout) Then
      ConnectToSpecifiedNumberEx7 = 3
    ElseIf (retState = gseStateRecorded) Then
      ConnectToSpecifiedNumberEx7 = 4
    Else
      ConnectToSpecifiedNumberEx7 = 1
    End If
    Exit Function
  End If

  'Check return value
  If (retVal = PBXSuccess) Then
    'ConnectTo successful. Leave this function.
    ConnectToSpecifiedNumberEx7 = 2
  ElseIf (retVal = PBXFailure) Or (retVal = PBXCallTermOriginatorDisconnected) Then
    'Something wrong. End script action
    ConnectToSpecifiedNumberEx7 = 1
  Else
    'No response. Try next calllerid.
    ConnectToSpecifiedNumberEx7 = 0
  End If

End Function


' Split szNumber using ";"
' szNumber [in]  - String with multiply numbers
'          [out] - Updated string (without extracted number and ";")
' Return value: extracted number
Function SplitNumber(ByRef szNumber)
  Dim nPos, szSubNumber

  nPos = 1
  szSubNumber = ""

  nPos = InStr(szNumber, ";")
  If (nPos = 0) Then
    szSubNumber = szNumber
    szNumber = ""
  ElseIf (nPos = 1) Then
    szSubNumber = ""
    szNumber = Right(szNumber, Len(szNumber) - nPos)
  Else
    szSubNumber = Left(szNumber, nPos - 1)
    szNumber = Right(szNumber, Len(szNumber) - nPos)
  End If

  SplitNumber = szSubNumber
End Function


' Compare 2 strings
' First string can contain wildcards "?" for one digit and "*" any number of digis
Function CompareWithWildcards(ByVal szNumber1, ByVal szNumber2)
  Dim ch1, ch2, nPos, bSkip, szSub
  
  CompareWithWildcards = PBXScript.CompareNumbers(szNumber1,szNumber2)
End Function

'/////////////////////////////////
'//      Functions for GSE.     //
'/////////////////////////////////

'//// Build-In functions ////

' obsolete (functions to support very old scripts)
Function gseBuildIn_Time()
  Dim dtNow, szRes, szVal

  dtNow = PBXUser.Now
  
  szRes = ""
  szVal = CStr(Hour(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  szRes = szRes & szVal

  szVal = CStr(Minute(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  szRes = szRes & ":" & szVal

  szVal = CStr(Second(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  szRes = szRes & ":" & szVal

  gseBuildIn_Time = szRes
  PBXScript.OutputTrace "gseBuildIn_Time, rc = " & gseBuildIn_Time
End Function

Function gseBuildIn_Date()
  Dim dtNow, szRes, szVal

  dtNow = PBXUser.Now

  szRes = ""
  szVal = CStr(Day(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  szRes = szRes & szVal

  szVal = CStr(Month(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  szRes = szRes & "." & szVal

  szVal = CStr(Year(dtNow))
  ' Add leading zeros
  Do While (Len(szVal) < 4)
    szVal = "0" & szVal
  Loop
  szRes = szRes & "." & szVal

  gseBuildIn_Date = szRes
  PBXScript.OutputTrace "gseBuildIn_Date, rc = " & gseBuildIn_Date
End Function

Function gseBuildIn_CallerID()
  gseBuildIn_CallerID = PBXCall.CallingPartyNumber
  PBXScript.OutputTrace "gseBuildIn_CallerID, rc = " & gseBuildIn_CallerID
End Function

' obsolete since 4.20
Function CallerID()
  Dim szTmp, szRITmp, nIdx
  szTmp = PBXCall.CallingPartyNumber
  If (Left(szTmp, 2) = "##") Then
    ' remove "##xxx#" characters
    nIdx = InStr(3, szTmp, "#", 0)
    If (nIdx > 0) Then
      ' found
      PBXScript.OutputTrace "CallerID, in = " & szTmp
      szTmp = Mid(szTmp, nIdx+1)
    End If
  End If

  CallerID = szTmp
  PBXScript.OutputTrace "CallerID, rc = " & CallerID
End Function

Function gseBuildIn_Extension()
  gseBuildIn_Extension = PBXCall.CalledPartyNumber
  PBXScript.OutputTrace "gseBuildIn_Extension, rc = " & gseBuildIn_Extension
End Function

Function gseBuildIn_CallStart()
  gseBuildIn_CallStart = tCallStarted
  PBXScript.OutputTrace "gseBuildIn_CallStart, rc = " & gseBuildIn_CallStart
End Function

Function gseBuildIn_CallDuration()
  gseBuildIn_CallDuration = DateDiff("s", tCallStarted, PBXUser.Now)
  PBXScript.OutputTrace "gseBuildIn_CallDuration, rc = " & gseBuildIn_CallDuration
End Function

Function gseBuildIn_DayOfWeek()
  gseBuildIn_DayOfWeek = WeekDay(PBXUser.Now, vbMonday)
  PBXScript.OutputTrace "gseBuildIn_DayOfWeek, rc = " & gseBuildIn_DayOfWeek
End Function

Function gseBuildIn_DateTime()
  gseBuildIn_DateTime = CStr(PBXUser.Now)
  PBXScript.OutputTrace "gseBuildIn_DateTime, rc = " & gseBuildIn_DateTime
End Function

Function gseBuildIn_CallerName()
  gseBuildIn_CallerName = PBXCall.CallingPartyName
  PBXScript.OutputTrace "gseBuildIn_CallerName, rc = " & gseBuildIn_CallerName
End Function

Function gseBuildIn_PIN()
  gseBuildIn_PIN = PBXUser.PIN
  PBXScript.OutputTrace "gseBuildIn_PIN, rc = " & gseBuildIn_PIN
End Function

Function gseBuildIn_Hour()
  Dim szVal

  szVal = CStr(Hour(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Hour = szVal
  PBXScript.OutputTrace "gseBuildIn_Hour, rc = " & gseBuildIn_Hour
End Function

Function gseBuildIn_Minute()
  Dim szVal

  szVal = CStr(Minute(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Minute = szVal
  PBXScript.OutputTrace "gseBuildIn_Minute, rc = " & gseBuildIn_Minute
End Function

Function gseBuildIn_Second()
  Dim szVal

  szVal = CStr(Second(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Second = szVal
  PBXScript.OutputTrace "gseBuildIn_Second, rc = " & gseBuildIn_Second
End Function

Function gseBuildIn_Day()
  Dim szVal

  szVal = CStr(Day(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Day = szVal
  PBXScript.OutputTrace "gseBuildIn_Day, rc = " & gseBuildIn_Day
End Function

Function gseBuildIn_Month()
  Dim szVal

  szVal = CStr(Month(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 2)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Month = szVal
  PBXScript.OutputTrace "gseBuildIn_Month, rc = " & gseBuildIn_Month
End Function

Function gseBuildIn_Year()
  Dim szVal

  szVal = CStr(Year(PBXUser.Now))
  ' Add leading zeros
  Do While (Len(szVal) < 4)
    szVal = "0" & szVal
  Loop
  gseBuildIn_Year = szVal
  PBXScript.OutputTrace "gseBuildIn_Year, rc = " & gseBuildIn_Year
End Function

'//// END Build-In functions ////





'//// Functions for GSE blocks ////
Function gseStart()
  TraceFunction "gseStart", ""
  gseStart = gseStateStarted
  TraceFunctionResult "gseStart", gseStart
End Function


Function gseSituation(ByVal bCondition)
  TraceFunction "gseSituation", bCondition
  If (bCondition = True) Then
    gseSituation = gseStateTrue
  Else
    gseSituation = gseStateFalse
  End If
  TraceFunctionResult "gseSituation", gseSituation
End Function

Function gseTerminate(ByVal nCause)
  Dim retVal

  TraceFunction "gseTerminate", nCause
  retVal = PBXCall.Disconnect(CStr(Int(nCause)+3))
  gseTerminate = gseStateTerminated
  TraceFunctionResult "gseTerminate", gseTerminate
End Function

' support old version
Function gseConnectTo(ByVal szDialNumber, ByVal nTimeout)
  Dim retVal

  PBXScript.OutputTrace "old gseConnectTo is called..."
  retVal = gseConnectToEx(szDialNumber, nTimeout)

  If (retVal = gseStateTimeout) Then
    retVal = gseStateNoAnswer
  End If

  gseConnectTo = retVal
End Function

Function gseConnectToEx(ByVal szDialNumber, ByVal nTimeout)
  Dim retVal

  TraceFunction "gseConnectToEx", szDialNumber & ", " & nTimeout
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If
  
  retVal = ConnectToNumberOrMySelf(szDialNumber, nTimeout)
  If (retVal = PBXSuccess) Then
    ' It's ok.
    gseConnectToEx = gseStateConnected
  ElseIf (retVal = PBXCallTermDestinationBusy) Then
    ' BUSY output
    gseConnectToEx = gseStateNoAnswer
  ElseIf (retVal = PBXTimeout) Or (retVal = PBXCallTermWrongNumber) Or (retVal = PBXCallTermConnectToCallerImpossible) Or (retVal = PBXCallTermDestinationUnreachable) Or (retVal = PBXCallTermReject) Then
    ' TIMEOUT output
    gseConnectToEx = gseStateTimeout
  Else
    ' Call terminated (disconnected).
    gseConnectToEx = gseStateDisconnected
  End If

  TraceFunctionResult "gseConnectToEx", gseConnectToEx
End Function

' GSE >= 4.2.0.50
Function gseConnectToEx2(ByVal szDialNumber, ByVal nTimeout, _
                         ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                         ByVal bPlayAlertSound, ByVal szAlertSound, _
                         ByVal bProceedWithDestinationScript)
  AdjustBoolean bProceedWithDestinationScript
  gseConnectToEx2 = gseConnectToEx3(szDialNumber, nTimeout, _
                         fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                         bPlayAlertSound, szAlertSound, _
                         bProceedWithDestinationScript)
  ' Support new 4.31 output "Not Delivered"
  If (gseConnectToEx2 = gseStateNotDelivered) Then
    gseConnectToEx2 = gseStateTimeout
    PBXScriptOutputTrace "gseStateNotDelivered -> gseStateTimeout"
  End If

  ' Support new 4.31 ouputs "Connected"/"Busy"/etc
  If (bProceedWithDestinationScript = True) Then
    If (gseConnectToEx2 = gseStateConnected) Or (gseConnectToEx2 = gseStateNoAnswer) Or _
       (gseConnectToEx2 = gseStateTimeout) Or (gseConnectToEx2 = gseStateNotDelivered) Then
      gseConnectToEx2 = gseStateProceedWDstScr
      PBXScriptOutputTrace "gseStateXXX (in case of bProceedWithDestinationScript = True) -> gseStateProceedWDstScr"
    End If
  End If
End Function

' GSE >= 4.3.1.79
Function gseConnectToEx3(ByVal szDialNumber, ByVal nTimeout, _
                         ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                         ByVal bPlayAlertSound, ByVal szAlertSound, _
                         ByVal bProceedWithDestinationScript)
  Dim retVal

  TraceFunction "gseConnectToEx3", szDialNumber & ", " & nTimeout & ", " & _
                fMask & ", " & bStoreToVariable & ", " & rVariableName & ", " & bResetVariableContent & ", " & _
                bPlayAlertSound & ", " & szAlertSound & ", " & bProceedWithDestinationScript

  retVal = gseConnectToEx4(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                            bPlayAlertSound, szAlertSound, bProceedWithDestinationScript, "")

  gseConnectToEx3 = retVal

  TraceFunctionResult "gseConnectToEx3", gseConnectToEx3
End Function

' 5.10
Function gseConnectToEx4(ByVal szDialNumber, ByVal nTimeout, _
                         ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                         ByVal bPlayAlertSound, ByVal szAlertSound, _
                         ByVal bProceedWithDestinationScript, ByVal szCallingPartyNumber)
  gseConnectToEx4 = gseConnectToEx5(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                           bPlayAlertSound, szAlertSound, bProceedWithDestinationScript, szCallingPartyNumber, True)
End Function

' 6.12
Function gseConnectToEx5(ByVal szDialNumber, ByVal nTimeout, _
                         ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                         ByVal bPlayAlertSound, ByVal szAlertSound, _
                         ByVal bProceedWithDestinationScript, ByVal szCallingPartyNumber, _
                         ByVal bIncludeMobileDevices)
                         
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayAlertSound
  AdjustBoolean bProceedWithDestinationScript
  AdjustBoolean bIncludeMobileDevices
  
  gseConnectToEx5 = gseConnectToEx6(szDialNumber, nTimeout, _
                         fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                         bPlayAlertSound, szAlertSound, _
                         bProceedWithDestinationScript, szCallingPartyNumber, _
                         bIncludeMobileDevices)
End Function

' 6.20
Function gseConnectToEx6(ByVal szDialNumber, ByVal nTimeout, _
                         ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                         ByVal bPlayAlertSound, ByVal szAlertSound, _
                         ByVal bProceedWithDestinationScript, ByVal szCallingPartyNumber, _
                         ByVal bIncludeMobileDevices)

  Dim retVal, szOldCallingPartyNumber

  TraceFunction "gseConnectToEx6", szDialNumber & ", " & nTimeout & ", " & _
                fMask & ", " & bStoreToVariable & ", " & rVariableName & ", " & bResetVariableContent & ", " & _
                bPlayAlertSound & ", " & szAlertSound & ", " & bProceedWithDestinationScript & ", " & szCallingPartyNumber & ", " & _
                bIncludeMobileDevices

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If
  
  szOldCallingPartyNumber = Empty
  ' check if user defined calling party should be used
  If (Len(szCallingPartyNumber) > 0) Then
    ' save current PBXCall calling party to restore it afterwards
    szOldCallingPartyNumber = PBXCall.CallingPartyNumber

    If szCallingPartyNumber = "*orgdst*" Then
        ' got magic word, now setting calling party number to original destination number
        PBXCall.CallingPartyNumber = PBXCall.CalledPartyNumber
    Else
        ' set new PBXCall calling party to perform ConnectTo
        PBXCall.CallingPartyNumber = szCallingPartyNumber
    End If
  End If

  retVal = ConnectToNumberOrMySelfEx3(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, _
             bResetVariableContent, bPlayAlertSound, szAlertSound, bProceedWithDestinationScript, bIncludeMobileDevices)
  If (retVal = PBXSuccess) Then
    ' It's ok.
    gseConnectToEx6 = gseStateConnected
    ' set alerted flag to true to skip post processing
    g_bCallAlerted = true
  ElseIf (retVal = PBXDestinationScriptStarted) Then
    ' Call proceed with destination script
    gseConnectToEx6 = gseStateProceedWDstScr
  ElseIf (retVal = PBXCallTermDestinationBusy) Then
    ' BUSY output
    gseConnectToEx6 = gseStateNoAnswer
    ' set alerted flag to true to skip post processing
    g_bCallAlerted = true
  ElseIf (retVal = PBXTimeout) Then
    ' TIMEOUT output (for result = Timeout)
    gseConnectToEx6 = gseStateTimeout
    ' set alerted flag to true to skip post processing
    g_bCallAlerted = true
  ElseIf (retVal = PBXCallTermOriginatorDisconnected) Or (retVal = PBXFailure) Then
    ' Call terminated (disconnected).
    gseConnectToEx6 = gseStateDisconnected
  ElseIf (retVal = PBXCallTermCancelled) Then
    ' DTMF Key pressed
    gseConnectToEx6 = gseStateDTMFKeyPressed
  Else
    ' NotDelivered output (all other results)
    gseConnectToEx6 = gseStateNotDelivered
  End If

  ' restore calling party number if user defined was used
  If NOT IsEmpty(szOldCallingPartyNumber) Then
    PBXCall.CallingPartyNumber = szOldCallingPartyNumber
  End If

  TraceFunctionResult "gseConnectToEx6", gseConnectToEx6
End Function

Function gsePlaySound(ByVal szSound, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  Dim retVal, pDtmfDigit

  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  TraceFunction "gsePlaySound", szSound & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  pDtmfDigit = "x"
  retVal = PBXCallGetDtmfInputEx(szSound, 0, 0, fMask, 0, pDtmfDigit)
  
  If ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
    ' It's ok.
    If (Len(pDtmfDigit) > 0) Then
      ' DTMF key pressed
      gsePlaySound = gseStateDTMFKeyPressed
      If (bStoreToVariable = True) Then
        If (bResetVariableContent = True) Then
          ' Reset variable content
          szVariableName = ""
        End If
        szVariableName = szVariableName & pDtmfDigit
      End If
    Else
      gsePlaySound = gseStatePlayed
    End If
  Else
    ' Call terminated (disconnected).
    gsePlaySound = gseStateDisconnected
  End If
  
  TraceFunctionResult "gsePlaySound", gsePlaySound
End Function

' GSE 4.2.0.51
Function gsePlaySoundEx(ByVal szSound, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                        ByVal bSkipBegining, ByVal nSkipSeconds, ByVal bPlayControl)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bSkipBegining
  AdjustBoolean bPlayControl
  
  gsePlaySoundEx = gsePlaySoundEx2(szSound, fMask, bStoreToVariable, szVariableName, bResetVariableContent, bSkipBegining, nSkipSeconds, bPlayControl)
End Function
                        
' GSE 6.12.0.18
Function gsePlaySoundEx2(ByVal szSound, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                        ByVal bSkipBegining, ByVal nSkipSeconds, ByVal bPlayControl)
  Dim retVal, pDtmfDigit
  
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  TraceFunction "gsePlaySoundEx2", szSound & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent & ", " & _
                                  bSkipBegining & ", " & nSkipSeconds & ", " & bPlayControl

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (bSkipBegining = True) Then
    nSkipSeconds = CInt(nSkipSeconds)
  Else
    nSkipSeconds = 0
  End If

  pDtmfDigit = ""

  retVal = PBXCallGetDtmfInputEx3(szSound, 0, 0, fMask, 0, pDtmfDigit, bSkipBegining, nSkipSeconds, bPlayControl)
  
  If ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
    ' It's ok.
    If (Len(pDtmfDigit) > 0) Then
      ' DTMF key pressed
      gsePlaySoundEx2 = gseStateDTMFKeyPressed
      If (bStoreToVariable = True) Then
        If (bResetVariableContent = True) Then
          ' Reset variable content
          szVariableName = ""
        End If
        szVariableName = szVariableName & pDtmfDigit
      End If
    Else
      gsePlaySoundEx2 = gseStatePlayed
    End If
  Else
    ' Call terminated (disconnected).
    gsePlaySoundEx2 = gseStateDisconnected
  End If
  
  TraceFunctionResult "gsePlaySoundEx2", gsePlaySoundEx2
End Function


' obsolete
Function gseRecordMessage(ByVal nTimeout)
  gseRecordMessage = gseRecordMessageEx(nTimeout, False)
End Function

Function gseRecordMessageEx(ByVal nTimeout, ByVal bPlayBeep)
  Dim retVal

  AdjustBoolean bPlayBeep
  
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  TraceFunction "gseRecordMessageEx", CStr(nTimeout) & ", " & bPlayBeep

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (bPlayBeep = True) Then
    retVal = PBXCallPlayMessageEx("Beep.wav")
  End If
  
  retVal = PBXCall.RecordMessage(nTimeout)
  
  If (retVal = PBXTimeout) Then
    ' It's ok.
    gseRecordMessageEx = gseStateTimeout
  ElseIf (retVal = PBXFailure) Then
    ' Server return Failure => output disconnect
    gseRecordMessageEx = gseStateDisconnected
  Else
    ' Call terminated (recorded).
    gseRecordMessageEx = gseStateRecorded
  End If

  TraceFunctionResult "gseRecordMessageEx", gseRecordMessageEx
End Function

Function gseRecordMessageEx2(ByVal nTimeout, ByVal bPlayBeep, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName)
  Dim retVal
  retVal = gseRecordMessageEx(nTimeout, bPlayBeep)
  AdjustBoolean bSaveTmpFileNameToVar
  If (bSaveTmpFileNameToVar = True) Then
    rVarToSaveTmpFileName = PBXCall.LastRecordedMessage
    PBXScript.OutputTrace "LastRecordedMessage = " & rVarToSaveTmpFileName
  End If
  gseRecordMessageEx2 = retVal
End Function

' GSE 4.2.0.50
Function gseRecordMessageEx3(ByVal nTimeout, ByVal bPlayBeep, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                             ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                             ByVal bStopOnSilence, ByVal nStopOnSilenceTimeout)
                             
  AdjustBoolean bPlayBeep
  AdjustBoolean bSaveTmpFileNameToVar
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bStopOnSilence
  gseRecordMessageEx3 = gseRecordMessageEx4(nTimeout, bPlayBeep, bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                             fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                             bStopOnSilence, nStopOnSilenceTimeout)
End Function
' GSE 4.2.0.50
Function gseRecordMessageEx4(ByVal nTimeout, ByVal bPlayBeep, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                             ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                             ByVal bStopOnSilence, ByVal nStopOnSilenceTimeout)
  TraceFunction "gseRecordMessageEx4", CStr(nTimeout) & ", " & bPlayBeep & ", " & bSaveTmpFileNameToVar & ", " & _
                fMask & ", " & bStoreToVariable & ", " & rVariableName & ", " & bResetVariableContent & ", " & _
                bStopOnSilence & ", " & nStopOnSilenceTimeout

  Dim retVal, nStopAfterSecSilence, szDTMFDigit
  
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (bPlayBeep = True) Then
    retVal = PBXCallPlayMessageEx("Beep.wav")
  End If

  If (bStopOnSilence = True) Then
    nStopAfterSecSilence = CInt(nStopOnSilenceTimeout)
  Else
    nStopAfterSecSilence = 0
  End If

  szDTMFDigit = ""
  
  retVal = PBXCall.RecordMessageEx(CInt(nTimeout), nStopAfterSecSilence, fMask, szDTMFDigit)
  PBXScript.OutputTrace "retVal = " & ExtractReturnValue(retVal) & ", DTMFDigit = " & szDTMFDigit

  If (retVal = PBXTimeout) Then
    ' It's ok.
    gseRecordMessageEx4 = gseStateTimeout
  ElseIf (retVal = PBXCallTermNormalCallClearing) Then
    ' message recorded
    gseRecordMessageEx4 = gseStateRecorded
  ElseIf (retVal = PBXSuccess) Then
    ' check szDTMFDigit
    If (Len(szDTMFDigit) > 0) Then
      ' DTMF key pressed
      If (bStoreToVariable = True) Then
        If (bResetVariableContent = True) Then
          rVariableName = ""
        End If
        rVariableName = rVariableName & szDTMFDigit
      End If
      gseRecordMessageEx4 = gseStateDTMFKeyPressed
    Else
      ' Silence detected
      gseRecordMessageEx4 = gseStateSilenceDetected
    End If
  Else
    ' Something wrong
    gseRecordMessageEx4 = gseStateDisconnected
  End If
  
  If (bSaveTmpFileNameToVar = True) Then
    rVarToSaveTmpFileName = PBXCall.LastRecordedMessage
    PBXScript.OutputTrace "LastRecordedMessage = " & rVarToSaveTmpFileName
  End If
  
  TraceFunctionResult "gseRecordMessageEx4", gseRecordMessageEx4
End Function

Function gseSendEMail(ByVal szAddress, ByVal szSubject, ByVal szBody, ByVal bAttach)
  gseSendEMail = gseSendEMailEx(szAddress, szSubject, szBody, bAttach)

  ' Support new 4.31 output "Disconnected"
  If (gseSendEMail = gseStateDisconnected) Then
    gseSendEMail = gseStateSent
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateSent"
  End If
End Function

' GSE >= 4.3.1.79
Function gseSendEMailEx(ByVal szAddress, ByVal szSubject, ByVal szBody, ByVal bAttach)
  Dim retVal, szSubAddress
  
  AdjustBoolean bAttach
  
  TraceFunction "gseSendEMailEx", szAddress & ", " & szSubject & ", " & szBody & ", " & bAttach
  Do While (Len(szAddress) > 0)
    szSubAddress = SplitNumber(szAddress)
    'Send Email
    If (Len(szSubAddress) > 0) Then
      retVal = PBXCall.SendEMail(szSubAddress, szSubject, szBody, bAttach)
    End If
  Loop
  
  gseSendEMailEx = gseStateSent

  CheckIfCallIsDisconnected gseSendEMailEx

  TraceFunctionResult "gseSendEMailEx", gseSendEMailEx
End Function

Function IsEmail(ByVal szAddress)
Dim retVal

  retVal = InStr(1, szAddress, "@", vbTextCompare)

  If (retVal = 0) OR (retVal = 1) OR (retVal = Null) Then
    IsEmail = False
  else
    IsEmail = True
  End If

End Function

'5.10
Function gseSendEMailEx2(ByVal szAddress, ByVal szSubject, ByVal szBody, ByVal AttachmentType, ByVal szFrom, ByVal szReplyTo, _
                         ByVal szCC, ByVal szBCC, ByVal szFileNameToSend, ByVal bSignalNewVoicemail, ByVal szUserName)
  AdjustBoolean bSignalNewVoicemail
  gseSendEMailEx2 = gseSendEMailEx3(szAddress, szSubject, szBody, AttachmentType, szFrom, szReplyTo, _
                         szCC, szBCC, szFileNameToSend, bSignalNewVoicemail, szUserName)
End Function

'6.20
Function gseSendEMailEx3(ByVal szAddress, ByVal szSubject, ByVal szBody, ByVal AttachmentType, ByVal szFrom, ByVal szReplyTo, _
                         ByVal szCC, ByVal szBCC, ByVal szFileNameToSend, ByVal bSignalNewVoicemail, ByVal szUserName)
  On Error Resume Next
  
  Dim retVal, szResultingSendToAddress, szSubAddress, szAttach, oPBXConfig, oUsers, oUsersForNVM, oUser, bNewVM, nNewAndUnreadVMs

  PBXScriptOutputTrace "--> gseSendEMailEx3"

  Set oPBXConfig = PBXScript.CreateObject("IpPBxSrv.PBXConfig")

  oUsers = Empty
  oUsersForNVM = Empty
  szResultingSendToAddress = ""

  If NOT szAddress = Trim(PBXUser.VoicemailEMailAddress) Then
    Do While (Len(szAddress) > 0)
      szSubAddress = SplitNumber(szAddress)
      If (Len(szSubAddress) > 0) Then
        If IsEmail(szSubAddress) Then
          If szResultingSendToAddress = "" Then
            szResultingSendToAddress = szSubAddress
          Else
            szResultingSendToAddress = szResultingSendToAddress & "; " & szSubAddress
          End If
        Else
          'todo: insert code to find e-mail address by user name or number
          'realized method is not preferred
          Set oUsers = oPBXConfig.GetUserByAddress(szSubAddress)
          For Each oUser In oUsers
            If szResultingSendToAddress = "" Then
              szResultingSendToAddress = oUser.EMailAddress
            Else
              szResultingSendToAddress = szResultingSendToAddress & "; " & oUser.EMailAddress
            End If
          Next
        End If
      End If
    Loop
  Else
    szResultingSendToAddress = Trim(PBXUser.VoicemailEMailAddress)
  End If

  'check for additional user name to signal 'Voicemail available' to
  If (Len(szUserName) > 0) Then
    Set oUsersForNVM = oPBXConfig.GetUserByAddress(szUserName)
  End If

  szAttach = ""
  Select Case AttachmentType
    Case "None" szAttach = ""
    Case "Last" szAttach = PBXCall.LastRecordedMessage
    Case "File" szAttach = szFileNameToSend
    Case Else szAttach = ""
  End Select

  If bSignalNewVoicemail = True Then
    bNewVM = True
  Else
    bNewVM = False
  End If

  PBXScriptOutputTrace "Sending an e-mail to: " & szResultingSendToAddress
  PBXScriptOutputTrace "Attachment          : " & szAttach
  PBXScriptOutputTrace "IsVoiceMail         : " & bSignalNewVoicemail

  retVal = PBXScript.SendEMail(szFrom, szReplyTo, szResultingSendToAddress, szCC, szBCC, szSubject, szBody, szAttach, "", bNewVM)

  If retVal = PBXSuccess Then
    gseSendEMailEx3 = gseStateSent
    If bNewVM = True Then
      If NOT IsEmpty(oUsersForNVM) Then
        'get number of new and unread VMs and increment by one
        For Each oUser In oUsersForNVM
          nNewAndUnreadVMs = oUser.NumberOfNewVoicemails + 1
          PBXScript.OutputTrace "Number of new and unread voicemails for additional user '" & oUser.Name & "' is " & nNewAndUnreadVMs
          oUser.NumberOfNewVoicemails = nNewAndUnreadVMs
        Next
      ElseIf NOT IsEmpty(oUsers) Then
        'get number of new and unread VMs and increment by one
        For Each oUser In oUsers
         nNewAndUnreadVMs = oUser.NumberOfNewVoicemails + 1
         PBXScript.OutputTrace "Number of new and unread voicemails for user '" & oUser.Name & "' is " & nNewAndUnreadVMs
         oUser.NumberOfNewVoicemails = nNewAndUnreadVMs
        Next
      Else
        nNewAndUnreadVMs = PBXUser.NumberOfNewVoicemails + 1
        PBXScript.OutputTrace "Number of new and unread voicemails = " & nNewAndUnreadVMs
        PBXUser.NumberOfNewVoicemails = nNewAndUnreadVMs
      End If
    End If
  Else
    gseSendEMailEx3 = gseStateSent ' GSE does not support gseStateFailed output so far, so use Sent output instead
  End If

  PBXScriptOutputTrace "<-- gseSendEMailEx3, return value = " & ExtractReturnValue(gseSendEMailEx3)

  CheckIfCallIsDisconnected gseSendEMailEx3

End Function

'support old version
Function gseFollowMe(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound)
  gseFollowMe = gseFollowMeEx(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     False, "", "", "", "", False, False)
End Function

' obsolete
Function gseFollowMeEx(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  ' obsolete. for 4.00 support
  gseFollowMeEx = gseFollowMeEx2(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                     g_szStdRiPIN, True)
End Function


' obsolete
Function gseFollowMeEx2(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI)

  Dim rVarToSaveTmpFileNameDummy
  gseFollowMeEx2 = gseFollowMeEx4(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     False, rVarToSaveTmpFileNameDummy, _
                     False, _
                     bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, False)

End Function


' obsolete
Function gseFollowMeEx3(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI)

  gseFollowMeEx3 = gseFollowMeEx4(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                     False, _
                     bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, False)
End Function


' 4.30
Function gseFollowMeEx4(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bUseStdVM, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  
  gseFollowMeEx4 = gseFollowMeEx5(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                     bUseStdVM, _
                     bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, bStdRIWithoutPIN)
End Function

' 4.31
Function gseFollowMeEx5(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bUseStdVM, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  
  gseFollowMeEx5 = gseFollowMeEx6(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                     bUseStdVM, _
                     bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, bStdRIWithoutPIN, False)
End Function

' 5.00
Function gseFollowMeEx6(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bUseStdVM, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)


  Dim retVal

  TraceFunction "gseFollowMeEx6", bAccept & ", " & szAcceptSound & ", " & bDeliver & ", " & nDeliverSec & ", " & _
                     bCallFwd1 & ", " & szCallFwdTo1 & ", " & nCallFwdSec1 & ", " & _
                     bCallFwd2 & ", " & szCallFwdTo2 & ", " & nCallFwdSec2 & ", " & _
                     bCallFwd3 & ", " & szCallFwdTo3 & ", " & nCallFwdSec3 & ", " & _
                     bCallFwdVoice & ", " & bPreFwd & ", " & szPreFwdSound & ", " & _
                     bActivate & ", " & bGreeting & ", " & szGreetingSound & ", " & _
                     bUseDTMF & ", " & szUseDTMFAnnouncementSound & ", " & _
                     bAnnouncement & ", " & szAnnouncementSound & ", " & nRecordMessage & ", " & _
                     szAddress & ", " & bUseStdVM & ", " & szSound & ", " &_
                     bEnabled & ", " & szServerName & ", " & szUserName & ", " & szPassword & ", " & bPasswordEncoded & ", " & szMailFolder & ", " & bUseSSL & ", " & bUsePINPrompt & ", " & _
                     szPIN & ", " & bUseStdRI & ", " & bStdRIWithoutPIN & ", " & bUseFromCriteria
  
  retVal = gseFollowMeEx7(bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, "", bGreeting,szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound,nRecordMessage, _
                     szAddress, szSound, bSaveTmpFileNameToVar, rVarToSaveTmpFileName, bUseStdVM, _
                     bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)

  gseFollowMeEx6 = retVal

  TraceFunctionResult "gseFollowMeEx6", gseFollowMeEx6
End Function

'5.10
Function gseFollowMeEx7(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal szCallingPartyNumber, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bUseStdVM, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  AdjustBoolean bAccept
  AdjustBoolean bDeliver
  AdjustBoolean bCallFwd1
  AdjustBoolean bCallFwd2
  AdjustBoolean bCallFwd3
  AdjustBoolean bCallFwdVoice
  AdjustBoolean bPreFwd
  AdjustBoolean bActivate
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement
  AdjustBoolean bSaveTmpFileNameToVar
  AdjustBoolean bUseStdVM
  AdjustBoolean bEnabled
  AdjustBoolean bPasswordEncoded
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
  gseFollowMeEx7 = gseFollowMeEx8(bAccept, szAcceptSound, bDeliver, nDeliverSec, _
                     bCallFwd1, szCallFwdTo1, nCallFwdSec1, _
                     bCallFwd2, szCallFwdTo2, nCallFwdSec2, _
                     bCallFwd3, szCallFwdTo3, nCallFwdSec3, _
                     bCallFwdVoice, bPreFwd, szPreFwdSound, _
                     bActivate, szCallingPartyNumber, bGreeting, szGreetingSound, _
                     bUseDTMF, szUseDTMFAnnouncementSound, _
                     bAnnouncement, szAnnouncementSound, nRecordMessage, _
                     szAddress, szSound, _
                     bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                     bUseStdVM, _
                     bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                     szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
End Function

'6.20
Function gseFollowMeEx8(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, _
                     ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, _
                     ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, _
                     ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, _
                     ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, _
                     ByVal bActivate, ByVal szCallingPartyNumber, ByVal bGreeting, ByVal szGreetingSound, _
                     ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                     ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                     ByVal szAddress, ByVal szSound, _
                     ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                     ByVal bUseStdVM, _
                     ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                     ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)


  Dim retVal, pDtmfDigit, retState, bPlayPreFwd, rResultOfLastConnectTo, szDigitMask, szOldCallingPartyNumber, pDummyV

  TraceFunction "gseFollowMeEx8", bAccept & ", " & szAcceptSound & ", " & bDeliver & ", " & nDeliverSec & ", " & _
                     bCallFwd1 & ", " & szCallFwdTo1 & ", " & nCallFwdSec1 & ", " & _
                     bCallFwd2 & ", " & szCallFwdTo2 & ", " & nCallFwdSec2 & ", " & _
                     bCallFwd3 & ", " & szCallFwdTo3 & ", " & nCallFwdSec3 & ", " & _
                     bCallFwdVoice & ", " & bPreFwd & ", " & szPreFwdSound & ", " & _
                     bActivate & ", " & szCallingPartyNumber & ", " & bGreeting & ", " & szGreetingSound & ", " & _
                     bUseDTMF & ", " & szUseDTMFAnnouncementSound & ", " & _
                     bAnnouncement & ", " & szAnnouncementSound & ", " & nRecordMessage & ", " & _
                     szAddress & ", " & bUseStdVM & ", " & szSound & ", " &_
                     bEnabled & ", " & szServerName & ", " & szUserName & ", " & szPassword & ", " & bPasswordEncoded & ", " & szMailFolder & ", " & bUseSSL & ", " & bUsePINPrompt & ", " & _
                     szPIN & ", " & bUseStdRI & ", " & bStdRIWithoutPIN & ", " & bUseFromCriteria
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If
  
  pDtmfDigit = "x"
  rResultOfLastConnectTo = PBXSuccess
  szDigitMask = ""
  
  If (bCallFwdVoice = False And bActivate = False) Then
    ' Do not start RI because user does not define RI outputs in GSE
    bEnabled = False
  End If

  If (bEnabled = True) Then
    ' RI enabled
    szDigitMask = "*"
  End If

  If (bActivate = True) Then
    szDigitMask = szDigitMask & "#"
  End If

  szOldCallingPartyNumber = Empty
  ' check if user defined calling party should be used
  If (Len(szCallingPartyNumber) > 0) Then
    ' save current PBXCall calling party to restore it afterwards
    szOldCallingPartyNumber = PBXCall.CallingPartyNumber

    If szCallingPartyNumber = "*orgdst*" Then
        ' got magic word, now setting calling party number to original destination number
        PBXCall.CallingPartyNumber = PBXCall.CalledPartyNumber
    Else
        ' set new PBXCall calling party to perform ConnectTo
        PBXCall.CallingPartyNumber = szCallingPartyNumber
    End If
  End If

  'Play announcement sound
  If (bAccept = True) Then
    retVal = PBXCallGetDtmfInputEx(szAcceptSound, 0, 0, szDigitMask, 0, pDtmfDigit)
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true
    If (bEnabled = True And pDtmfDigit = "*") Then
      ' Start RI, leave this func
      If (bUseStdVM = True) Then
        ' start standard RI
        gseFollowMeEx8 = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, True, bStdRIWithoutPIN, bUseFromCriteria)
      Else
        ' start custom RI
        gseFollowMeEx8 = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
      End If

      ' restore calling party number if user defined was used
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
      Exit Function
    End If
    If (pDtmfDigit = "#") Then
      'Start voicemail
      retState = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                                bSaveTmpFileNameToVar, rVarToSaveTmpFileName, bUseStdVM, _
                                bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                                szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      If (retState = gseStateTimeout) Then
        ' voicemail (timeout)
        gseFollowMeEx8 = gseStateTimeout
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      ElseIf (retState = gseStateRecorded) Then
        ' voicemail (disconnect)
        gseFollowMeEx8 = gseStateRecorded
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      Else
        ' disconnected
        gseFollowMeEx8 = gseStateDisconnected
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      End If
    End If
    If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
      'Something wrong. End this action
      TraceError "gseFollowMeEx8", "Disconnect on szAcceptSound.", retVal
      gseFollowMeEx8 = gseStateDisconnected
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
      Exit Function
    End If
  End If
  
  'Connect to myself
  If (bDeliver = True) Then
    If (bActivate = True) Then
      szDigitMask = "#"
      If (Not bCallConnected) Then
        ' Accept call automatically
        retVal = PBXCall.PlayMessage("Announcements/Silence_200ms.wav")
        bCallConnected = True
      End If
    Else
      szDigitMask = ""
    End If
    pDtmfDigit = ""
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nDeliverSec, 0, "", szDigitMask, pDtmfDigit, true, nDeliverSec, true, "", szDigitMask, pDummyV, false, true)
    If (retVal = PBXDestinationScriptStarted) Then
      ' in case if call was proceed with destination script while deflecting return back calling party number
      ' this is why we are calling PBXCallConnectToWrapper with last parameter set to "false" --> we will end the
      ' script manually returning back calling party numer first
      PBXScript.EndScript()
      Exit Function
    End If
    rResultOfLastConnectTo = retVal

    If retVal = PBXCallTermOriginatorDisconnected Then
      'Everything was OK but caller hung up
      gseFollowMeEx8 = gseStateDisconnected
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
      Exit Function
    End If

    If (pDtmfDigit = "#") Then
      'Start voicemail
      retState = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                                bSaveTmpFileNameToVar, rVarToSaveTmpFileName, bUseStdVM, _
                                bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                                szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      If (retState = gseStateTimeout) Then
        ' voicemail (timeout)
        gseFollowMeEx8 = gseStateTimeout
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      ElseIf (retState = gseStateRecorded) Then
        ' voicemail (disconnect)
        gseFollowMeEx8 = gseStateRecorded
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      Else
        ' disconnected
        gseFollowMeEx8 = gseStateDisconnected
        TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
        Exit Function
      End If
    End If

    If (retVal = PBXSuccess) Then
      'Its ok. Leave this function.
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      gseFollowMeEx8 = gseStateConnected
      TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
      Exit Function
    ElseIf (retVal = PBXFailure) Then
      'Something wrong. End this action
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      gseFollowMeEx8 = gseStateDisconnected
      TraceError "gseFollowMeEx8", "Fail on ConnectTo MySelf.", retVal
      TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
      Exit Function
    Else
      'No response. Try next calllerid.
    End If
  End If


  'Connect to specified numbers.
  ' Note on return values of ConnectToSpecifiedNumber(...)       
  ' retState = 0  => not connected and try next destination 
  ' retState = 1  => failure occured. Stop script action
  ' retState = 2  => connected successful.
  ' retState = 3  => Voicemail (timeout)
  ' retState = 4  => Voicemail (disconnect)
  ' retState = 5  => gseStateIMAP4Success
  ' retState = 6  => gseStateIMAP4Error

  If (bCallFwd1 = True) Then
    ' If bDeliver is not selected (connect to original destination) do not play pre-fwd sound (#2894)
    If ((bDeliver = True) And (bPreFwd = True)) Then
      bPlayPreFwd = True
    Else
      bPlayPreFwd = False
    End If


    retState = ConnectToSpecifiedNumberEx7(bPlayPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                   szCallFwdTo1, nCallFwdSec1, _
                   bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)

    If (retState <> 0) Then
        If NOT IsEmpty(szOldCallingPartyNumber) Then
            PBXCall.CallingPartyNumber = szOldCallingPartyNumber
        End If
    End If

    If (CheckReturnIfResult("gseFollowMeEx8", retState) = True) Then
      gseFollowMeEx8 = retState
      Exit Function
    End If
  End If

  If (bCallFwd2 = True) Then
    retState = ConnectToSpecifiedNumberEx7(bPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                   szCallFwdTo2, nCallFwdSec2, _
                   bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)

    If (retState <> 0) Then
        If NOT IsEmpty(szOldCallingPartyNumber) Then
            PBXCall.CallingPartyNumber = szOldCallingPartyNumber
        End If
    End If
    
    If (CheckReturnIfResult("gseFollowMeEx8", retState) = True) Then
      gseFollowMeEx8 = retState
      Exit Function
    End If
  End If
  
  If (bCallFwd3 = True) Then
    retState = ConnectToSpecifiedNumberEx7(bPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, szSound, _
                   szCallFwdTo3, nCallFwdSec3, _
                   bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)

    If (retState <> 0) Then
        If NOT IsEmpty(szOldCallingPartyNumber) Then
            PBXCall.CallingPartyNumber = szOldCallingPartyNumber
        End If
    End If

    If (CheckReturnIfResult("gseFollowMeEx8", retState) = True) Then
      gseFollowMeEx8 = retState
      Exit Function
    End If
  End If
  
  ' Connect directly to voicemail, if it is selected.
  If (bCallFwdVoice = True) Then
    retVal = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, szSound, _
                            bSaveTmpFileNameToVar, rVarToSaveTmpFileName, bUseStdVM, _
                            bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    gseFollowMeEx8 = retVal
    TraceInfo "gseFollowMeEx8", gseFollowMeEx8
    If NOT IsEmpty(szOldCallingPartyNumber) Then
      PBXCall.CallingPartyNumber = szOldCallingPartyNumber
    End If
    TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8
    Exit Function
  End If
  
  gseFollowMeEx8 = gseStateNoAnswer
  If NOT IsEmpty(szOldCallingPartyNumber) Then
    PBXCall.CallingPartyNumber = szOldCallingPartyNumber
  End If
  TraceFunctionResult "gseFollowMeEx8", gseFollowMeEx8


  If (bSaveTmpFileNameToVar = True) Then
    rVarToSaveTmpFileName = PBXCall.LastRecordedMessage
    PBXScript.OutputTrace "LastRecordedMessage = " & rVarToSaveTmpFileName
  End If
End Function

Function CheckReturnIfResult(ByVal szFunctionName, ByRef retState)
    If (retState = 1) Then
      ' disconnected
      retState = gseStateDisconnected
    ElseIf (retState = 2) Then
      ' connected
      retState = gseStateConnected
    ElseIf (retState = 3) Then
      ' voicemail (timeout)
      retState = gseStateTimeout
    ElseIf (retState = 4) Then
      ' voicemail (disconnect)
      retState = gseStateRecorded
    ElseIf (retState = 5) Then
      ' RI success
      retState = gseStateIMAP4Success
    ElseIf (retState = 6) Then
      ' RI access failed
      retState = gseStateIMAP4Error
    Else 
      CheckReturnIfResult = False
      Exit Function
    End If
    TraceFunctionResult szFunctionName, retState
    CheckReturnIfResult = True
End Function

'support old version
Function gseVoicemail(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound)
  gseVoicemail = gseVoicemailEx(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                      bAnnouncement, szAnnouncementSound, nRecordMessage, _
                      szAddress, szSound, _
                      False, "", "", "", "", False, False)
End Function

' obsolete
Function gseVoicemailEx(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  gseVoicemailEx = gseVoicemailEx2(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                      bAnnouncement, szAnnouncementSound, nRecordMessage, _
                      szAddress, szSound, _
                      bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                      g_szStdRiPIN, True)
End Function

' obsolete
Function gseVoicemailEx2(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI)
  
  Dim rVarToSaveTmpFileNameDummy
  gseVoicemailEx2 = gseVoicemailEx4(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                          bAnnouncement, szAnnouncementSound, nRecordMessage, _
                          szAddress, szSound, _
                          False, rVarToSaveTmpFileNameDummy, _
                          False, _
                          bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                          szPIN, bUseStdRI, False)
End Function

' obsolete
Function gseVoicemailEx3(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI)
  gseVoicemailEx3 = gseVoicemailEx4(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                          bAnnouncement, szAnnouncementSound, nRecordMessage, _
                          szAddress, szSound, _
                          bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                          False, _
                          bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                          szPIN, bUseStdRI, False)
End Function


' for 4.20
Function gseVoicemailEx4(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                      ByVal bUseStdVM, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)

  gseVoicemailEx4 = gseVoicemailEx5(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                      bAnnouncement, szAnnouncementSound, nRecordMessage, _
                      szAddress, szSound, _
                      bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                      bUseStdVM, _
                      bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                      szPIN, bUseStdRI, bStdRIWithoutPIN)
End Function

' 4.31
Function gseVoicemailEx5(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                      ByVal bUseStdVM, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)

  gseVoicemailEx5 = gseVoicemailEx6(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                      bAnnouncement, szAnnouncementSound, nRecordMessage, _
                      szAddress, szSound, _
                      bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                      bUseStdVM, _
                      bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                      szPIN, bUseStdRI, bStdRIWithoutPIN, False)
End Function

' 5.00
Function gseVoicemailEx6(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                      ByVal bUseStdVM, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement
  AdjustBoolean bSaveTmpFileNameToVar
  AdjustBoolean bUseStdVM
  AdjustBoolean bEnabled
  AdjustBoolean bPasswordEncoded
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
  
  gseVoicemailEx6 = gseVoicemailEx7(bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                      bAnnouncement, szAnnouncementSound, nRecordMessage, _
                      szAddress, szSound, _
                      bSaveTmpFileNameToVar, rVarToSaveTmpFileName, _
                      bUseStdVM, _
                      bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, _
                      szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
End Function

' 6.20
Function gseVoicemailEx7(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, _
                      ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, _
                      ByVal szAddress, ByVal szSound, _
                      ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName, _
                      ByVal bUseStdVM, _
                      ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                      ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  Dim retVal, szCallerID, pDtmfDigit, retVal2, szDtmfMask, szDtmfMaskTmp

  TraceFunction "gseVoicemailEx7", bGreeting & ", " & szGreetingSound & ", " & bUseDTMF & ", " & szUseDTMFAnnouncementSound & ", " & _
                      bAnnouncement & ", " & szAnnouncementSound & ", " & nRecordMessage & ", " & _
                      szAddress & ", " & szSound  & ", " & bUseStdVM & ", " & _
                      bEnabled & ", " & szServerName & ", " & szUserName & ", " & szPassword & ", " & bPasswordEncoded & ", " & szMailFolder & ", " & bUseSSL & ", " & bUsePINPrompt & ", " & _
                      szPIN & ", " & bUseStdRI & ", " & bStdRIWithoutPIN & ", " & bUseFromCriteria

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  nRecordMessage = CInt(nRecordMessage)

  ' set connected flag to true to skip post processing
  bCallConnected = true

  ' If we use stnadard VM start it immediatelly
  If (bUseStdVM = True) Then
    PBXScript.OutputTrace "use Standard Voicemail"
    StandardVoicemailEx
    ' for standard RI allways return first output "Recorded (timeout)"
    gseVoicemailEx7 = gseStateTimeout
    Exit Function
  End If

  If (bEnabled = True) Then
    ' allow Remote inquiry
    szDtmfMask = "*"
  Else
    ' disable Remote inquiry
    szDtmfMask = ""
  End If

  'Play greeting
  If (bGreeting = True) Then
    retVal = PBXCallGetDtmfInputEx(szGreetingSound, 0, 0, szDtmfMask, 0, pDtmfDigit)
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      retVal2 = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
      gseVoicemailEx7 = retVal2
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If

    If Not ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
      'Something wrong. End this action
      TraceError "gseVoicemailEx7", "Disconnect on szGreetingSound.", retVal
      gseVoicemailEx7 = gseStateDisconnected
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If
  End If
  
  'Play DTMF announcement sound
  If ((bUseDTMF = True) and (PBXCall.CallingPartyNumber = "")) Then
    szDtmfMaskTmp = "1234567890#" & szDtmfMask
    pDtmfDigit = ""

    retVal = PBXCallGetDtmfInputEx(szUseDTMFAnnouncementSound, 0, 0, szDtmfMaskTmp, 15, pDtmfDigit)
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      retVal2 = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
      gseVoicemailEx7 = retVal2
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If

    If Not ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
      'Something wrong. End this action
      TraceError "gseVoicemailEx7", "Disconnect on szUseDTMFAnnouncementSound.", retVal
      gseVoicemailEx7 = gseStateDisconnected
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If
  
    'Get CallerID; "#" - end input
    szCallerID = pDtmfDigit
              
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true
    retVal = PBXSuccess  
    Do While (retVal = PBXSuccess)
      If (pDtmfDigit = "#") Then
        szCallerID = ""
        Exit Do
      End If
      pDtmfDigit = ""
      retVal = PBXCall.GetDtmfInput("", 0, 0, "1234567890#", 15, pDtmfDigit)
      If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
        'Something wrong. End this action
        TraceError "gseVoicemailEx7", "Disconnect on CallerID digits collecting (GetDtmfInput).", retVal
        gseVoicemailEx7 = gseStateDisconnected
        TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
        Exit Function
      End If
      If (pDtmfDigit = "#") Or (retVal = PBXTimeout) Then
        Exit Do
      Else
        szCallerID = szCallerID & pDtmfDigit
      End If
      If (Len(CStr(pDtmfDigit)) = 0) Then
        ' an error
        Exit Do
      End If
    Loop
  
    If (szCallerID <> "") Then
      TraceInfo "gseVoicemailEx7", "Collected CallerID is """ & szCallerID & """"
      PBXCall.CallingPartyNumber = szCallerID
    End If
  End If

  If Not PBXCall.IsOriginatorDisconnected Then 
    PBXCall.PhoneCallListEntry.State = PhoneCallStateCallDivertedToVoicemail 
  End If

  If (bAnnouncement = True) Then
    retVal = PBXCallGetDtmfInputEx(szAnnouncementSound, 0, 0, szDtmfMask, 0, pDtmfDigit)
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      retVal2 = gseRemoteInquiryEx5("Voicemail.True", szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
      gseVoicemailEx7 = retVal2
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If

    If Not ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
      'Something wrong. End this action
      TraceError "gseVoicemailEx7", "Disconnect on szAnnouncementSound.", retVal
      gseVoicemailEx7 = gseStateDisconnected
      TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
      Exit Function
    End If
  End If
  
  'Record messge
  retVal = PBXCallPlayMessageEx("Beep.wav")
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true
  If (retVal <> PBXSuccess) Then
    'Something wrong. End this action
    TraceError "gseVoicemailEx7", "Disconnect on Beep.wav.", retVal
    gseVoicemailEx7 = gseStateDisconnected
    TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7
    Exit Function
  End If

  retVal = PBXCall.RecordMessage(nRecordMessage)
  TraceInfo "gseVoicemailEx7", "RecordMessage result """ & ExtractReturnValue(retVal) & """"

  If (retVal = PBXTimeout) Then
    ' Voicemail recorded (Timeout)
    gseVoicemailEx7 = gseStateTimeout
  ElseIf (retVal = PBXFailure) Then
    ' Something wrong (woicemail is not recorded)
    gseVoicemailEx7 = gseStateDisconnected
  Else
    ' Voicemail recorded (Disconnect)
    gseVoicemailEx7 = gseStateRecorded
  End If

  'Send EMail
  retVal = gseSendEMailEx(szAddress, g_resStandardVoicemailSubject, g_resStandardVoicemailBody, True)

  TraceFunctionResult "gseVoicemailEx7", gseVoicemailEx7  
  
  If (bSaveTmpFileNameToVar = True) Then
    rVarToSaveTmpFileName = PBXCall.LastRecordedMessage
    PBXScript.OutputTrace "LastRecordedMessage = " & rVarToSaveTmpFileName
  End If
End Function


Function gseGetDTMFChar(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal nTimeout, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, ByVal fMask)
  Dim pDtmfDigit, retVal
  
  TraceFunction "gseGetDTMFChar", szSound & ", " & nRepetitions & ", " & nInterval & ", " & nTimeout & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (Len(szSound) = 0) Then
    szSound = "beep.wav"
    nRepetitions = 0
  End If


  pDtmfDigit = "x"
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true
  If (g_bUseInputVariable = False) Then
    retVal = PBXCallGetDtmfInputEx(szSound, Int(nRepetitions), Int(nInterval), fMask, Int(nTimeout), pDtmfDigit)
    TraceInfo "gseGetDTMFChar", "[retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
  Else           
    g_bUseInputVariable = False
    pDtmfDigit = szVariableName
    retVal = PBXSuccess
    TraceInfo "gseGetDTMFChar,use variable", "[retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
  End If
   
  If (retVal = PBXSuccess) Then
    Select Case pDtmfDigit
      Case "0"
        gseGetDTMFChar = gseStateKey0
      Case "1"
        gseGetDTMFChar = gseStateKey1
      Case "2"
        gseGetDTMFChar = gseStateKey2
      Case "3"
        gseGetDTMFChar = gseStateKey3
      Case "4"
        gseGetDTMFChar = gseStateKey4
      Case "5"
        gseGetDTMFChar = gseStateKey5
      Case "6"
        gseGetDTMFChar = gseStateKey6
      Case "7"
        gseGetDTMFChar = gseStateKey7
      Case "8"
        gseGetDTMFChar = gseStateKey8
      Case "9"
        gseGetDTMFChar = gseStateKey9
      Case "*"
        gseGetDTMFChar = gseStateKey10
      Case "#"
        gseGetDTMFChar = gseStateKey11
      Case Else
        gseGetDTMFChar = gseStateDisconnected
    End Select
    
    AdjustBoolean bStoreToVariable
    AdjustBoolean bResetVariableContent
  
    If (bStoreToVariable = True) Then
      ' Store character to a variable
      ' Reset variable cintent in case if this checmark is selected
      If (bResetVariableContent = True) Then
        szVariableName = ""
      End If
      szVariableName = szVariableName & pDtmfDigit
    End If
  ElseIf (retVal = PBXTimeout) Then
    ' Timeout
    gseGetDTMFChar = gseStateTimeout
  Else
    ' Call terminated (disconnected).
    gseGetDTMFChar = gseStateDisconnected
  End If
  TraceFunctionResult "gseGetDTMFChar", gseGetDTMFChar
End Function

' GSE >= 4.2.0.50
Function gseGetDTMFCharEx(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal nTimeout, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                          ByVal bPlayFromVariable, ByRef szVariableToPlay, ByVal fMask)
  ' Adjust nRepetitions - if "1" drop it to "0" to play sound once
  If (nRepetitions = 1) Then
    nRepetitions = 0
  End If
  
  gseGetDTMFCharEx = gseGetDTMFCharEx2(szSound, nRepetitions, nInterval, nTimeout, bStoreToVariable, szVariableName, bResetVariableContent, _
                          bPlayFromVariable, szVariableToPlay, fMask)
End Function

' GSE >= 6.0.2.119
Function gseGetDTMFCharEx2(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal nTimeout, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                          ByVal bPlayFromVariable, ByRef szVariableToPlay, ByVal fMask)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayFromVariable
  
  gseGetDTMFCharEx2 = gseGetDTMFCharEx3(szSound, nRepetitions, nInterval, nTimeout, bStoreToVariable, szVariableName, bResetVariableContent, _
                          bPlayFromVariable, szVariableToPlay, fMask)
End Function

' GSE >= 6.20.0.17
Function gseGetDTMFCharEx3(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal nTimeout, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                          ByVal bPlayFromVariable, ByRef szVariableToPlay, ByVal fMask)
  Dim pDtmfDigit, retVal, bVariableWasUsed, nLen
  
  TraceFunction "gseGetDTMFCharEx3", szSound & ", " & nRepetitions & ", " & nInterval & ", " & _
                 nTimeout & ", " & bStoreToVariable & ", " & szVariableName & ", " & _
                 bResetVariableContent & ", " & bPlayFromVariable & ", " & szVariableToPlay & ", " & fMask
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (Len(szSound) = 0) Then
    szSound = "beep.wav"
    nRepetitions = 0
  End If
  
  bVariableWasUsed = False

  pDtmfDigit = "x"
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true
  nLen = Len(szVariableToPlay)
  If (bPlayFromVariable = True And nLen > 0) Then
    g_bUseInputVariable = False

    ' use first character for input
    pDtmfDigit = Left(szVariableToPlay, 1)
    ' delete first left character
    szVariableToPlay = Right(szVariableToPlay, nLen - 1)

    retVal = PBXSuccess
    bVariableWasUsed = True
    TraceInfo "gseGetDTMFCharEx3, use variable", "[retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
  Else
    If (Len(szSound) = 0) Then
      szSound = "Announcements/1_second_silence.wav"
      nTimeout = 10
    End If
    retVal = PBXCallGetDtmfInputEx(szSound, Int(nRepetitions), Int(nInterval), fMask, Int(nTimeout), pDtmfDigit)
    TraceInfo "gseGetDTMFCharEx3", "[retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
  End If
   
  If (retVal = PBXSuccess) Then
    Select Case pDtmfDigit
      Case "0"
        gseGetDTMFCharEx3 = gseStateKey0
      Case "1"
        gseGetDTMFCharEx3 = gseStateKey1
      Case "2"
        gseGetDTMFCharEx3 = gseStateKey2
      Case "3"
        gseGetDTMFCharEx3 = gseStateKey3
      Case "4"
        gseGetDTMFCharEx3 = gseStateKey4
      Case "5"
        gseGetDTMFCharEx3 = gseStateKey5
      Case "6"
        gseGetDTMFCharEx3 = gseStateKey6
      Case "7"
        gseGetDTMFCharEx3 = gseStateKey7
      Case "8"
        gseGetDTMFCharEx3 = gseStateKey8
      Case "9"
        gseGetDTMFCharEx3 = gseStateKey9
      Case "*"
        gseGetDTMFCharEx3 = gseStateKey10
      Case "#"
        gseGetDTMFCharEx3 = gseStateKey11
      Case Else
        If (bVariableWasUsed) Then
          gseGetDTMFCharEx3 = gseStateTimeout
        Else
          gseGetDTMFCharEx3 = gseStateDisconnected
        End If
    End Select
    If (bStoreToVariable = True) Then
      ' Store character to a variable
      ' Reset variable cintent in case if this checmark is selected
      If (bResetVariableContent = True) Then
        szVariableName = ""
      End If
      szVariableName = szVariableName & pDtmfDigit
    End If
  ElseIf (retVal = PBXTimeout) Then
    ' Timeout
    gseGetDTMFCharEx3 = gseStateTimeout
  Else
    ' Call terminated (disconnected).
    gseGetDTMFCharEx3 = gseStateDisconnected
  End If
  TraceFunctionResult "gseGetDTMFCharEx3", gseGetDTMFCharEx3
End Function


Function gseCalls(ByVal bCondition)
  TraceFunction "gseCalls", bCondition
  If (bCondition = True) Then
    gseCalls = gseStateTrue
  Else
    gseCalls = gseStateFalse
  End If
  TraceFunctionResult "gseCalls", gseCalls
End Function


Function gseTimes(ByVal bCondition)
  TraceFunction "gseTimes", bCondition
  If (bCondition = True) Then
    gseTimes = gseStateTrue
  Else
    gseTimes = gseStateFalse
  End If
  TraceFunctionResult "gseTimes", gseTimes
End Function


Function gseDayOfWeek()
  gseDayOfWeek = gseDayOfWeekEx()

  ' Support new 4.31 output "Disconnected"
  If (gseDayOfWeek = gseStateDisconnected) Then
    Select Case WeekDay(PBXUser.Now, vbMonday)
      Case 1: gseDayOfWeek = gseStateMonday
      Case 2: gseDayOfWeek = gseStateTuesday
      Case 3: gseDayOfWeek = gseStateWednesday
      Case 4: gseDayOfWeek = gseStateThursday
      Case 5: gseDayOfWeek = gseStateFriday
      Case 6: gseDayOfWeek = gseStateSaturday
      Case 7: gseDayOfWeek = gseStateSunday
    End Select
    PBXScriptOutputTrace "gseStateDisconnected -> " & gseDayOfWeek
  End If
End Function

' GSE >= 4.3.1.79
Function gseDayOfWeekEx()
  TraceFunction "gseDayOfWeekEx", ""
  Select Case WeekDay(PBXUser.Now, vbMonday)
    Case 1: gseDayOfWeekEx = gseStateMonday
    Case 2: gseDayOfWeekEx = gseStateTuesday
    Case 3: gseDayOfWeekEx = gseStateWednesday
    Case 4: gseDayOfWeekEx = gseStateThursday
    Case 5: gseDayOfWeekEx = gseStateFriday
    Case 6: gseDayOfWeekEx = gseStateSaturday
    Case 7: gseDayOfWeekEx = gseStateSunday
  End Select

  CheckIfCallIsDisconnected gseDayOfWeekEx

  TraceFunctionResult "gseDayOfWeekEx", gseDayOfWeekEx
End Function

' support old version
Function gseConnectToLoop(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops)
  Dim retVal

  PBXScript.OutputTrace "old gseConnectToLoop is called..."
  retVal = gseConnectToLoopEx(szDialNumber, nTimeout, szSound, nNumberOfLoops)

  If (retVal = gseStateTimeout) Then
    retVal = gseStateNoAnswer
  End If

  gseConnectToLoop = retVal
End Function

Function gseConnectToLoopEx(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops)
  Dim retVal, nLoop, retDummy, retValLast
  
  TraceFunction "gseConnectToLoopEx", szDialNumber & ", " & nTimeout & ", " & szSound & ", " & nNumberOfLoops
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  retValLast = gseStateTimeout
  For nLoop = 1 To Int(nNumberOfLoops)
    retVal = ConnectToNumberOrMySelf(szDialNumber, nTimeout)
    If (retVal = PBXSuccess) Then
      'Its ok. Leave this function.
      gseConnectToLoopEx = gseStateConnected
      TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
      Exit Function
    ElseIf (retVal = PBXCallTermDestinationBusy) Then
      'Busy. Try again. (output BUSY)
      retValLast = gseStateNoAnswer
    ElseIf (retVal = PBXTimeout) Or (retVal = PBXCallTermWrongNumber) Or (retVal = PBXCallTermConnectToCallerImpossible)  Or (retVal = PBXCallTermDestinationUnreachable) Then
      'No response. Try again. (output TIMEOUT)
      retValLast = gseStateTimeout
    ElseIf (retVal = PBXCallTermReject) Then
      'Call rejected
      gseConnectToLoopEx = gseStateTimeout
      TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
      Exit Function
    ElseIf (retVal = PBXFailure) Then
      'Something wrong. End Action.
      gseConnectToLoopEx = gseStateDisconnected
      TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
      Exit Function
    Else
      'Call terminated. Leave this function.
      gseConnectToLoopEx = gseStateDisconnected
      TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
      Exit Function
    End If
    If (nLoop < Int(nNumberOfLoops)) Then
      ' Don't play after last ConnectTo
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      If (retVal = PBXCallTermDestinationBusy) Then
        'Play busy announcement
        retDummy = PBXCallPlayMessageEx("ConnectToLoopBusy.wav")
      End If
      retDummy = PBXCallPlayMessageEx(szSound)

      'Check disconnect
      If (retDummy = PBXCallTermNormalCallClearing) Then
        'Call terminated. Leave this function.
        gseConnectToLoopEx = gseStateDisconnected
        TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
        Exit Function
      End If
    End If
  Next
  gseConnectToLoopEx = retValLast
  TraceFunctionResult "gseConnectToLoopEx", gseConnectToLoopEx
End Function


' GSE 4.2.0.52
Function gseConnectToLoopEx2(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops, _
                             ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                             ByVal bPlayAlertSound, ByVal szAlertSound)
  Dim retVal
  
  TraceFunction "gseConnectToLoopEx2", szDialNumber & ", " & nTimeout & ", " & szSound & ", " & nNumberOfLoops & ", " & _
                      fMask  & ", " & bStoreToVariable & ", " & rVariableName & ", " & bResetVariableContent & ", " & _
                      bPlayAlertSound & ", " & szAlertSound
  
  retVal = gseConnectToLoopEx3(szDialNumber, nTimeout, szSound, nNumberOfLoops, fMask, bStoreToVariable, _
                               rVariableName, bResetVariableContent, bPlayAlertSound, szAlertSound, "")

  gseConnectToLoopEx2 = retVal
  TraceFunctionResult "gseConnectToLoopEx2", gseConnectToLoopEx2
End Function

'5.10
Function gseConnectToLoopEx3(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops, _
                             ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                             ByVal bPlayAlertSound, ByVal szAlertSound, ByVal szCallingPartyNumber)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayAlertSound
  gseConnectToLoopEx3 = gseConnectToLoopEx4(szDialNumber, nTimeout, szSound, nNumberOfLoops, _
                             fMask, bStoreToVariable, rVariableName, bResetVariableContent, _
                             bPlayAlertSound, szAlertSound, szCallingPartyNumber)
End Function

'6.20
Function gseConnectToLoopEx4(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops, _
                             ByVal fMask, ByVal bStoreToVariable, ByRef rVariableName, ByVal bResetVariableContent, _
                             ByVal bPlayAlertSound, ByVal szAlertSound, ByVal szCallingPartyNumber)
  Dim retVal, nLoop, retDummy, retValLast, rDtmfDigit, szOldCallingPartyNumber
  
  TraceFunction "gseConnectToLoopEx4", szDialNumber & ", " & nTimeout & ", " & szSound & ", " & nNumberOfLoops & ", " & _
                      fMask  & ", " & bStoreToVariable & ", " & rVariableName & ", " & bResetVariableContent & ", " & _
                      bPlayAlertSound & ", " & szAlertSound & ", " & szCallingPartyNumber
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  If (bResetVariableContent = True) Then
    rVariableName = ""
  End If

  szOldCallingPartyNumber = Empty
  ' check if user defined calling party should be used
  If (Len(szCallingPartyNumber) > 0) Then
    ' save current PBXCall calling party to restore it afterwards
    szOldCallingPartyNumber = PBXCall.CallingPartyNumber

    If szCallingPartyNumber = "*orgdst*" Then
        ' got magic word, now setting calling party number to original destination number
        PBXCall.CallingPartyNumber = PBXCall.CalledPartyNumber
    Else
        ' set new PBXCall calling party to perform ConnectTo
        PBXCall.CallingPartyNumber = szCallingPartyNumber
    End If
  End If

  retValLast = gseStateTimeout
  For nLoop = 1 To Int(nNumberOfLoops)
    PBXScript.OutputTrace "loop " & CStr(nLoop)
    retVal = ConnectToNumberOrMySelfEx3(szDialNumber, nTimeout, fMask, bStoreToVariable, rVariableName, _
                 bResetVariableContent, bPlayAlertSound, szAlertSound, False, True)
    PBXScript.OutputTrace "retVal = " & ExtractReturnValue(retVal) & ", Variable = " & rVariableName
    If (retVal = PBXSuccess) Then
      'Its ok. Leave this function.
      gseConnectToLoopEx4 = gseStateConnected
      ' restore calling party number if user defined was used
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
      Exit Function
    ElseIf (retVal = PBXCallTermDestinationBusy) Then
      'Busy. Try again. (output BUSY)
      retValLast = gseStateNoAnswer
    ElseIf (retVal = PBXCallTermOriginatorDisconnected) Or (retVal = PBXFailure) Then
      'Call terminated or internal failure. Leave this function.
      gseConnectToLoopEx4 = gseStateDisconnected
      ' restore calling party number if user defined was used
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
      Exit Function
    ElseIf (retVal = PBXCallTermCancelled) Then
      'DTMF key pressed
      gseConnectToLoopEx4 = gseStateDTMFKeyPressed
      ' restore calling party number if user defined was used
      If NOT IsEmpty(szOldCallingPartyNumber) Then
        PBXCall.CallingPartyNumber = szOldCallingPartyNumber
      End If
      TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
      Exit Function
    Else
      'Call rejected or No response. Try again. (output TIMEOUT)
      retValLast = gseStateTimeout
    End If
    If (nLoop < Int(nNumberOfLoops)) Then
      ' Don't play after last ConnectTo
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      ' /*bCallConnected = true*/ - don't set bCallConnected flag. If call was accetped, bCallConnected flag
      ' will be sed inside ConnectToNumberOrMySelfEx function
      If (retVal = PBXCallTermDestinationBusy) Then
        'Play busy announcement
        rDtmfDigit = ""
        retDummy = PBXCallGetDtmfInputEx("ConnectToLoopBusy.wav", 0, 0, fMask, 0, rDtmfDigit)
        If ((retDummy = PBXSuccess) And (Len(rDtmfDigit) > 0)) Then
          'DTMF key pressed
          rVariableName = rVariableName & rDtmfDigit
          gseConnectToLoopEx4 = gseStateDTMFKeyPressed
          ' restore calling party number if user defined was used
          If NOT IsEmpty(szOldCallingPartyNumber) Then
            PBXCall.CallingPartyNumber = szOldCallingPartyNumber
          End If
          TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
          Exit Function
        End If
      End If
      rDtmfDigit = ""
      retDummy = PBXCallGetDtmfInputEx(szSound, 0, 0, fMask, 0, rDtmfDigit)
      If ((retDummy = PBXSuccess) And (Len(rDtmfDigit) > 0)) Then
        'DTMF key pressed
        rVariableName = rVariableName & rDtmfDigit
        gseConnectToLoopEx4 = gseStateDTMFKeyPressed
        ' restore calling party number if user defined was used
        If NOT IsEmpty(szOldCallingPartyNumber) Then
          PBXCall.CallingPartyNumber = szOldCallingPartyNumber
        End If
        TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
        Exit Function
      End If

      'Check disconnect
      If (retDummy = PBXCallTermNormalCallClearing) Then
        'Call terminated. Leave this function.
        gseConnectToLoopEx4 = gseStateDisconnected
        ' restore calling party number if user defined was used
        If NOT IsEmpty(szOldCallingPartyNumber) Then
          PBXCall.CallingPartyNumber = szOldCallingPartyNumber
        End If
        TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
        Exit Function
      End If
    End If
  Next
  gseConnectToLoopEx4 = retValLast
  ' restore calling party number if user defined was used
  If NOT IsEmpty(szOldCallingPartyNumber) Then
    PBXCall.CallingPartyNumber = szOldCallingPartyNumber
  End If
  TraceFunctionResult "gseConnectToLoopEx4", gseConnectToLoopEx4
End Function

Function gseGetDTMFStringEx(ByRef szVarName, ByVal bResetVariableContent, ByVal szSound, ByVal bStopOnChar, ByVal bStopOnLength, ByVal szStopChar, ByVal nMaxLength, ByVal nTimeout)
  AdjustBoolean bResetVariableContent
  AdjustBoolean bStopOnChar
  AdjustBoolean bStopOnLength
  
  gseGetDTMFStringEx = gseGetDTMFStringEx2(szVarName, bResetVariableContent, szSound, bStopOnChar, bStopOnLength, szStopChar, nMaxLength, nTimeout)
End Function

Function gseGetDTMFStringEx2(ByRef szVarName, ByVal bResetVariableContent, ByVal szSound, ByVal bStopOnChar, ByVal bStopOnLength, ByVal szStopChar, ByVal nMaxLength, ByVal nTimeout)
  ' In case if at least one digit collected the return value is gseStateDTMFStringCollected (Stored in GSE)
  ' In case of disconnect the return value is gseStateDisconnected (Disconnected in GSE)
  ' In case of only termination character (szStopChar) is collected the return value is gseStateOnlyStopChar
  ' Otherwise the return value is gseStateTimeout (Nothing Entered in GSE)
  Dim pDtmfDigit, bCollected, retVal, bConditionStopOnChar, bConditionStopOnLength, nTimeoutFirstPlay, bOnlyStopCharRecieved
  
  nTimeoutFirstPlay = Int(nTimeout)

  If (Int(nTimeout) <= 0) Then
    nTimeout = 15
    nTimeoutFirstPlay = 0
  End If
  
  TraceFunction "gseGetDTMFStringEx2", szVarName & ", " & bResetVariableContent & ", " & szSound & ", " & bStopOnChar & ", " & bStopOnLength & ", " & szStopChar & ", " & nMaxLength & ", " & nTimeout

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  'Convert parameters
  nTimeout = Int(nTimeout)
  nMaxLength = Int(nMaxLength)
  pDtmfDigit = ""
  bCollected = False

  If (Len(szSound) = 0) Then
    szSound = "beep.wav"
  End If

  retVal = PBXCallGetDtmfInputEx(szSound, 0, 0, "1234567890*#", nTimeoutFirstPlay, pDtmfDigit)
  TraceInfo "gseGetDTMFStringEx2", "<-- GetDtmfInput() [retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
  If (retVal <> PBXSuccess) Then
    If (retVal = PBXTimeout) Then
      gseGetDTMFStringEx2 = gseStateTimeout
      TraceFunctionResult "gseGetDTMFStringEx2", gseGetDTMFStringEx2
      Exit Function
    Else
      ' Call terminated or timeout reached (disconnected).
      gseGetDTMFStringEx2 = gseStateDisconnected
      TraceFunctionResult "gseGetDTMFStringEx2", gseGetDTMFStringEx2
      Exit Function
    End If
  End If
  
  If (bResetVariableContent = True) Then
    szVarName = ""
  End If
  
  nMaxLength = CInt(nMaxLength) + Len(szVarName)

  bConditionStopOnChar = True
  bConditionStopOnLength = True
  bOnlyStopCharRecieved = False

  If (bStopOnChar = True) Then
    ' Stop input when the specified DTMF key will be pressed
    bConditionStopOnChar = (pDtmfDigit <> szStopChar)
    bOnlyStopCharRecieved = Not bConditionStopOnChar
  End If
  
  If (bConditionStopOnChar) Then
    szVarName = szVarName & pDtmfDigit
    bCollected = True
  End If

  If (bStopOnLength = True) Then
    ' Stop on specified length
    bConditionStopOnLength = (Len(szVarName) < Int(nMaxLength))
  End If

  Do While (bConditionStopOnChar And bConditionStopOnLength)
    pDtmfDigit = ""
    
    ' Read the dtmf char
    retVal = PBXCallGetDtmfInputEx("Announcements/1_second_silence.wav", 0, 0, "1234567890*#", nTimeout, pDtmfDigit) ' Bugfix: Play silence insted of music repetition
    TraceInfo "gseGetDTMFStringEx2", "<-- GetDtmfInput() [retVal = " & ExtractReturnValue(retVal) & "] [pDtmfDigit = " & pDtmfDigit & "]"
    
    If (retVal <> PBXSuccess) Then
      If (retVal = PBXTimeout) Then
        If (bCollected) Then
          gseGetDTMFStringEx2 = gseStateDTMFStringCollected
        Else
          gseGetDTMFStringEx2 = gseStateTimeout
        End If
        TraceFunctionResult "gseGetDTMFStringEx2", gseGetDTMFStringEx2
        Exit Function
      Else
        ' Call terminated or timeout reached (disconnected).
        gseGetDTMFStringEx2 = gseStateDisconnected
        TraceFunctionResult "gseGetDTMFStringEx2", gseGetDTMFStringEx2
        Exit Function
      End If
    ElseIf (retVal = PBXSuccess) And (Len(CStr(pDtmfDigit)) = 0) Then
      ' PBXSuccess and no digit --> looks like sound file does not exists, terminate the function
      bCollected = False
      Exit Do
    End If

    If (bStopOnChar = True) Then
      ' Stop input when the specified DTMF key will be pressed
      bConditionStopOnChar = (pDtmfDigit <> szStopChar)
    End If

    If (bConditionStopOnChar) Then
      szVarName = szVarName & pDtmfDigit
      bCollected = True
    End If

    If (bStopOnLength = True) Then
      ' Stop on specified length
      bConditionStopOnLength = (Len(szVarName) < Int(nMaxLength))
    End If
  Loop
  
  TraceInfo "gseGetDTMFStringEx2", "Collected Digits: [" & szVarName & "]"

  If (bCollected) Then
      gseGetDTMFStringEx2 = gseStateDTMFStringCollected
  Else
    If (bOnlyStopCharRecieved) Then
      gseGetDTMFStringEx2 = gseStateOnlyStopChar
    Else
      gseGetDTMFStringEx2 = gseStateTimeout
    End If
  End If
  TraceFunctionResult "gseGetDTMFStringEx2", gseGetDTMFStringEx2
End Function

Function gseGetDTMFString(ByRef szVarName, ByVal bResetVariableContent, ByVal szSound, ByVal bStopOnChar, ByVal bStopOnLength, ByVal szStopChar, ByVal nMaxLength, ByVal nTimeout)
    Dim retVal
    retVal = gseGetDTMFStringEx(szVarName, bResetVariableContent, szSound, bStopOnChar, bStopOnLength, szStopChar, nMaxLength, nTimeout)
    If retVal = gseStateOnlyStopChar Then
        ' support old script
        retVal = gseStateTimeout
    End If
    gseGetDTMFString = retVal
End Function

' obsolete
Function gseEvaluate(ByVal szName, ByVal szOperation, ByVal szValue)
  TraceFunction "gseEvaluate", szName & ", " & szOperation & ", " & szValue
  Select Case szOperation
    Case "="
      If (CStr(szName) = CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateMatch
      Else
        gseEvaluate = gseStateEvaluateNoMatch
      End If
    Case "<>"
      If (CStr(szName) = CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateNoMatch
      Else
        gseEvaluate = gseStateEvaluateMatch
      End If
    Case ">"
      If (CStr(szName) > CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateMatch
      Else
        gseEvaluate = gseStateEvaluateNoMatch
      End If
    Case "<"
      If (CStr(szName) < CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateMatch
      Else
        gseEvaluate = gseStateEvaluateNoMatch
      End If
    Case ">="
      If (CStr(szName) >= CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateMatch
      Else
        gseEvaluate = gseStateEvaluateNoMatch
      End If
    Case "<="
      If (CStr(szName) <= CStr(szValue)) Then
        gseEvaluate = gseStateEvaluateMatch
      Else
        gseEvaluate = gseStateEvaluateNoMatch
      End If
    Case Else
      'In case if condition is invalid
      gseEvaluate = gseStateEvaluateNoMatch
  End Select
  TraceFunctionResult "gseEvaluate", gseEvaluate
End Function

Function gseEvaluateEx(ByVal bCondition)
  TraceFunction "gseEvaluateEx", CStr(bCondition)
  If bCondition Then
    gseEvaluateEx = gseStateEvaluateMatch
  Else
    gseEvaluateEx = gseStateEvaluateNoMatch
  End If
  TraceFunctionResult "gseEvaluateEx", gseEvaluateEx
End Function

Function gseSayNumber(ByVal szDigitString, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  gseSayNumber = gseSayNumberEx(szDigitString, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
End Function

Function gseSayNumberEx(ByVal szDigitString, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  Dim szDigit, nLen, rc, szSoundName, retVal
  
  TraceFunction "gseSayNumberEx", szDigitString & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  gseSayNumberEx = gseStatePlayed
  Do While (Len(szDigitString) > 0)
    nLen = Len(szDigitString)
    szDigit = Left(szDigitString, 1)
    szDigitString = Right(szDigitString, nLen - 1)
    ' Choose wav file
    szSoundName = ""
    Select Case szDigit
      Case "1" szSoundName = "one.wav"
      Case "2" szSoundName = "two.wav"
      Case "3" szSoundName = "three.wav"
      Case "4" szSoundName = "four.wav"
      Case "5" szSoundName = "five.wav"
      Case "6" szSoundName = "six.wav"
      Case "7" szSoundName = "seven.wav"
      Case "8" szSoundName = "eight.wav"
      Case "9" szSoundName = "nine.wav"
      Case "0" szSoundName = "zero.wav"
      Case "*" szSoundName = "asterisk.wav"
      Case "#" szSoundName = "pound.wav"
    End Select
    ' Play sound
    If (Len(szSoundName) > 0) Then
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
      rc = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
      gseSayNumberEx = rc
      ' Check returned state
      If (rc = gseStateDisconnected) Then
        ' Call disconnected. Return immediatly.
        TraceFunctionResult "gseSayNumberEx", gseSayNumberEx
        Exit Function
      End If
      If (rc = gseStateDTMFKeyPressed) Then
        ' Dtmf key pressed. Return immediatly.
        TraceFunctionResult "gseSayNumberEx", gseSayNumberEx
        Exit Function
      End If
    End If
  Loop
  TraceFunctionResult "gseSayNumberEx", gseSayNumberEx
End Function

' obsolete
Function gsePlayMultipleSounds(ByVal szPrevState, _
                               ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                               ByVal szName, ByVal szOperation, ByVal szValue, ByVal szSound)
  TraceFunction "gsePlayMultipleSounds", szPrevState & ", " & _
                               fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent & ", " & _
                               szName & ", " & szOperation & ", " & szValue & ", " & szSound

  ' Check the previouse state
  If (szPrevState = gseStateNoPlayed) Then
    ' Check the condition first
    If (gseEvaluate(szName, szOperation, szValue) = gseStateEvaluateMatch) Then
      ' Play specified sound
      gsePlayMultipleSounds = gsePlaySound(szSound, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    Else
      ' The condition is not match
      gsePlayMultipleSounds = gseStateNoPlayed
    End If
  Else
    ' Sound already played. Skip this function, return previos state.
    gsePlayMultipleSounds = szPrevState
  End If
End Function

Function gsePlayMultipleSoundsEx(ByVal szPrevState, _
                               ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                               ByVal bCondition, ByVal szSound)
  TraceFunction "gsePlayMultipleSoundsEx", szPrevState & ", " & _
                               fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent & ", " & _
                               bCondition & ", " & szSound

  Dim retVal
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  ' Check the previouse state
  If (szPrevState = gseStateNoPlayed) Then
    ' Check the condition first
    If (gseEvaluateEx(bCondition) = gseStateEvaluateMatch) Then
      ' Play specified sound
      gsePlayMultipleSoundsEx = gsePlaySound(szSound, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    Else
      ' The condition is not match
      gsePlayMultipleSoundsEx = gseStateNoPlayed
    End If
  Else
    ' Sound already played. Skip this function, return previos state.
    gsePlayMultipleSoundsEx = szPrevState
  End If
  TraceFunctionResult "gsePlayMultipleSoundsEx", gsePlayMultipleSoundsEx
End Function

' GSE 4.2.0.51
Function gsePlayMultipleSoundsEx2(ByVal szPrevState, _
                               ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                               ByVal bPlayControl, _
                               ByVal bCondition, ByVal szSound, _
                               ByVal bSkipBegining, ByVal nSkipSeconds)
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayControl
  AdjustBoolean bSkipBegining  
  gsePlayMultipleSoundsEx2 = gsePlayMultipleSoundsEx3(szPrevState, _
                               fMask, bStoreToVariable, szVariableName, bResetVariableContent, _
                               bPlayControl, _
                               bCondition, szSound, _
                               bSkipBegining, nSkipSeconds)
End Function

'6.20
Function gsePlayMultipleSoundsEx3(ByVal szPrevState, _
                               ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, _
                               ByVal bPlayControl, _
                               ByVal bCondition, ByVal szSound, _
                               ByVal bSkipBegining, ByVal nSkipSeconds)
  TraceFunction "gsePlayMultipleSoundsEx3", szPrevState & ", " & _
                               fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent & ", " & _
                               bPlayControl & ", " & _
                               bCondition & ", " & szSound & ", " & bSkipBegining & ", " & nSkipSeconds

  Dim retVal
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  ' Check the previouse state
  If (szPrevState = gseStateNoPlayed) Then
    ' Check the condition first
    If (gseEvaluateEx(bCondition) = gseStateEvaluateMatch) Then
      ' Play specified sound
      gsePlayMultipleSoundsEx3 = gsePlaySoundEx2(szSound, fMask, bStoreToVariable, szVariableName, bResetVariableContent, _
                                                bSkipBegining, nSkipSeconds, bPlayControl)
    Else
      ' The condition is not match
      gsePlayMultipleSoundsEx3 = gseStateNoPlayed
    End If
  Else
    ' Sound already played. Skip this function, return previos state.
    gsePlayMultipleSoundsEx3 = szPrevState
  End If
  TraceFunctionResult "gsePlayMultipleSoundsEx3", gsePlayMultipleSoundsEx3
End Function


Sub PostProcessing()
  Dim strAddr
  PBXScript.OutputTrace "--> PostProcessing()"
  If (Not bCallConnected) Then
    PBXScript.OutputTrace "PostProcessing Started..."
    strAddr = Trim(PBXUser.VoicemailEMailAddress)
    If strAddr = "" Then
      PBXScript.OutputTrace "E-mail address is not set, terminating the call..."
	    Terminate (PBXCallTermDestinationBusy - 3)
	  Else
	    StandardVoicemail
	End If
  Else
    PBXScript.OutputTrace "PostProcessing Skipped..."
  End If
  PBXScript.OutputTrace "<-- PostProcessing()"
End Sub

Sub PostProcessingEx()
  Dim retDummy
  Dim strAddr

  Dim rInParams
  Set rInParams = new GSEParamList
  rInParams.Count = 0
  
  PBXScript.OutputTrace "--> PostProcessingEx()"
  ' try user-defined post processing first
  If (rulePostProcessing(rInParams) = False) Then
    If (Not bCallConnected) Then
      If (PBXUser.IsConferenceUser = True) Then
        ' Check for conference
        retDummy = PBXCall.PlayMessage("ConferenceMgr/ConfMgrNotAvailable.wav")
      Else
        PBXScript.OutputTrace "PostProcessing Started..."
    strAddr = Trim(PBXUser.VoicemailEMailAddress)
		If strAddr = "" Then
			PBXScript.OutputTrace "E-mail address is not set, terminating the call..."
			Terminate (PBXCallTermDestinationBusy - 3)
		Else
			StandardVoicemailEx
		End If
      End If
    Else
      PBXScript.OutputTrace "PostProcessing Skipped..."
    End If
  Else
    ' PostProcessing handled by rulePostProcessing.vbs
  End If
  PBXScript.OutputTrace "<-- PostProcessingEx()"
End Sub

Sub PostProcessingEx2(ByVal bSkipNextRules)
  Dim retDummy
  Dim retValRPP, strAddr

  Dim rInParams
  Set rInParams = new GSEParamList
  rInParams.Count = 0
  PBXScript.OutputTrace "--> PostProcessingEx2()"
  PBXScript.OutputTrace "PostProcessingEx2, bSkipNextRules = " & bSkipNextRules

  ' try user-defined post processing first
  retValRPP = rulePostProcessing(rInParams)
  If (retValRPP = False) Then
    If (bSkipNextRules = False) Then
      If (Not bCallConnected) and (Not g_bCallAlerted) Then
        If (PBXUser.IsConferenceUser = True) Then
          ' Check for conference
          retDummy = PBXCall.PlayMessage("ConferenceMgr/ConfMgrNotAvailable.wav")
        Else
          PBXScript.OutputTrace "PostProcessing Started..."
          strAddr = Trim(PBXUser.VoicemailEMailAddress)
		  If strAddr = "" Then
            PBXScript.OutputTrace "E-mail address is not set, terminating the call..."
			Terminate (PBXCallTermDestinationBusy - 3)
		  Else
			StandardVoicemailEx
		  End If
        End If
      Else
        PBXScript.OutputTrace "PostProcessing Skipped..."
      End If
    Else ' bSkipNextRules = True
      If (Not bCallConnected) Then 
        PBXScript.OutputTrace "return busy tone"
        PBXCall.Disconnect(PBXCallTermDestinationBusy)
      End If
    End If
  Else
    ' PostProcessing handled by rulePostProcessing.vbs
  End If
  PBXScript.OutputTrace "<-- PostProcessingEx2()"
End Sub


Function PreProcessing()
  Dim rInParams
  Set rInParams = new GSEParamList
  rInParams.Count = 0

  PBXScript.OutputTrace "rule PreProcessing started..."

  PreProcessing = rulePreProcessing(rInParams)

End Function


'***** Conditions *****

Function AllSituations()
  TraceFunction "AllSituations", ""
  AllSituations = True
  TraceFunctionResult "AllSituations", AllSituations
End Function

Function IsLoggedIn()
  TraceFunction "IsLoggedIn", ""
  If ((PBXUser.IsLoggedIn <> 0) And (PBXUser.IsBusy = 0)) Then
    IsLoggedIn = True
  Else
    IsLoggedIn = False
  End If
  TraceFunctionResult "IsLoggedIn", IsLoggedIn
End Function

Function IsBusy()
  TraceFunction "IsBusy", ""
  If (PBXUser.IsBusy <> 0) Then
    IsBusy = True
  Else
    IsBusy = False
  End If
  TraceFunctionResult "IsBusy", IsBusy
End Function

Function IsOutOfOffice()
  TraceFunction "IsOutOfOffice", ""
  If (PBXUser.IsOutOfOffice <> 0) Then
    IsOutOfOffice = True
  Else
    IsOutOfOffice = False
  End If
  TraceFunctionResult "IsOutOfOffice", IsOutOfOffice
End Function

Function IsOutlookBusy()
  TraceFunction "IsOutlookBusy", ""
  If (PBXUser.IsOutlookBusy <> 0) Then
    IsOutlookBusy = True
  Else
    IsOutlookBusy = False
  End If
  TraceFunctionResult "IsOutlookBusy", IsOutlookBusy
End Function

Function NotLoggedIn()
  TraceFunction "NotLoggedIn", ""
  If (PBXUser.IsLoggedIn = 0) Then
    NotLoggedIn = True
  Else
    NotLoggedIn = False
  End If
  TraceFunctionResult "NotLoggedIn", NotLoggedIn
End Function

Function OnEveryCall()
  TraceFunction "OnEveryCall", ""
  OnEveryCall = True
  TraceFunctionResult "OnEveryCall", OnEveryCall
End Function

Function CallsWithCallerID(ByVal szCallingNum)
  TraceFunction "CallsWithCallerID", CStr(szCallingNum)
  CallsWithCallerID = PBXScript.CompareNumbers(szCallingNum, CallerID())
  TraceFunctionResult "CallsWithCallerID", CallsWithCallerID
End Function

Function CallsWithoutCallerID()
  TraceFunction "CallsWithoutCallerID", ""
  If (Len(PBXCall.CallingPartyNumber) > 0) Then
    CallsWithoutCallerID = False
  Else
    CallsWithoutCallerID = True
  End If
  TraceFunctionResult "CallsWithoutCallerID", CallsWithoutCallerID
End Function

Function InternalCall()
  TraceFunction "InternalCall", ""
  If (PBXCall.IsInternal <> 0) Then
    InternalCall = True
  Else
    InternalCall = False
  End If
  TraceFunctionResult "InternalCall", InternalCall
End Function

Function ExternalCall()
  TraceFunction "ExternalCall", ""
  If (PBXCall.IsInternal = 0) Then
    ExternalCall = True
  Else
    ExternalCall = False
  End If
  TraceFunctionResult "ExternalCall", ExternalCall
End Function

Function CallsToTheBranch(ByVal szCalledNum)
  TraceFunction "CallsToTheBranch", CStr(szCalledNum)
  CallsToTheBranch = PBXSCript.CompareNumbers(szCalledNum, PBXCall.CalledPartyNumber)
  TraceFunctionResult "CallsToTheBranch", CallsToTheBranch
End Function

Function CallsToAllNumbers()
  TraceFunction "CallsToAllNumbers", ""
  CallsToAllNumbers = True
  TraceFunctionResult "CallsToAllNumbers", CallsToAllNumbers
End Function

Function AnyTime()
  TraceFunction "AnyTime", ""
  AnyTime = True
  TraceFunctionResult "AnyTime", AnyTime
End Function

Function OnWeekends()
  TraceFunction "OnWeekends", ""
  Dim CurrentDayOfWeek
  CurrentDayOfWeek = ""
  Select Case WeekDay(PBXUser.Now, vbMonday)
    Case 1: CurrentDayOfWeek = "Monday"
    Case 2: CurrentDayOfWeek = "Tuesday"
    Case 3: CurrentDayOfWeek = "Wednesday"
    Case 4: CurrentDayOfWeek = "Thursday"
    Case 5: CurrentDayOfWeek = "Friday"
    Case 6: CurrentDayOfWeek = "Saturday"
    Case 7: CurrentDayOfWeek = "Sunday"
  End Select
  OnWeekends = ((CurrentDayOfWeek = "Saturday") Or (CurrentDayOfWeek = "Sunday"))
  TraceFunctionResult "OnWeekends", OnWeekends
End Function

Function DuringTheWeek()
  TraceFunction "DuringTheWeek", ""
  Dim CurrentDayOfWeek
  CurrentDayOfWeek = ""
  Select Case WeekDay(PBXUser.Now, vbMonday)
    Case 1: CurrentDayOfWeek = "Monday"
    Case 2: CurrentDayOfWeek = "Tuesday"
    Case 3: CurrentDayOfWeek = "Wednesday"
    Case 4: CurrentDayOfWeek = "Thursday"
    Case 5: CurrentDayOfWeek = "Friday"
    Case 6: CurrentDayOfWeek = "Saturday"
    Case 7: CurrentDayOfWeek = "Sunday"
  End Select
  DuringTheWeek = Not ((CurrentDayOfWeek = "Saturday") Or (CurrentDayOfWeek = "Sunday"))
  TraceFunctionResult "DuringTheWeek", DuringTheWeek
End Function

Function DayOfWeek(ByVal szDays)
  TraceFunction "DayOfWeek", CStr(szDays)
  Dim CurrentDayOfWeek
  CurrentDayOfWeek = ""
  Select Case WeekDay(PBXUser.Now, vbMonday)
    Case 1: CurrentDayOfWeek = "Monday"
    Case 2: CurrentDayOfWeek = "Tuesday"
    Case 3: CurrentDayOfWeek = "Wednesday"
    Case 4: CurrentDayOfWeek = "Thursday"
    Case 5: CurrentDayOfWeek = "Friday"
    Case 6: CurrentDayOfWeek = "Saturday"
    Case 7: CurrentDayOfWeek = "Sunday"
  End Select
  DayOfWeek = (InStr(szDays, CurrentDayOfWeek)) > 0
  TraceFunctionResult "DayOfWeek", DayOfWeek
End Function

Function WithinTheTimeOf(ByVal szBeginDate, ByVal szBeginTime, ByVal szEndDate, ByVal szEndTime, ByVal bIgnoreDate, ByVal bIgnoreTime)
  AdjustBoolean bIgnoreDate
  AdjustBoolean bIgnoreTime
  WithinTheTimeOf = WithinTheTimeOfEx(szBeginDate, szBeginTime, szEndDate, szEndTime, bIgnoreDate, bIgnoreTime)
End Function
 
' 6.20
Function WithinTheTimeOfEx(ByVal szBeginDate, ByVal szBeginTime, ByVal szEndDate, ByVal szEndTime, ByVal bIgnoreDate, ByVal bIgnoreTime)
  TraceFunction "WithinTheTimeOfEx", CStr(szBeginDate) & ", " & CStr(szBeginTime) & ", " & CStr(szEndDate) & ", " & CStr(szEndTime) & ", " & CStr(bIgnoreDate) & ", " & CStr(bIgnoreTime)
  Dim CurrentDate, CurrentTime, BeginDate, EndDate, BeginTime, EndTime, bBegin, bEnd

  CurrentDate = DateValue(PBXUser.Now)
  CurrentTime = TimeValue(PBXUser.Now)
  BeginDate = CDate(szBeginDate)
  EndDate   = CDate(szEndDate)
  BeginTime = TimeValue(szBeginTime)
  EndTime   = TimeValue(szEndTime)
  
  If ((bIgnoreDate = True) And (bIgnoreTime = False)) Then
    'Ignore date
    ' check if time overlap midnight
    If (BeginTime > EndTime) Then
      bBegin = (CurrentTime >= BeginTime) Or (CurrentTime <= EndTime)
      bEnd = True
    Else
      bBegin = (CurrentTime >= BeginTime)
      bEnd = (CurrentTime <= EndTime)
    End If
  ElseIf ((bIgnoreDate = False) And (bIgnoreTime = True)) Then
    'Ignore time
    bBegin = (CurrentDate >= BeginDate)
    bEnd = (CurrentDate <= EndDate)
  ElseIf ((bIgnoreDate = False) And (bIgnoreTime = False)) Then
    'Check both date and time
    bBegin = ((CurrentDate > BeginDate) Or ((CurrentDate = BeginDate) And (CurrentTime >= BeginTime)))
    bEnd = ((CurrentDate < EndDate) Or ((CurrentDate = EndDate) And (CurrentTime <= EndTime)))
  Else
    'At any time
    bBegin = True
    bEnd = True
  End If
  
  WithinTheTimeOfEx = bBegin And bEnd
  TraceFunctionResult "WithinTheTimeOfEx", WithinTheTimeOfEx
End Function

Function OutsideTheTimeOf(ByVal szBeginDate, ByVal szBeginTime, ByVal szEndDate, ByVal szEndTime, ByVal bIgnoreDate, ByVal bIgnoreTime)
  AdjustBoolean bIgnoreDate
  AdjustBoolean bIgnoreTime
  OutsideTheTimeOf = OutsideTheTimeOfEx(szBeginDate, szBeginTime, szEndDate, szEndTime, bIgnoreDate, bIgnoreTime)
End Function

'6.20
Function OutsideTheTimeOfEx(ByVal szBeginDate, ByVal szBeginTime, ByVal szEndDate, ByVal szEndTime, ByVal bIgnoreDate, ByVal bIgnoreTime)
  TraceFunction "OutsideTheTimeOfEx", CStr(szBeginDate) & ", " & CStr(szBeginTime) & ", " & CStr(szEndDate) & ", " & CStr(szEndTime) & ", " & CStr(bIgnoreDate) & ", " & CStr(bIgnoreTime)
  Dim CurrentDate, CurrentTime, BeginDate, EndDate, BeginTime, EndTime, bBegin, bEnd

  CurrentDate = DateValue(PBXUser.Now)
  CurrentTime = TimeValue(PBXUser.Now)
  BeginDate = CDate(szBeginDate)
  EndDate   = CDate(szEndDate)
  BeginTime = TimeValue(szBeginTime)
  EndTime   = TimeValue(szEndTime)
  
  If ((bIgnoreDate = True) And (bIgnoreTime = False)) Then
    'Ignore date
    ' check if time overlap midnight
    If (BeginTime > EndTime) Then
      bBegin = (CurrentTime >= BeginTime) Or (CurrentTime <= EndTime)
      bEnd = True
    Else
      bBegin = (CurrentTime >= BeginTime)
      bEnd = (CurrentTime <= EndTime)
    End If
  ElseIf ((bIgnoreDate = False) And (bIgnoreTime = True)) Then
    'Ignore time
    bBegin = (CurrentDate >= BeginDate)
    bEnd = (CurrentDate <= EndDate)
  ElseIf ((bIgnoreDate = False) And (bIgnoreTime = False)) Then
    'Chack both date and time
    bBegin = ((CurrentDate > BeginDate) Or ((CurrentDate = BeginDate) And (CurrentTime >= BeginTime)))
    bEnd = ((CurrentDate < EndDate) Or ((CurrentDate = EndDate) And (CurrentTime <= EndTime)))
  Else
    'At any time
    bBegin = True
    bEnd = True
  End If
  
  OutsideTheTimeOfEx = Not (bBegin And bEnd)
  TraceFunctionResult "OutsideTheTimeOfEx", OutsideTheTimeOfEx
End Function

Function ExceptDayOfWeek(ByVal szDays)
  TraceFunction "ExceptDayOfWeek", CStr(szDays)
  Dim CurrentDayOfWeek

  CurrentDayOfWeek = ""
  Select Case WeekDay(DateValue(PBXUser.Now), vbMonday)
    Case 1: CurrentDayOfWeek = "Monday"
    Case 2: CurrentDayOfWeek = "Tuesday"
    Case 3: CurrentDayOfWeek = "Wednesday"
    Case 4: CurrentDayOfWeek = "Thursday"
    Case 5: CurrentDayOfWeek = "Friday"
    Case 6: CurrentDayOfWeek = "Saturday"
    Case 7: CurrentDayOfWeek = "Sunday"
  End Select
  ExceptDayOfWeek = (InStr(szDays, CurrentDayOfWeek)) > 0
  TraceFunctionResult "ExceptDayOfWeek", ExceptDayOfWeek
End Function

Function ExceptCallsToTheBranch(ByVal szCalledNum)
  TraceFunction "ExceptCallsToTheBranch", CStr(szCalledNum)
  ExceptCallsToTheBranch = PBXScript.CompareNumbers(szCalledNum, PBXCall.CalledPartyNumber)
  TraceFunctionResult "ExceptCallsToTheBranch", ExceptCallsToTheBranch
End Function

Function ExceptCallsWithCallerID(ByVal szCallingNum)
  TraceFunction "ExceptCallsWithCallerID", CStr(szCallingNum)
  ExceptCallsWithCallerID = PBXScript.CompareNumbers(szCallingNum, CallerID())
  TraceFunctionResult "ExceptCallsWithCallerID", ExceptCallsWithCallerID
End Function

Function ExceptWeekends()
  TraceFunction "ExceptWeekends", ""
  Dim CurrentDayOfWeek

  CurrentDayOfWeek = ""
  Select Case WeekDay(DateValue(PBXUser.Now), vbMonday)
    Case 1: CurrentDayOfWeek = "Monday"
    Case 2: CurrentDayOfWeek = "Tuesday"
    Case 3: CurrentDayOfWeek = "Wednesday"
    Case 4: CurrentDayOfWeek = "Thursday"
    Case 5: CurrentDayOfWeek = "Friday"
    Case 6: CurrentDayOfWeek = "Saturday"
    Case 7: CurrentDayOfWeek = "Sunday"
  End Select
  ExceptWeekends = ((CurrentDayOfWeek = "Saturday") Or (CurrentDayOfWeek = "Sunday"))
  TraceFunctionResult "ExceptWeekends", ExceptWeekends
End Function

'***** Actions *****

Sub Terminate(ByVal nCause)
  TraceFunction "Terminate", CStr(nCause)  
  Dim retVal

  'nCause + 3 -> Termination reasons are shifted 
  retVal = PBXCall.Disconnect(CStr(Int(nCause)+3))
  
  'We don't need to check return value
  TraceSubResult "Terminate"
End Sub

Sub ConnectTo(ByVal szDialNumber, ByVal nTimeout)
  TraceFunction "ConnectTo", CStr(szDialNumber) & ", " & CStr(nTimeout)
  Dim retVal

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  retVal = ConnectToNumberOrMySelf(szDialNumber, nTimeout)
  'We don't need to check return value
  TraceSubResult "ConnectTo"
End Sub


' Required for CRM 4.2.0.64
Sub ConnectToEx(ByVal szDialNumber, ByVal nTimeout, ByVal bProceedWithDestinationScript)
  ConnectToEx2 szDialNumber, nTimeout, bProceedWithDestinationScript, True
End Sub

' Required for CRM 6.12.0.14
Sub ConnectToEx2(ByVal szDialNumber, ByVal nTimeout, ByVal bProceedWithDestinationScript, ByVal bIncludeMobileDevices)
  AdjustBoolean bProceedWithDestinationScript
  AdjustBoolean bIncludeMobileDevices
  ConnectToEx3 szDialNumber, nTimeout, bProceedWithDestinationScript, bIncludeMobileDevices
End Sub

Sub ConnectToEx3(ByVal szDialNumber, ByVal nTimeout, ByVal bProceedWithDestinationScript, ByVal bIncludeMobileDevices)
  TraceFunction "ConnectToEx3", CStr(szDialNumber) & ", " & CStr(nTimeout) & ", " & CStr(bProceedWithDestinationScript) & ", " & CStr(bIncludeMobileDevices)
  Dim retVal

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  Dim rDummy
  rDummy = ""

  retVal = ConnectToNumberOrMySelfEx3(szDialNumber, nTimeout, "", False, rDummy, _
             False, False, "", bProceedWithDestinationScript, bIncludeMobileDevices)
  PBXScript.OutputTrace "retVal = " & retVal & " [" & ExtractReturnValue(retVal) & "]"

  'We don't need to check return value
  TraceSubResult "ConnectToEx3"
End Sub


Sub ConnectToDTMF()
  TraceFunction "ConnectToDTMF", ""
  Dim retVal, szDialNumber, pDtmfDigit, pDummy, pDummyV

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  'Get CallerID; "#" - end input
  szDialNumber = ""
  
  Do While True
    pDtmfDigit = "x"
    retVal = PBXCall.GetDtmfInput("", 0, 0, "1234567890#", 10, pDtmfDigit)
    If (retVal = PBXSuccess) And (pDtmfDigit <> "#") Then
      szDialNumber = szDialNumber & pDtmfDigit
    Else
      Exit Do
    End If
  Loop
  
  PBXScript.OutputTrace "ConnectToDTMF, szDialNumber = [" & szDialNumber & "]"

  If (Len(szDialNumber) > 0) Then
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    retVal = PBXCallConnectToWrapper(szDialNumber, 15, false, "", "", pDummy, true, 15, true, "", "", pDummyV, true, true)
    ' Bugfix for connect to caller impossible
    If (retVal = PBXCallTermConnectToCallerImpossible) Then
      PBXScript.OutputTrace "ConnectTo returns PBXCallTermConnectToCallerImpossible, try ConnectTo(PBXCall.CalledPartyNumber)"
      If (Not bCallConnected) Then
        ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
        PBXCall.CallProceeding
      End If
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, 15, false, "", "", pDummy, true, 15, true, "", "", pDummyV, true, true)
    End If
  End If
  TraceSubResult "ConnectToDTMF"
End Sub

Sub ConnectToLoop(ByVal szDialNumber, ByVal nTimeout, ByVal szSound, ByVal nNumberOfLoops)
  TraceFunction "ConnectToLoop", CStr(szDialNumber) & ", " & CStr(nTimeout) & ", " & CStr(szSound) & ", " & CStr(nNumberOfLoops)
  Dim nLoop, retVal, retDummy

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  For nLoop = 1 To Int(nNumberOfLoops)
    PBXScript.OutputTrace "loop " & CStr(nLoop)
    retVal = ConnectToNumberOrMySelf(szDialNumber, nTimeout)
    PBXScript.OutputTrace "retVal = " & retVal & " [" & ExtractReturnValue(retVal) & "]"
    If (retVal = PBXSuccess) Then
      'Its ok. Leave this function.
      Exit For
    ElseIf (retVal = PBXTimeout) Or (retVal = PBXCallTermDestinationBusy) Then
      'No response. Try again.
    ElseIf (retVal = PBXCallTermReject) Then
      'Call rejected
      TraceSubResult "ConnectToLoop"
      Exit Sub
    ElseIf (retVal = PBXFailure) Then
      'Something wrong. End Action.
      TraceSubResult "ConnectToLoop"
      Exit Sub
    Else
      'Call terminated. Leave this function.
      TraceSubResult "ConnectToLoop"
      Exit Sub
    End If
    If (nLoop < Int(nNumberOfLoops)) Then
      ' Don't play after last ConnectTo
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      ' /*bCallConnected = true*/ - don't set bCallConnected flag. If call was accetped, bCallConnected flag
      ' will be sed inside ConnectToNumberOrMySelf function
      If (retVal = PBXCallTermDestinationBusy) Then
        'Play busy announcement
        PBXScript.OutputTrace "playing ""ConnectToLoopBusy.wav""..."
        retDummy = PBXCall.PlayMessage("ConnectToLoopBusy.wav")
        If (retDummy = PBXSuccess) Then
          bCallConnected = true
        End If
      End If
      If (Len(szSound) > 0) Then
        PBXScript.OutputTrace "playing """ & szSound & """..."

        If szSound="*hold*" Then
          retDummy = PBXCall.PlayMessage("")
        Else
          retDummy = PBXCall.PlayMessage(szSound)
        End If

        If (retDummy = PBXSuccess) Then
          bCallConnected = true
        End If
      Else
        PBXScript.OutputTrace "sound skipped..."
      End If
    End If
  Next
  TraceSubResult "ConnectToLoop"
End Sub

Sub PlaySound(ByVal szSound)
  TraceFunction "PlaySound", CStr(szSound)
  Dim retVal

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  If szSound="*hold*" Then
    retVal = PBXCall.PlayMessage("")
  Else
    retVal = PBXCall.PlayMessage(szSound)
  End If

  'We don't need to check return value

  TraceSubResult "PlaySound"
End Sub

Sub Voicemail(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound)
  ' Obsolete. This function is used to support 3.20 clients
  VoicemailEx bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, _
              False, "", "", "", "", False, False
End Sub

Sub VoicemailEx(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, _
                ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  ' Obsolete. This function is used to support 4.00 clients
  VoicemailEx2 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, _
               bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
               g_szStdRiPIN, True
End Sub


' obsolete (for support 4.20 scripts)
Sub VoicemailEx2(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, _
                ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                ByVal szPIN, ByVal bUseStdRI)
  ' Obsolete. This function is used to support 4.20 clients
  VoicemailEx3 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, False,_
                bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                szPIN, bUseStdRI, False
End Sub

' for 4.30
Sub VoicemailEx3(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
                ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  VoicemailEx4 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM,_
                bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                szPIN, bUseStdRI, bStdRIWithoutPIN, False
End Sub

' for 5.00
Sub VoicemailEx4(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
                ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
                
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement
  AdjustBoolean bUseStdVM
  AdjustBoolean bEnabled
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
                
  VoicemailEx5 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, _
                bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
                szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
End Sub
                
' for 6.20
Sub VoicemailEx5(ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
                ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
                ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  TraceFunction "VoicemailEx5", bGreeting & ", " & szGreetingSound & ", " & bUseDTMF & ", " & szUseDTMFAnnouncementSound & ", " & _
                      bAnnouncement & ", " & szAnnouncementSound & ", " & nRecordMessage & ", " & _
                      szAddress & ", " & bUseStdVM & ", " & _
                      bEnabled & ", " & szServerName & ", " & szUserName & ", " & szPassword & ", " & szMailFolder & ", " & bUseSSL & ", " & bUsePINPrompt & ", " & _
                      szPIN & ", " & bUseStdRI & ", " & bStdRIWithoutPIN & ", " & bUseFromCriteria
  Dim retVal, szDtmfMask, pDtmfDigit, szCallerID, szDtmfMaskTmp
  
  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  If Not PBXCall.IsOriginatorDisconnected Then
    PBXCall.PhoneCallListEntry.State = PhoneCallStateCallDivertedToVoicemail
  End If

  ' set connected flag to true to skip post processing
  bCallConnected = true

  ' If we use stnadard VM start it immediatelly
  If (bUseStdVM = True) Then
    PBXScript.OutputTrace "use Standard Voicemail"
    StandardVoicemailEx
    Exit Sub
  End If
  
  szDtmfMask = ""
  pDtmfDigit = ""

  If (bEnabled = True) Then
    ' allow Remote inquiry
    szDtmfMask = "*"
  Else
    ' disable Remote inquiry
    szDtmfMask = ""
  End If
  
  'Play greeting
  If (bGreeting = True) Then
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true

    If szGreetingSound = "*hold*" Then
      retVal = PBXCall.GetDtmfInput("##holdmusic#", 0, 0, szDtmfMask, 0, pDtmfDigit)
    Else
      retVal = PBXCall.GetDtmfInput(szGreetingSound, 0, 0, szDtmfMask, 0, pDtmfDigit)
    End If

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      crmRemoteInquiryEx4 "Voicemail.True", szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
    If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
      'Something wrong. End this action
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
  End If
  
  'Play DTMF announcement sound
  If ((bUseDTMF = True) and (PBXCall.CallingPartyNumber = "")) Then
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true
    szDtmfMaskTmp = "1234567890#" & szDtmfMask
    pDtmfDigit = ""

    If szUseDTMFAnnouncementSound = "*hold*" Then
      retVal = PBXCall.GetDtmfInput("##holdmusic#", 0, 0, szDtmfMaskTmp, 15, pDtmfDigit)
    Else
      retVal = PBXCall.GetDtmfInput(szUseDTMFAnnouncementSound, 0, 0, szDtmfMaskTmp, 15, pDtmfDigit)
    End If

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      crmRemoteInquiryEx4 "Voicemail.True", szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
    If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
      'Something wrong. End this action
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
  
    'Get CallerID; "#" - end input
    szCallerID = pDtmfDigit
              
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true
    retVal = PBXSuccess  
    Do While (retVal = PBXSuccess)
      If (pDtmfDigit = "#") Then
        szCallerID = ""
        Exit Do
      End If
      pDtmfDigit = ""
      retVal = PBXCall.GetDtmfInput("", 0, 0, "1234567890#", 15, pDtmfDigit)
      If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
        'Something wrong. End this action
        TraceSubResult "VoicemailEx5"
        Exit Sub
      End If
      If (pDtmfDigit = "#") Or (retVal = PBXTimeout) Then
        Exit Do
      Else
        szCallerID = szCallerID & pDtmfDigit
      End If
      If (Len(CStr(pDtmfDigit)) = 0) Then
        ' an error
        Exit Do
      End If
    Loop
  
    If (szCallerID <> "") Then
      PBXCall.CallingPartyNumber = szCallerID
    End If
  End If
  
  If (bAnnouncement = True) Then
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true

    If szAnnouncementSound="*hold*" Then
      retVal = PBXCall.GetDtmfInput("##holdmusic#", 0, 0, szDtmfMask, 0, pDtmfDigit)
    Else
      retVal = PBXCall.GetDtmfInput(szAnnouncementSound, 0, 0, szDtmfMask, 0, pDtmfDigit)
    End If

    If ((bEnabled = True) And (pDtmfDigit = "*")) Then
      ' start remote inquiry
      crmRemoteInquiryEx4 "Voicemail.True", szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
    If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
      'Something wrong. End this action
      TraceSubResult "VoicemailEx5"
      Exit Sub
    End If
  End If
  
  'Record messge
  retVal = PBXCall.PlayMessage("Beep.wav")
  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true
  If (retVal <> PBXSuccess) Then
    'Something wrong. End this action
    TraceSubResult "VoicemailEx5"
    Exit Sub
  End If
  retVal = PBXCall.RecordMessage(nRecordMessage)
  
  If ((retVal <> PBXSuccess) And (retVal <> PBXTimeout) And (retVal <> PBXCallTermNormalCallClearing)) Then
    'Something wrong. End this action
    TraceSubResult "VoicemailEx5"
    Exit Sub
  End If
  
  'Send EMail
  SendEmail szAddress, g_resStandardVoicemailSubject, g_resStandardVoicemailBody, True
  TraceSubResult "VoicemailEx5"
End Sub

' obsolete
Sub RecordMessage(ByVal nTimeout)
  RecordMessageEx2 nTimeout, False
End Sub

Sub RecordMessageEx(ByVal nTimeout, ByVal bPlayBeep)
  AdjustBoolean bPlayBeep
  RecordMessageEx2 nTimeout, bPlayBeep
End Sub

Sub RecordMessageEx2(ByVal nTimeout, ByVal bPlayBeep)
  TraceFunction "RecordMessageEx2", CStr(nTimeout) & ", " & CStr(bPlayBeep)
  Dim retVal

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  If (bPlayBeep = True) Then
    retVal = PBXCallPlayMessageEx("Beep.wav")
  End If

  ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
  bCallConnected = true

  retVal = PBXCall.RecordMessage(nTimeout)
  'We don't need to check the return value
  TraceSubResult "RecordMessageEx2"
End Sub

Sub SendEmail(ByVal szAddress, ByVal szSubject, ByVal szBody, ByVal bAttach)
  TraceFunction "SendEmail", CStr(szAddress) & ", " & CStr(szSubject) & ", ..., " & CStr(bAttach)
  Dim retVal, szSubAddress

  AdjustBoolean bAttach
  Do While (Len(szAddress) > 0)
    szSubAddress = SplitNumber(szAddress)
    'Send Email
    If (Len(szSubAddress) > 0) Then
      retVal = PBXCall.SendEMail(szSubAddress, szSubject, szBody, bAttach)
    End If
  Loop
  TraceSubResult "SendEmail"
End Sub

Sub FollowMe(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal szSound)
  ' Obsolete. This function is used to support 3.20 clients
  FollowMeEx bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, _
               False, "", "", "", "", False, False
End Sub

Sub FollowMeEx(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, _
               ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  ' Obsolete. This function is used to support 4.00 clients
  FollowMeEx2 bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, _
              bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
              g_szStdRiPIN, True
End Sub

' obsolete
Sub FollowMeEx2(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, _
               ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
               ByVal szPIN, ByVal bUseStdRI)

  FollowMeEx3 bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, _
              bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, False, _
              bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
              szPIN, bUseStdRI, False
End Sub

'for 4.30
Sub FollowMeEx3(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
               ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
               ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)

  FollowMeEx4 bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, _
              bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, _
              bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
              szPIN, bUseStdRI, bStdRIWithoutPIN, False
End Sub

'for 5.00
Sub FollowMeEx4(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
               ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
               ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
               
  AdjustBoolean bAccept
  AdjustBoolean bDeliver
  AdjustBoolean bCallFwd1
  AdjustBoolean bCallFwd2
  AdjustBoolean bCallFwd3
  AdjustBoolean bCallFwdVoice
  AdjustBoolean bPreFwd
  AdjustBoolean bActivate
  AdjustBoolean bGreeting
  AdjustBoolean bUseDTMF
  AdjustBoolean bAnnouncement
  AdjustBoolean bUseStdVM
  AdjustBoolean bEnabled
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria

  FollowMeEx5 bAccept, szAcceptSound, bDeliver, nDeliverSec, bCallFwd1, szCallFwdTo1, nCallFwdSec1, bCallFwd2, szCallFwdTo2, nCallFwdSec2, bCallFwd3, szCallFwdTo3, nCallFwdSec3, bCallFwdVoice, bPreFwd, szPreFwdSound, bActivate, bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, _
               bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, _
               szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
End Sub

'for 6.20
Sub FollowMeEx5(ByVal bAccept, ByVal szAcceptSound, ByVal bDeliver, ByVal nDeliverSec, ByVal bCallFwd1, ByVal szCallFwdTo1, ByVal nCallFwdSec1, ByVal bCallFwd2, ByVal szCallFwdTo2, ByVal nCallFwdSec2, ByVal bCallFwd3, ByVal szCallFwdTo3, ByVal nCallFwdSec3, ByVal bCallFwdVoice, ByVal bPreFwd, ByVal szPreFwdSound, ByVal bActivate, ByVal bGreeting, ByVal szGreetingSound, ByVal bUseDTMF, ByVal szUseDTMFAnnouncementSound, ByVal bAnnouncement, ByVal szAnnouncementSound, ByVal nRecordMessage, ByVal szAddress, ByVal bUseStdVM, _
               ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, _
               ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  TraceFunction "FollowMeEx5", bAccept & ", " & szAcceptSound & ", " & bDeliver & ", " & nDeliverSec & ", " & _
                     bCallFwd1 & ", " & szCallFwdTo1 & ", " & nCallFwdSec1 & ", " & _
                     bCallFwd2 & ", " & szCallFwdTo2 & ", " & nCallFwdSec2 & ", " & _
                     bCallFwd3 & ", " & szCallFwdTo3 & ", " & nCallFwdSec3 & ", " & _
                     bCallFwdVoice & ", " & bPreFwd & ", " & szPreFwdSound & ", " & _
                     bActivate & ", " & bGreeting & ", " & szGreetingSound & ", " & _
                     bUseDTMF & ", " & szUseDTMFAnnouncementSound & ", " & _
                     bAnnouncement & ", " & szAnnouncementSound & ", " & nRecordMessage & ", " & _
                     szAddress & ", " & bUseStdVM & ", " & _
                     bEnabled & ", " & szServerName & ", " & szUserName & ", " & szPassword & ", " & szMailFolder & ", " & bUseSSL & ", " & bUsePINPrompt & ", " & _
                     szPIN & ", " & bUseStdRI & ", " & bStdRIWithoutPIN & ", " & bUseFromCriteria
  Dim pDtmfDigit, retVal, retState, bPlayPreFwd, rResultOfLastConnectTo, szDigitMask, pDummy, pDummyV

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    Dim retHoldVal
    retHoldVal = gseActivate()
  End If

  pDtmfDigit = "x"
  rResultOfLastConnectTo = PBXSuccess
  szDigitMask = ""
  
  If (bEnabled = True) Then
    ' RI enabled
    szDigitMask = "*"
  End If

  If (bActivate = True) Then
    szDigitMask = szDigitMask & "#"
  End If

  'Play announcement sound
  If (bAccept = True) Then
    retVal = PBXCallGetDtmfInputEx(szAcceptSound, 0, 0, szDigitMask, 0, pDtmfDigit)
    ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
    bCallConnected = true
    If (bEnabled = True And pDtmfDigit = "*") Then
      ' Start RI, leave this func
      If (bUseStdVM = True) Then
        ' start standard RI
        crmRemoteInquiryEx4 "Voicemail.True", szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, True, bStdRIWithoutPIN, bUseFromCriteria
      Else
        ' start custom RI
        crmRemoteInquiryEx4 "Voicemail.True", szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
      End If
      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If

    If (pDtmfDigit = "#") Then
      VoicemailEx5 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM,_
                  bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria

      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If

    If (retVal <> PBXSuccess) And (retVal <> PBXTimeout) Then
      'Something wrong. End this action
      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If
  End If
    
  'Connect to myself
  If (bDeliver = True) Then
    If (Not bCallConnected) Then
      ' send "CallProceeding" to external originating call to avoid ISDN timeout on external calls!
      PBXCall.CallProceeding
    End If
    If (PBXUser.IsBusy = 0) Then
      retVal = PBXCallConnectToWrapper(PBXCall.CalledPartyNumber, nDeliverSec, false, "", "", pDummy, true, nDeliverSec, true, "", "", pDummyV, true, true)
    Else
      retVal = PBXCallTermDestinationBusy
    End If

    rResultOfLastConnectTo = retVal
    If (retVal = PBXSuccess) Or (retVal = PBXFailure) Then
      'ConnectTo successful or something failed. Leave this function.
      TraceSubResult "FollowMeEx5"
      Exit Sub
    Else
      'No response. Try next calllerid.
    End If
  End If
  
  'Connect to specified numbers.
  ' Note on return values of ConnectToSpecifiedNumber(...)       
  ' retState = 0  => not connected and try next destination 
  ' retState = 1  => failure occured. Stop script action
  ' retState = 2  => connected successful.
  ' retState = 3  => Voicemail (timeout)
  ' retState = 4  => Voicemail (disconnect)

  If (bCallFwd1 = True) Then
    ' If bDeliver is not selected (connect to original destination) do not play pre-fwd sound (#2894)
    If ((bDeliver = True) And (bPreFwd = True)) Then
      bPlayPreFwd = True
    Else
      bPlayPreFwd = False
    End If

    retState = ConnectToSpecifiedNumberEx7(bPlayPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, "", _
                   szCallFwdTo1, nCallFwdSec1, _
                   bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    If (retState >= 1) Then
      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If
  End If

  If (bCallFwd2 = True) Then
    retState = ConnectToSpecifiedNumberEx7(bPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, "", _
                   szCallFwdTo2, nCallFwdSec2, _
                   bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    If (retState >= 1) Then
      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If
  End If
      
  If (bCallFwd3 = True) Then
    retState = ConnectToSpecifiedNumberEx7(bPreFwd, bActivate, szPreFwdSound, _
                   bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, _
                   bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM, "", _
                   szCallFwdTo3, nCallFwdSec3, _
                   bEnabled, szServerName, szUserName, szPassword, True, szMailFolder, bUseSSL, bUsePINPrompt, _
                   True, rResultOfLastConnectTo, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
    If (retState >= 1) Then
      TraceSubResult "FollowMeEx5"
      Exit Sub
    End If
  End If
  
  'Connect directly to voicemail, if it is selected.
  If (bCallFwdVoice = True) Then
    VoicemailEx5 bGreeting, szGreetingSound, bUseDTMF, szUseDTMFAnnouncementSound, bAnnouncement, szAnnouncementSound, nRecordMessage, szAddress, bUseStdVM,_
                 bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
  End If
  TraceSubResult "FollowMeEx5"
End Sub



'' ****************************************************************************************************
'' ************************************* Functions for IpPBX v3.30 ************************************
'' ****************************************************************************************************

' Last downloaded email (function gseIMAP4_SaveVoicemailToTmpFile) (temporary solution. futuremore these outputs will be removed to callrouting.vbs file)
Dim g_szLastDownloadedVoicemail
g_szLastDownloadedVoicemail = ""

' Folder for temporary voicemails (temporary solution. futuremore these outputs will be removed to callrouting.vbs file)
Dim g_szTmpVoicemailFolder
g_szTmpVoicemailFolder = ""

'' **************************************** Commmon functions *****************************************
''''''''''''''
'' Function:
''   ExtractIpPbxIMAP4RetVal()
'' Description:
''   Converts the return code for display
'' Parameters:
''   [in] nRetVal - Number of error message
'' Return value:
''   Text of error message
Function ExtractIpPbxIMAP4RetVal(ByVal nRetVal)
  Dim szRetVal

  Select Case nRetVal
    Case 0: szRetVal = "IpPbxMailErrorSuccess"
    Case 1: szRetVal = "IpPbxMailErrorInvalidState"
    Case 2: szRetVal = "IpPbxMailErrorMailAccess"
    Case 3: szRetVal = "IpPbxMailErrorInvalidParameter"
    Case 4: szRetVal = "IpPbxMailErrorNoFileAttached"
    Case 5: szRetVal = "IpPbxMailErrorCreateFile"
    Case 6: szRetVal = "IpPbxMailErrorWriteFile"
    Case 7: szRetVal = "IpPbxMailErrorNoMailServer"
    Case 8: szRetVal = "IpPbxMailErrorLogin"
    Case 9: szRetVal = "IpPbxMailErrorTimeout"
    Case Else: szRetVal = "Unknown Error"
  End Select
  ExtractIpPbxIMAP4RetVal = szRetVal
End Function


''''''''''''''
'' Function:
''   AddLeadingZeros()
'' Description:
''   Append number with leading zeros
'' Parameters:
''   [in] szSrc - Source number
''   [in] nExpectedNumberLength - Expected length of number
'' Return value:
''   String with leading zeros
Function AddLeadingZeros(ByVal szSrc, ByVal nExpectedNumberLength)
  Dim szDst

  szDst = CStr(szSrc)
  ' Add leading zeros
  Do While (Len(szDst) < CIntEx(nExpectedNumberLength))
    szDst = "0" & szDst
  Loop
  AddLeadingZeros = szDst
End Function


''''''''''''''
'' Function:
''   SplitString()
'' Description:
''   Split string szText using delimeter szDelimiter
'' Parameters:
''   [in/out] szText - String with multiply numbers, return: updated string (without extracted number and delimeter)
''   [in] szDelimiter - delimeter character
'' Return value:
''   Extracted substring
Function SplitString(ByRef szText, ByVal szDelimiter)
  Dim nPos, szSubString

  nPos = 1
  szSubString = ""

  If (Len(szText) = 0) Then
    szSubString = ""
    szText = ""
  Else
    nPos = InStr(szText, szDelimiter)
    If (nPos = 0) Then
      szSubString = szText
      szText = ""
    ElseIf (nPos = 1) Then
      szSubString = ""
      szText = Right(szText, Len(szText) - nPos)
    Else
      szSubString = Left(szText, nPos - 1)
      szText = Right(szText, Len(szText) - nPos)
    End If
  End If

  SplitString = szSubString
End Function

Function CollectPostDialDigits(ByVal szEndMark)
  Dim szDigits, nCount

  szDigits = PBXCall.PostDialingDigits
  nCount = 0
  While (Not (Right(szDigits, 1) = szEndMark) And (nCount<20))
    PBXScript.OutputTrace "no end mark, waiting for additional digits: " & szDigits
    PBXScript.Sleep(500)
    nCount = nCount + 1
    szDigits = PBXCall.PostDialingDigits
  Wend
  CollectPostDialDigits = PBXCall.PostDialingDigits
End Function

''''''''''''''
'' Function:
''   CIntEx()
'' Description:
''   Convert any string to int. In addition to VBScript's CInt function this function returns "0" in case of empty string
'' Parameters:
''   [in] szVal - String to convert
'' Return value:
''   Integer
Function CIntEx(ByVal szVal)
  If (Not IsNumeric(szVal)) Or (Len(CStr(szVal)) > 4) Then
    CIntEx = CInt("0")
  Else
    CIntEx = CInt(szVal)
  End If
End Function


''''''''''''''
'' Function:
''   CIntExWithDef()
'' Description:
''   Convert any string to int. In addition to CIntEx function this function returns szDefault instead of "0"
'' Parameters:
''   [in] szVal - String to convert
''   [in] szDefault - default value in case if szVal is not integer
'' Return value:
''   Integer
Function CIntExWithDef(ByVal szVal, ByVal szDefault)
  If (Not IsNumeric(szVal)) Or (Len(CStr(szVal)) > 4) Then
    CIntExWithDef = CInt(szDefault)
  Else
    CIntExWithDef = CInt(szVal)
  End If
End Function


''''''''''''''
'' Function:
''   PBXCallGetDtmfInputEx()
'' Description:
''   Paly normal sound of saved IMAP4 attacment (gseIMAP4_SaveVoicemailToTmpFile) in case if szSoud = "..."
'' Parameters:
''   The same as in PBXCall::GetDtmfInput
'' Return value:
''   result of PBXCall::GetDtmfInput
Function PBXCallGetDtmfInputEx(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal fMask, ByVal nTimeout, ByRef rDtmfDigit)
  rDtmfDigit = ""
  If (szSound = "...") Then
    ' Play temporary file (last file saved in gseIMAP4_SaveVoicemailToTmpFile function)
    PBXScript.OutputTrace "PBXCallGetDtmfInputEx, play file: [" & g_szLastDownloadedVoicemail & "]"
    If (Len(g_szLastDownloadedVoicemail) = 0) Then
      ' If no tmp file available --> return Played
      PBXCallGetDtmfInputEx = PBXSuccess
      rDtmfDigit = ""
    Else
      PBXCallGetDtmfInputEx = PBXCall.GetDtmfInput(g_szLastDownloadedVoicemail, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  Else
    If (Len(szSound) = 0) Then
      ' If no tmp file available --> return Played
      PBXCallGetDtmfInputEx = PBXSuccess
      PBXScript.OutputTrace "PBXCallGetDtmfInputEx, no sound file"
    Else
      ' Play sound
      If szSound="*hold*" Then
        PBXCallGetDtmfInputEx = PBXCall.GetDtmfInput("##holdmusic#", 0, nInterval, fMask, nTimeout, rDtmfDigit)
      Else
        PBXCallGetDtmfInputEx = PBXCall.GetDtmfInput(szSound, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit)
      End If

      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  End If
End Function

' GSE 4.2.0.51
Function PBXCallGetDtmfInputEx2(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal fMask, ByVal nTimeout, ByRef rDtmfDigit, _
                                ByVal bSkipBegining, ByVal nSkipSeconds, ByVal bPlayControl)
  AdjustBoolean bSkipBegining
  AdjustBoolean bPlayControl
  PBXCallGetDtmfInputEx2 = PBXCallGetDtmfInputEx3(szSound, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit, bSkipBegining, nSkipSeconds, bPlayControl)
End Function
                                
' GSE 6.20.0.17
''''''''''''''
'' Function:
''   PBXCallGetDtmfInputEx3()
'' Description:
''   Paly normal sound of saved IMAP4 attacment (gseIMAP4_SaveVoicemailToTmpFile) in case if szSoud = "..."
''   Support skip beginning
''   Support play control
'' Parameters:
''   The same as in PBXCall::GetDtmfInputEx
'' Return value:
''   result of PBXCall::GetDtmfInputEx
Function PBXCallGetDtmfInputEx3(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal fMask, ByVal nTimeout, ByRef rDtmfDigit, _
                                ByVal bSkipBegining, ByVal nSkipSeconds, ByVal bPlayControl)
  rDtmfDigit = ""
  If (szSound = "...") Then
    ' Play temporary file (last file saved in gseIMAP4_SaveVoicemailToTmpFile function)
    PBXScript.OutputTrace "PBXCallGetDtmfInputEx3, play file: [" & g_szLastDownloadedVoicemail & "]"
    If (Len(g_szLastDownloadedVoicemail) = 0) Then
      ' If no tmp file available --> return Played
      PBXCallGetDtmfInputEx3 = PBXSuccess
      rDtmfDigit = ""
    Else
      If (bPlayControl = True) Then
        PBXCallGetDtmfInputEx3 = PBXCallGetDtmfInputEx2PlayControl(g_szLastDownloadedVoicemail, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit, bSkipBegining, nSkipSeconds, bPlayControl)
      Else
        PBXCallGetDtmfInputEx3 = PBXCall.GetDtmfInputEx(g_szLastDownloadedVoicemail, nSkipSeconds, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit)
      End If
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  Else
    If (Len(szSound) = 0) Then
      ' If no tmp file available --> return Played
      PBXCallGetDtmfInputEx3 = PBXSuccess
      PBXScript.OutputTrace "PBXCallGetDtmfInputEx3, no sound file"
    Else
      ' Play sound
      If (bPlayControl = True) Then
        PBXCallGetDtmfInputEx3 = PBXCallGetDtmfInputEx2PlayControl(szSound, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit, bSkipBegining, nSkipSeconds, bPlayControl)
      Else
        If szSound="*hold*" Then
          PBXCallGetDtmfInputEx3 = PBXCall.GetDtmfInputEx("##holdmusic#", nSkipSeconds, 0, nInterval, fMask, nTimeout, rDtmfDigit)
        Else
          PBXCallGetDtmfInputEx3 = PBXCall.GetDtmfInputEx(szSound, nSkipSeconds, nRepetitions, nInterval, fMask, nTimeout, rDtmfDigit)
        End If
      End If
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  End If
End Function



' GSE 4.2.0.51
''''''''''''''
'' Function:
''   PBXCallGetDtmfInputEx2PlayControl()
'' Description:
''   Implementation of play control
'' Parameters:
''   The same as in PBXCall::GetDtmfInputEx
'' Return value:
''   result of PBXCall::GetDtmfInputEx
Function PBXCallGetDtmfInputEx2PlayControl(ByVal szSound, ByVal nRepetitions, ByVal nInterval, ByVal fMask, ByVal nTimeout, ByRef rDtmfDigit, _
                                ByVal bSkipBegining, ByVal nSkipSeconds, ByVal bPlayControl)
  Dim retVal, nStartPosition, nCurPosition, szCurMask, nTimeB, nTimeE, nTimeDelta, bSilence, nSilenceTime, bNowSilence, bWasTimeout, nTotalLen, bWasKeyPressed
  
  'AdjustBoolean bSkipBegining
  'AdjustBoolean bPlayControl

  nTotalLen = PBXScript.GetAudioFileLength(szSound)

  If szSound = "*hold*" Then
    nTotalLen = 9999
  End If

  PBXScript.OutputTrace "[PlayControl] started, SkipSeconds = " & nSkipSeconds & ", Total Lenght " & nTotalLen

  nStartPosition = CInt(nSkipSeconds)
  If (nStartPosition > nTotalLen) Then
    nStartPosition = nTotalLen
  End If
  nCurPosition = nStartPosition
  szCurMask = "1234567890*#"
  ' szCurMask = "13456*"
  bSilence = False
  nSilenceTime = 0
  bNowSilence = False
  bWasTimeout = False
  bWasKeyPressed = False

  Do
    rDtmfDigit = ""
    If (bSilence) Then
      ' Play silence
      retVal = PBXCall.GetDtmfInputEx("", 0, 0, 0, szCurMask, nSilenceTime, rDtmfDigit)
      bSilence = False
      bNowSilence = True
    Else
      If (nCurPosition < nTotalLen) Then
        nTimeB = PBXUser.Now
        If szSound="*hold*" Then
          retVal = PBXCall.GetDtmfInputEx("##holdmusic#", nCurPosition, 0, nInterval, szCurMask, nTimeout, rDtmfDigit)
        Else
          retVal = PBXCall.GetDtmfInputEx(szSound, nCurPosition, nRepetitions, nInterval, szCurMask, nTimeout, rDtmfDigit)
        End If

        nTimeE = PBXUser.Now
        bNowSilence = False
        nTimeDelta = DateDiff("s", nTimeB, nTimeE)
        PBXScript.OutputTrace "[PlayControl] Duration=" & nTimeDelta & ", retVal=[" & ExtractReturnValue(retVal) & "]"
      Else
        retVal = PBXTimeout
      End If
    End If
    If (retVal = PBXSuccess) Then
      bWasTimeout = False
      bWasKeyPressed = True
      ' DTMF key pressed
      PBXScript.OutputTrace "[PlayControl] DTMF=[" & rDtmfDigit & "]"
      Select Case rDtmfDigit
        Case "1"
          PBXScript.OutputTrace "[PlayControl] 1: Play from beginning"
          nCurPosition = nStartPosition
        Case "3"
          PBXScript.OutputTrace "[PlayControl] 3: Go end, wait 1 sec for more input"
          bSilence = True
          nSilenceTime = 1
          nCurPosition = nTotalLen
        Case "4"
          PBXScript.OutputTrace "[PlayControl] 4: Go 10 sec back"
          nCurPosition = nCurPosition + nTimeDelta - 10
          If (nCurPosition < nStartPosition) Then
            nCurPosition = nStartPosition
          End If
          PBXScript.OutputTrace "[PlayControl] New position = " & nCurPosition & " sec"
        Case "5"
          If (bNowSilence) Then
            PBXScript.OutputTrace "[PlayControl] 5: Resume"
          Else
            PBXScript.OutputTrace "[PlayControl] 5: Pause"
            bSilence = True
            nSilenceTime = 180
            nCurPosition = nCurPosition + nTimeDelta
            nTimeDelta = 0
            PBXScript.OutputTrace "[PlayControl] New position = " & nCurPosition & " sec"
          End If
        Case "6"
          PBXScript.OutputTrace "[PlayControl] 6: Go 10 sec forward"
          nCurPosition = nCurPosition + nTimeDelta + 10
          If (nCurPosition >= nTotalLen) Then
            nCurPosition = nTotalLen
            nSilenceTime = 1
            bSilence = True
          End If
          PBXScript.OutputTrace "[PlayControl] New position = " & nCurPosition & " sec"
        Case Else
          PBXScript.OutputTrace "[PlayControl] DTMF=[" & rDtmfDigit & "]: Leave block with output DTMFKeyPressed"
          PBXCallGetDtmfInputEx2PlayControl = PBXSuccess
          Exit Function
      End Select
    ElseIf (retVal = PBXTimeout) Then
      If (Not bWasTimeout And bWasKeyPressed) Then
        bSilence = True
        nSilenceTime = 3
        bWasTimeout = True
      Else
        ' Timeout
        rDtmfDigit = ""
        PBXCallGetDtmfInputEx2PlayControl = retVal
        Exit Function
      End If
    Else
      ' Disconnect
      rDtmfDigit = ""
      PBXCallGetDtmfInputEx2PlayControl = retVal
      Exit Function
    End If
  Loop
End Function


''''''''''''''
'' Function:
''   PBXCallPlayMessageEx()
'' Description:
''   Paly normal sound of saved IMAP4 attacment (gseIMAP4_SaveVoicemailToTmpFile) in case if szSoud = "..."
'' Parameters:
''   The same as in PBXCall::PlayMessage
'' Return value:
''   result of PBXCall::PlayMessage
Function PBXCallPlayMessageEx(ByVal szSound)
  If (szSound = "...") Then
    ' Play temporary file (last file saved in gseIMAP4_SaveVoicemailToTmpFile function)
    PBXScript.OutputTrace "PBXCallPlayMessageEx, play file: [" & g_szLastDownloadedVoicemail & "]"
    If (Len(g_szLastDownloadedVoicemail) = 0) Then
      ' If no tmp file available --> return Played
      PBXCallPlayMessageEx = PBXSuccess
    Else
      PBXCallPlayMessageEx = PBXCall.PlayMessage(g_szLastDownloadedVoicemail)
      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  Else
    ' Play sound
    If (Len(CStr(szSound)) = 0) Then
      ' There is not soyund file
      PBXCallPlayMessageEx = PBXSuccess
      PBXScript.OutputTrace "PBXCallPlayMessageEx, no sound file"
    Else

      If szSound="*hold*" Then
        PBXCallPlayMessageEx = PBXCall.PlayMessage("")
      Else
        PBXCallPlayMessageEx = PBXCall.PlayMessage(szSound)
      End If

      ' set connected flag to true to skip post processing, because the originating call will be connected to voice call
      bCallConnected = true
    End If
  End If
End Function


'' *************************************** SayDate and SayTime ****************************************
Function gseSayTime(ByVal szTime, ByVal bSaySeconds, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  AdjustBoolean bSaySeconds
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  gseSayTime = gseSayTimeEx(szTime, bSaySeconds, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
End Function

''''''''''''''
'' Function:
''   gseSayTimeEx()
'' Description:
''   Reads out the time using multiple wav-files, not a Text-To-Speech module.
'' Time format:
''  XXh.wav YYm.wav [TimeAnd.wav ZZs.wav]
'' Where:
''  XX - Hour (00-23)
''      YY - Minute (00-59)
''      ZZ - Second (00-59)
'' Parameters:
''   [in] szTime - Time to read (Format: HH:MM:SS or HH:MM)
''   [in] bSaySeconds - The second are read out only, if "True"
''   [in] fMask - DTMF detection mask
''   [in] bStoreToVariable - Store DTMF digit to variable or not
''   [in/out] szVariableName - MVariable to store
''   [in] bResetVariableContent - Reset variable content or not
'' Return value:
''   gseStatePlayed - Played
''   gseStateDTMFKeyPressed - DTMF detected
''   gseStateFailed - Invalid parameter
''   gseStateDisconnected - Disconnect
Function gseSayTimeEx(ByVal szTime, ByVal bSaySeconds, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  Dim fnResult, nHour, nMinute, nSecond, retVal, szSoundName, szDef
  
  TraceFunction "gseSayTimeEx", szTime & ", " & bSaySeconds & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  fnResult = gseStateFailed


  If (VarType(szTime) = vbDate) Then
    nHour = Hour(szTime)
    nMinute = Minute(szTime)
    nSecond = Second(szTime)
  Else
    ' Split time
    nHour = CIntExWithDef(SplitString(szTime, ":"), "-1")
    nMinute = CIntExWithDef(SplitString(szTime, ":"), "-1")

    If (bSaySeconds = True) Then
      szDef = "-1"
    Else
      szDef = "0"
    End If
    nSecond = CIntExWithDef(SplitString(szTime, ":"), szDef)
  End If

  If ((nHour < 0) Or (nHour > 23) Or (nMinute < 0) Or (nMinute > 59) Or (nSecond < 0) Or (nSecond > 59)) Then
    PBXScript.OutputTrace "gseSayTimeEx, error: invalid time format"
    retVal = gsePlaySound("datetime/WrongTime.wav", fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayTimeEx = retVal
      PBXScript.OutputTrace "gseSayTimeEx DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
      Exit Function
    End If
  Else
    ' Play hours
    szSoundName = "datetime/" & AddLeadingZeros(CStr(nHour), 2) & "h.wav"
    PBXScript.OutputTrace "gseSayTimeEx, hour=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayTimeEx = retVal
      PBXScript.OutputTrace "gseSayTimeEx DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
      Exit Function
    End If
    ' Play minutes
    szSoundName = "datetime/" & AddLeadingZeros(CStr(nMinute), 2) & "m.wav"
    PBXScript.OutputTrace "gseSayTimeEx, minute=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayTimeEx = retVal
      PBXScript.OutputTrace "gseSayTimeEx DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
      Exit Function
    End If
    ' Play seconds
    If (bSaySeconds = True) Then
      retVal = gsePlaySound("datetime/TimeAnd.wav", fMask, bStoreToVariable, szVariableName, bResetVariableContent)
      If (retVal <> gseStatePlayed) Then
        gseSayTimeEx = retVal
		PBXScript.OutputTrace "gseSayTimeEx DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
        Exit Function
      End If
      szSoundName = "datetime/" & AddLeadingZeros(CStr(nSecond), 2) & "s.wav"
      PBXScript.OutputTrace "gseSayTimeEx, second=" & szSoundName
      retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
      If (retVal <> gseStatePlayed) Then
        gseSayTimeEx = retVal
		PBXScript.OutputTrace "gseSayTimeEx DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
        Exit Function
      End If
    End If
    fnResult = gseStatePlayed
  End If
 
  gseSayTimeEx = fnResult
  TraceFunctionResult "gseSayTimeEx", gseSayTimeEx
End Function


''''''''''''''
'' Function:
''   gseSayDate()
'' Description:
''   Reads out the date using multiple wav-files, not a Text-To-Speech module.
'' Date format:
''      [DOW.wav] XXd.wav YYt.wav ZZy.wav
'' Where:
''      DOW - Day of Week (Monday, Tuesday, ..., Sunday)
''      XX - Day (01-31)
''      YY - Month (01-12)
''      ZZ - Year (1990-2009)
'' Parameters:
''   [in] szDate - Time to read (Format: DD.MM.YYYY)
''   [in] bPlayDOF - If "True" play day of week
''   [in] fMask - DTMF detection mask
''   [in] bStoreToVariable - Store DTMF digit to variable or not
''   [in/out] szVariableName - MVariable to store
''   [in] bResetVariableContent - Reset variable content or not
'' Return value:
''   gseStatePlayed - Played
''   gseStateDTMFKeyPressed - DTMF detected
''   gseStateFailed - Invalid parameter
''   gseStateDisconnected - Disconnect
Function gseSayDate(ByVal szDate, ByVal bPlayDOF, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent)
  Dim fnResult, nDay, nMonth, nYear, retVal, szSoundName, nDOF
  AdjustBoolean bPlayDOF
    
  TraceFunction "gseSayDate", szDate & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  fnResult = gseStateFailed

  If (VarType(szDate) = vbDate) Then
    nDay = Day(szDate)
    nMonth = Month(szDate)
    nYear = Year(szDate)
  Else
    ' Split date
    nDay = CIntEx(SplitString(szDate, "."))
    nMonth = CIntEx(SplitString(szDate, "."))
    nYear = CIntEx(SplitString(szDate, "."))
  End If

  If ((nDay < 1) Or (nDay > 31) Or (nMonth < 1) Or (nMonth > 12) Or (nYear < 1990) Or (nYear > 2009)) Then
    PBXScript.OutputTrace "gseSayDate, error: invalid date format"
    retVal = gsePlaySound("datetime/WrongDate.wav", fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDate = retVal
      TraceFunctionResult "gseSayDate, wrong date", gseSayDate
      Exit Function
    End If
  Else
    ' Play DOF
    If (bPlayDOF = True) Then
      nDOF = Weekday(DateSerial(nYear, nMonth, nDay))
      Select Case nDOF
        Case vbSunday
          szSoundName = "datetime/Sunday.wav"
        Case vbMonday
          szSoundName = "datetime/Monday.wav"
        Case vbTuesday
          szSoundName = "datetime/Tuesday.wav"
        Case vbWednesday
          szSoundName = "datetime/Wednesday.wav"
        Case vbThursday
          szSoundName = "datetime/Thursday.wav"
        Case vbFriday
          szSoundName = "datetime/Friday.wav"
        Case vbSaturday
          szSoundName = "datetime/Saturday.wav"
        Case Else
          ' this case will never be reached
          szSoundName = "datetime/WrongDate.wav"
      End Select
      PBXScript.OutputTrace "gseSayDate, dof=" & szSoundName
      retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
      If (retVal <> gseStatePlayed) Then
        gseSayDate = retVal
        TraceFunctionResult "gseSayDate, day", gseSayDate
        Exit Function
      End If
    End If
    ' Play day
    szSoundName = "datetime/" & AddLeadingZeros(CStr(nDay), 2) & "d.wav"
    PBXScript.OutputTrace "gseSayDate, day=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDate = retVal
      TraceFunctionResult "gseSayDate", gseSayDate
      Exit Function
    End If
    ' Play month
    szSoundName = "datetime/" & AddLeadingZeros(CStr(nMonth), 2) & "t.wav"
    PBXScript.OutputTrace "gseSayDate, month=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDate = retVal
      TraceFunctionResult "gseSayDate", gseSayDate
      Exit Function
    End If
    ' Play year
    szSoundName = "datetime/" & CStr(nYear) & "y.wav"
    PBXScript.OutputTrace "gseSayDate, year=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDate = retVal
      TraceFunctionResult "gseSayDate", gseSayDate
      Exit Function
    End If
    fnResult = gseStatePlayed
  End If
 
  gseSayDate = fnResult
  TraceFunctionResult "gseSayDate", gseSayDate
End Function

Function gseSayDateEx(ByVal szDate, ByVal bPlayDOF, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, ByVal bSayTodayYesterday)
  AdjustBoolean bPlayDOF
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bSayTodayYesterday
  gseSayDateEx = gseSayDateEx2(szDate, bPlayDOF, fMask, bStoreToVariable, szVariableName, bResetVariableContent, bSayTodayYesterday)
End Function
''''''''''''''
'' Function:
''   gseSayDateEx2()
'' Description:
''   Reads out the date using multiple wav-files, not a Text-To-Speech module.
'' Date format:
''      [DOW.wav] XXd.wav YYt.wav ZZy.wav
'' Where:
''      DOW - Day of Week (Monday, Tuesday, ..., Sunday)
''      XX - Day (01-31)
''      YY - Month (01-12)
''      ZZ - Year (1990-2009)
'' Parameters:
''   [in] szDate - Time to read (Format: DD.MM.YYYY)
''   [in] bPlayDOF - If "True" play day of week
''   [in] fMask - DTMF detection mask
''   [in] bStoreToVariable - Store DTMF digit to variable or not
''   [in/out] szVariableName - MVariable to store
''   [in] bResetVariableContent - Reset variable content or not
''   [in] bSayTodayYesterday - If true pronounce "today" and "ysterday" if match
'' Return value:
''   gseStatePlayed - Played
''   gseStateDTMFKeyPressed - DTMF detected
''   gseStateFailed - Invalid parameter
''   gseStateDisconnected - Disconnect
Function gseSayDateEx2(ByVal szDate, ByVal bPlayDOF, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, ByVal bSayTodayYesterday)
  Dim fnResult, nDay, nMonth, nYear, retVal, szSoundName, nDOF, variantDate
  
  TraceFunction "gseSayDateEx2", szDate & ", " & fMask & ", " & bStoreToVariable & ", " & szVariableName & ", " & bResetVariableContent & ", " & bSayTodayYesterday

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If

  fnResult = gseStateFailed


  ' Split date
  If (IsDate(szDate)) Then
    variantDate = CDate(szDate)
    nDay = Day(variantDate)
    nMonth = Month(variantDate)
    nYear = Year(variantDate)
  Else
    ' a code to support old scripts...
    nDay = CIntEx(SplitString(szDate, "."))
    nMonth = CIntEx(SplitString(szDate, "."))
    nYear = CIntEx(SplitString(szDate, "."))
    variantDate = DateSerial(nYear, nMonth, nDay)
  End If


  If ((nDay < 1) Or (nDay > 31) Or (nMonth < 1) Or (nMonth > 12) Or (nYear < 1990) Or (nYear > 2009)) Then
    PBXScript.OutputTrace "gseSayDateEx2, error: invalid date format"
    retVal = gsePlaySound("datetime/WrongDate.wav", fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDateEx2 = retVal
      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
      Exit Function
    End If
  Else
    ' Chek if today/testerday
    If (bSayTodayYesterday = True) Then
      Dim dtNow, dtUser, diff
      dtNow = DateValue(PBXUser.Now)
      dtUser = DateSerial(nYear, nMonth, nDay)
      diff = DateDiff("d", dtUser, dtNow)

      If (diff = 0) Then
        szSoundName = "DateTime/today.wav"
      ElseIf (diff = 1) Then
        szSoundName = "DateTime/yesterday.wav"
      Else
        szSoundName = ""
      End if

      If (Len(szSoundName) > 0) Then
        PBXScript.OutputTrace "gseSayDateEx2, file=" & szSoundName
        retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
        gseSayDateEx2 = retVal
        PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
        Exit Function
      End If
    End If

    ' Play DOF
    If (bPlayDOF = True) Then
      nDOF = Weekday(variantDate)
      Select Case nDOF
        Case vbSunday
          szSoundName = "datetime/Sunday.wav"
        Case vbMonday
          szSoundName = "datetime/Monday.wav"
        Case vbTuesday
          szSoundName = "datetime/Tuesday.wav"
        Case vbWednesday
          szSoundName = "datetime/Wednesday.wav"
        Case vbThursday
          szSoundName = "datetime/Thursday.wav"
        Case vbFriday
          szSoundName = "datetime/Friday.wav"
        Case vbSaturday
          szSoundName = "datetime/Saturday.wav"
        Case Else
          ' this case will never be reached
          szSoundName = "datetime/WrongDate.wav"
      End Select
      PBXScript.OutputTrace "gseSayDateEx2, dof=" & szSoundName
      retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
      If (retVal <> gseStatePlayed) Then
        gseSayDateEx2 = retVal
        PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
        Exit Function
      End If
    End If
    
    'check if US date format
    If (PBXScript.InstallLanguageID = 1033) Then
	    ' Play month
	    szSoundName = "datetime/" & AddLeadingZeros(CStr(nMonth), 2) & "t.wav"
	    PBXScript.OutputTrace "gseSayDateEx2, month=" & szSoundName
	    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
	    If (retVal <> gseStatePlayed) Then
	      gseSayDateEx2 = retVal
	      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
	      Exit Function
	    End If
	    ' Play day
	    szSoundName = "datetime/" & AddLeadingZeros(CStr(nDay), 2) & "d.wav"
	    PBXScript.OutputTrace "gseSayDateEx2, day=" & szSoundName
	    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
	    If (retVal <> gseStatePlayed) Then
	      gseSayDateEx2 = retVal
	      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
	      Exit Function
	    End If
    Else
	    ' Play day
	    szSoundName = "datetime/" & AddLeadingZeros(CStr(nDay), 2) & "d.wav"
	    PBXScript.OutputTrace "gseSayDateEx2, day=" & szSoundName
	    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
	    If (retVal <> gseStatePlayed) Then
	      gseSayDateEx2 = retVal
	      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
	      Exit Function
	    End If
	    ' Play month
	    szSoundName = "datetime/" & AddLeadingZeros(CStr(nMonth), 2) & "t.wav"
	    PBXScript.OutputTrace "gseSayDateEx2, month=" & szSoundName
	    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
	    If (retVal <> gseStatePlayed) Then
	      gseSayDateEx2 = retVal
	      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
	      Exit Function
	    End If
    End If
    ' Play year
    szSoundName = "datetime/" & CStr(nYear) & "y.wav"
    PBXScript.OutputTrace "gseSayDateEx2, year=" & szSoundName
    retVal = gsePlaySound(szSoundName, fMask, bStoreToVariable, szVariableName, bResetVariableContent)
    If (retVal <> gseStatePlayed) Then
      gseSayDateEx2 = retVal
      PBXScript.OutputTrace "gseSayDateEx2 DTMF=[" & szVariableName & "]: Leave block with output DTMFKeyPressed"
      Exit Function
    End If
    fnResult = gseStatePlayed
  End If
 
  gseSayDateEx2 = fnResult
  TraceFunctionResult "gseSayDateEx2", gseSayDateEx2
End Function


'' ***************************************** IMAP4 Functions ******************************************
''''''''''''''
'' rConnectionID is an array with following elements:
'' rConnectionID(1) - An Integer. "1" if connection established, "0" othrwise
'' rConnectionID(2) - IpPbxIMAP4.MailSession object
'' rConnectionID(3) - An Integer. "1" if mail set initialized, "0" othrwise
'' rConnectionID(4) - IMailMessageCollection object
'' rConnectionID(5) - Currentemail in mail set
'' rConnectionID(6) - Number of emails in mail set
'' rConnectionID(7)..rConnectionID(10) - Save attributes of last mail set
Dim nIsConnected, nMailSession, nHasMailSet, nMailSet, nCurMail, nTotalMails, nOnlyIpPbxFlag, nOnlyWithAttachementFlag, _
    nOnlyUnreadFlag, nOldestFirstFlag, nReserved1, nReserved2, nReserved3, nReserved4, nReserved5, nReserved6
nIsConnected              = 1
nMailSession              = 2
nHasMailSet               = 3
nMailSet                  = 4
nCurMail                  = 5
nTotalMails               = 6
nOnlyIpPbxFlag            = 7
nOnlyWithAttachementFlag  = 8
nOnlyUnreadFlag           = 9
nOldestFirstFlag          = 10
nReserved1                = 11
nReserved2                = 12
nReserved3                = 13
nReserved4                = 14
nReserved5                = 15
nReserved6                = 16


' IMAP4 Error constants (from IDL file)
Dim IpPbxMailErrorSuccess, IpPbxMailErrorInvalidState, IpPbxMailErrorMailAccess, IpPbxMailErrorInvalidParameter, IpPbxMailErrorNoFileAttached, _
    IpPbxMailErrorCreateFile, IpPbxMailErrorWriteFile, IpPbxMailErrorNoMailServer, IpPbxMailErrorLogin, IpPbxMailErrorTimeout, IpPbxMailErrorInternal
IpPbxMailErrorSuccess           = 0
IpPbxMailErrorInvalidState      = 1
IpPbxMailErrorMailAccess        = 2
IpPbxMailErrorInvalidParameter  = 3
IpPbxMailErrorNoFileAttached    = 4
IpPbxMailErrorCreateFile        = 5
IpPbxMailErrorWriteFile         = 6
IpPbxMailErrorNoMailServer      = 7
IpPbxMailErrorLogin             = 8
IpPbxMailErrorTimeout           = 9
IpPbxMailErrorInternal          = 1001


''''''''''''''
'' Sub:
''   gseIMAP4_Initialize()
'' Description:
''   Initialize rConnectionID. Must be called before using of rConnectionID.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
Sub gseIMAP4_Initialize(ByRef rConnectionID)
  TraceFunction "gseIMAP4_Initialize", ""
  rConnectionID(nIsConnected) = 0
  rConnectionID(nHasMailSet) = 0
  TraceSubResult "gseIMAP4_Initialize"
End Sub


' for 4.30 scripts
Function gseIMAP4_ConnectToServer(ByRef rConnectionID, ByVal szServerName, ByVal szUserName, ByVal szUserPassword, ByVal szMailFolder, ByVal bUseSSL)
  gseIMAP4_ConnectToServer = gseIMAP4_ConnectToServerEx(rConnectionID, szServerName, szUserName, _
      szUserPassword, True, szMailFolder, bUseSSL)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_ConnectToServer = gseStateDisconnected) Then
    gseIMAP4_ConnectToServer = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_ConnectToServerEx(ByRef rConnectionID, ByVal szServerName, ByVal szUserName, ByVal szUserPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL)
  Dim rTotalEmails, rRecentEmails
  rTotalEmails = ""
  rRecentEmails = ""
  gseIMAP4_ConnectToServerEx = gseIMAP4_ConnectToServerEx2(rConnectionID, szServerName, szUserName, szUserPassword, bPasswordEncoded, szMailFolder, bUseSSL, False, rTotalEmails, False, rRecentEmails)
End Function

Function gseIMAP4_ConnectToServerEx2(ByRef rConnectionID, ByVal szServerName, ByVal szUserName, ByVal szUserPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bStoreMailsCount, ByRef rTotalEmails, ByVal bStoreRecentCount, ByRef rRecentEmails)
  AdjustBoolean bPasswordEncoded
  AdjustBoolean bUseSSL
  AdjustBoolean bStoreMailsCount
  AdjustBoolean bStoreRecentCount
  gseIMAP4_ConnectToServerEx2 = gseIMAP4_ConnectToServerEx3(rConnectionID, szServerName, szUserName, szUserPassword, bPasswordEncoded, szMailFolder, bUseSSL, bStoreMailsCount, rTotalEmails, bStoreRecentCount, rRecentEmails)
End Function

''''''''''''''
'' Function:
''   gseIMAP4_ConnectToServerEx3()
'' Description:
''   Initiate connection to the mail server
'' Parameters:
''   [in/out] rConnectionID - Mail session object. Should be used in future to get information from server
''   [in] szServerName - DNS name of mail server or IP address
''   [in] szUserName - User name.
''   [in] szUserPassword - User password in encrypted form.
''   [in] bPasswordEncoded - if "False" use plain text password
''   [in] szMailFolder - Mail folder where IpPbx voicemails are stored. If not specified the "INBOX" folder
''          will be user by default
''   [in] bUseSSL - Use SSL ("True") or not ("False")
''   [in] bStoreMailsCount - if false then rTotalEmails will be ignored
''   [in/out] rTotalEmails - Total number of emails
''   [in] bStoreRecentCount - if false then rRecentEmails will be ignored
''   [in/out] rRecentEmails - Total number of recent emails
'' Return value:
''   gseStateIMAP4Success - Connection established sucessfully
''   gseStateIMAP4Error - Access to MailServer failed, e.g. bad parameters
Function gseIMAP4_ConnectToServerEx3(ByRef rConnectionID, ByVal szServerName, ByVal szUserName, ByVal szUserPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bStoreMailsCount, ByRef rTotalEmails, ByVal bStoreRecentCount, ByRef rRecentEmails)
  Dim retDummy, nUseSSL, retVal, fnResult

  TraceFunction "gseIMAP4_ConnectToServerEx3", szServerName & ", " & szUserName & ", " & "XXX" & ", " & bPasswordEncoded & ", " & szMailFolder & ", " & bUseSSL & ", " & bStoreMailsCount & ", " & rTotalEmails & ", " & bStoreRecentCount & ", " & rRecentEmails
  fnResult = gseStateIMAP4Error

  ' If mail session is already opened, close previous connection first
  If (rConnectionID(nIsConnected) <> 0) Then
    retDummy = gseIMAP4_CloseSession(rConnectionID)
  End If

  ' Reset "IsConnected" and "HasMailSet" flags
  rConnectionID(nIsConnected) = 0
  rConnectionID(nHasMailSet) = 0
  
  ' Initialize temporary folder if it is not yet initialized
  If (Len(g_szTmpVoicemailFolder) = 0) Then
    g_szTmpVoicemailFolder = PBXUser.DataFolder
    PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, g_szTmpVoicemailFolder = [" & g_szTmpVoicemailFolder & "]"
  End If

  ' Create mail session object
  set rConnectionID(nMailSession) = CreateObject("IpPbxIMAP4.MailSession")
  PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, MailSession object created"

  If (bUseSSL = True) Then
    nUseSSL = 1
  Else
    nUseSSL = 0
  End If

  ' Set mail server name and user atributes
  retVal = rConnectionID(nMailSession).SetMailServer(szServerName, nUseSSL, 1) 'IpPbxAuthMethodLogin = 1
  PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, SetMailServer: retVal = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
  
  
  'If password comes from variable, it was planned, that the variable would contain a plain text password. But the main usage of the possibility to enter the
  'password from a variable is to implement the Remote Inquiry via GSE action WITHOUT any additional manual changes. Therefore the Password come ENCRYPTED in a variable.
 
  'If (bPasswordEncoded = True) Then
    retVal = rConnectionID(nMailSession).SetAccountInformation(szUserName, szUserPassword)
    PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, SetAccountInformationCrypt: retVal = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
  'Else
  '  retVal = rConnectionID(nMailSession).SetAccountInformationPlain(szUserName, szUserPassword)
  '  PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx, SetAccountInformationPlain: retVal = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
  'End If

  ' Set IpPbx voicemail folder
  If (Len(szMailFolder) > 0) Then
    rConnectionID(nMailSession).ActiveMailFolder = szMailFolder
    retVal = rConnectionID(nMailSession).ActiveMailFolder
    PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, ActiveMailFolder: retVal = " & retVal
  End If

  ' Set folder for wav files downloading
  rConnectionID(nMailSession).AudioFileFolder = g_szTmpVoicemailFolder
  
  If (Not bCallConnected) Then
    PBXCall.Alerting
  End If
  
  ' Connect to server
  retVal = rConnectionID(nMailSession).Connect(0) ' IpPbxSessionFlagsBlock = 0
  PBXScript.OutputTrace "gseIMAP4_ConnectToServerEx3, Connect: retVal = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"

  If (retVal = IpPbxMailErrorSuccess) Then
    ' Connection established
    fnResult = gseStateIMAP4Success
    rConnectionID(nIsConnected) = 1

    If bStoreMailsCount <> False Then
      rTotalEmails = rConnectionID(nMailSession).TotalMails
      PBXScript.OutputTrace  "gseIMAP4_ConnectToServerEx3, rTotalEmails = " & rTotalEmails
    End If
    
    If bStoreRecentCount <> False Then    
      rRecentEmails = rConnectionID(nMailSession).TotalRecentMails
      PBXScript.OutputTrace  "gseIMAP4_ConnectToServerEx3, nRecentEmails = " & rRecentEmails
    End If

  Else
    ' Connection failed
    fnResult = gseStateIMAP4Error
  End If
  
  CheckIfCallIsDisconnected fnResult

  gseIMAP4_ConnectToServerEx3 = fnResult
  TraceFunctionResult "gseIMAP4_ConnectToServerEx3", gseIMAP4_ConnectToServerEx3
End Function


''''''''''''''
'' Function:
''   gseIMAP4_CloseSession()
'' Description:
''   Close mail session
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
'' Return value:
''   gseStateIMAP4Success - Connection closed successfully
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_CloseSession(ByRef rConnectionID)
  Dim retVal, fnResult

  TraceFunction "gseIMAP4_CloseSession", ""
  fnResult = gseStateIMAP4Error

  If (rConnectionID(nIsConnected) = 0) Then
    ' Mail session is already closed
    retVal = IpPbxMailErrorSuccess
    PBXScript.OutputTrace "gseIMAP4_CloseSession, Mail session is already closed"
  Else
    retVal = rConnectionID(nMailSession).Close(0) ' IpPbxSessionFlagsBlock = 0
    PBXScript.OutputTrace "gseIMAP4_CloseSession, Close: retVal = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
  End If

  If (retVal = IpPbxMailErrorSuccess) Then
    ' Session closed
    fnResult = gseStateIMAP4Success
    rConnectionID(nIsConnected) = 0
    rConnectionID(nHasMailSet) = 0
  Else
    ' Error
    fnResult = gseStateIMAP4Error
  End If
  
  gseIMAP4_CloseSession = fnResult
  TraceFunctionResult "gseIMAP4_CloseSession", gseIMAP4_CloseSession
End Function


''''''''''''''
'' Function:
''   gseIMAP4_GetMails()
'' Description:
''   Set current set of emails using defined conditions
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bOnlyIpPbx - Only emails from IpPbx (Voicemails)
''   [in] bOnlyWithAttachement - Only emails with attached file
''   [in] bOnlyUnread - Only emails marked as unread
''   [in] bOldestFirst - Sort list in "oldest first order"
''   [out] rVariableNumberOfMails - Variable to store number of emails
'' Return value:
''   gseStateIMAP4Success - Number of emails is stored to a variable
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_GetMails(ByRef rConnectionID, ByVal bOnlyIpPbx, ByVal bOnlyWithAttachement, ByVal bOnlyUnread, ByVal bOldestFirst, ByRef rVariableNumberOfMails)
  gseIMAP4_GetMails = gseIMAP4_GetMailsEx(rConnectionID, bOnlyIpPbx, bOnlyWithAttachement, bOnlyUnread, bOldestFirst, rVariableNumberOfMails)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_GetMails = gseStateDisconnected) Then
    gseIMAP4_GetMails = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_GetMailsEx(ByRef rConnectionID, ByVal bOnlyIpPbx, ByVal bOnlyWithAttachement, ByVal bOnlyUnread, ByVal bOldestFirst, ByRef rVariableNumberOfMails)
  gseIMAP4_GetMailsEx = gseIMAP4_GetMailsEx2(rConnectionID, bOnlyIpPbx, bOnlyWithAttachement, bOnlyUnread, bOldestFirst, rVariableNumberOfMails, "", "", "")
End Function

Function gseIMAP4_GetMailsEx2(ByRef rConnectionID, ByVal bOnlyIpPbx, ByVal bOnlyWithAttachement, ByVal bOnlyUnread, ByVal bOldestFirst, ByRef rVariableNumberOfMails, ByVal nNotOlder, ByVal nNotNewer, ByVal strOnlyFrom)
  AdjustBoolean bOnlyIpPbx
  AdjustBoolean bOnlyWithAttachement
  AdjustBoolean bOnlyUnread
  AdjustBoolean bOldestFirst
  gseIMAP4_GetMailsEx2 = gseIMAP4_GetMailsEx3(rConnectionID, bOnlyIpPbx, bOnlyWithAttachement, bOnlyUnread, bOldestFirst, rVariableNumberOfMails, nNotOlder, nNotNewer, strOnlyFrom)
End Function

Function gseIMAP4_GetMailsEx3(ByRef rConnectionID, ByVal bOnlyIpPbx, ByVal bOnlyWithAttachement, ByVal bOnlyUnread, ByVal bOldestFirst, ByRef rVariableNumberOfMails, ByVal nNotOlder, ByVal nNotNewer, ByVal strOnlyFrom)
  Dim fnResult, nOnlyIpPbx, nOnlyWithAttachement, nOnlyUnread, nOldestFirst

  TraceFunction "gseIMAP4_GetMailsEx3", bOnlyIpPbx & ", " & bOnlyWithAttachement & ", " & bOnlyUnread & ", " & bOldestFirst & ", " & rVariableNumberOfMails & ", " & nNotOlder & ", " & nNotNewer & ", " & strOnlyFrom
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailsEx3, error: connection is not established so far"
  Else
    rConnectionID(nHasMailSet) = 0
    If (bOnlyIpPbx = True) Then
      nOnlyIpPbx = 1
    Else
      nOnlyIpPbx = 0
    End If
    If (bOnlyWithAttachement = True) Then
      nOnlyWithAttachement = 1
    Else
      nOnlyWithAttachement = 0
    End If
    If (bOnlyUnread = True) Then
      nOnlyUnread = 1
    Else
      nOnlyUnread = 0
    End If
    If (bOldestFirst = True) Then
      nOldestFirst = 1
    Else
      nOldestFirst = 0
    End If
    
	If (Len(nNotOlder) = 0) Then
		nNotOlder = CInt("-1")
	Else
		nNotOlder = CInt(nNotOlder)
	End If

	If (Len(nNotNewer) = 0) Then
		nNotNewer = CInt("-1")
	Else
		nNotNewer = CInt(nNotNewer)
	End If
    
    Set rConnectionID(nMailSet) = rConnectionID(nMailSession).GetMessagesEx(nOnlyIpPbx, nOnlyWithAttachement, nOnlyUnread, nOldestFirst, nNotOlder, nNotNewer, strOnlyFrom)
    rVariableNumberOfMails = CStr(rConnectionID(nMailSet).Count)
    rConnectionID(nCurMail) = 0 ' set first mail as current
    rConnectionID(nTotalMails) = CIntEx(rVariableNumberOfMails) ' set total number of mails
    rConnectionID(nOnlyIpPbxFlag) = nOnlyIpPbx
    rConnectionID(nOnlyWithAttachementFlag) = nOnlyWithAttachement
    rConnectionID(nOnlyUnreadFlag) = nOnlyUnread
    rConnectionID(nOldestFirstFlag) = nOldestFirst
    PBXScript.OutputTrace "gseIMAP4_GetMailsEx3(" &  nOnlyIpPbx & ", " &  nOnlyWithAttachement & ", " &  nOnlyUnread & ", " &  nOldestFirst & ", " & nNotOlder & ", " & nNotNewer & ", " & strOnlyFrom & "), Total = " & rVariableNumberOfMails
    rConnectionID(nHasMailSet) = 1
    fnResult = gseStateIMAP4Success
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_GetMailsEx3 = fnResult
  TraceFunctionResult "gseIMAP4_GetMailsEx3", gseIMAP4_GetMailsEx3
End Function


''''''''''''''
'' Function:
''   gseIMAP4_SeekMail()
'' Description:
''   Seek email: First / Previous / Next / Last
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] nAction - Action: First (0), Previous (1), Next (2), Last (3)
'' Return value:
''   gseStateIMAP4Success - Action Completed.
''   gseStateIMAP4Failed - Condition could not be reached, e.g. user tries to get next email when pointer already located on last email.
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_SeekMail(ByRef rConnectionID, ByVal nAction)
  gseIMAP4_SeekMail = gseIMAP4_SeekMailEx(rConnectionID, nAction)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_SeekMail = gseStateDisconnected) Then
    gseIMAP4_SeekMail = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_SeekMailEx(ByRef rConnectionID, ByVal nAction)
  Dim fnResult

  TraceFunction "gseIMAP4_SeekMailEx", nAction
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SeekMailEx, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SeekMailEx, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_SeekMailEx, warning: email set is empty"
    fnResult = gseStateIMAP4Failed
  Else
    fnResult = gseStateIMAP4Failed
    Select Case nAction
      Case "0"
        ' Find First
        If (rConnectionID(nTotalMails) > 0) Then
          rConnectionID(nCurMail) = 0
          fnResult = gseStateIMAP4Success
        End If
      Case "1"
        ' Find Previous
        If ((rConnectionID(nTotalMails) > 0) And (rConnectionID(nCurMail) > 0)) Then
          rConnectionID(nCurMail) = rConnectionID(nCurMail) - 1
          fnResult = gseStateIMAP4Success
        End If
      Case "2"
        ' Find Next
        If ((rConnectionID(nTotalMails) > 0) And (CIntEx(rConnectionID(nCurMail) + 1) < rConnectionID(nTotalMails))) Then
          rConnectionID(nCurMail) = rConnectionID(nCurMail) + 1
          fnResult = gseStateIMAP4Success
        End If
      Case "3"
        ' Find Last
        If (rConnectionID(nTotalMails) > 0) Then
          rConnectionID(nCurMail) = rConnectionID(nTotalMails) - 1
          fnResult = gseStateIMAP4Success
        End If
      Case Else
        ' Incorrect parameter
        PBXScript.OutputTrace "gseIMAP4_SeekMailEx, error: incorrect parameter"
        gseIMAP4_SeekMailEx = gseStateIMAP4Failed
        TraceFunctionResult "gseIMAP4_SeekMailEx", gseIMAP4_SeekMailEx
        Exit Function
    End Select
    If (fnResult = gseStateIMAP4Success) Then
      PBXScript.OutputTrace "gseIMAP4_SeekMailEx, success: current mail: " & CStr(rConnectionID(nCurMail) + 1) & "/" & rConnectionID(nTotalMails)
    Else
      PBXScript.OutputTrace "gseIMAP4_SeekMailEx, failed: out of range reached"
    End If
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_SeekMailEx = fnResult
  TraceFunctionResult "gseIMAP4_SeekMailEx", gseIMAP4_SeekMailEx
End Function


''''''''''''''
'' Function:
''   gseIMAP4_IsFirstMail()
'' Description:
''   Check if this is first email or not.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
'' Return value:
''   gseStateIMAP4True - Condition is True
''   gseStateIMAP4False - Condition is False
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_IsFirstMail(ByRef rConnectionID)
  gseIMAP4_IsFirstMail = gseIMAP4_IsFirstMailEx(rConnectionID)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_IsFirstMail = gseStateDisconnected) Then
    gseIMAP4_IsFirstMail = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_IsFirstMailEx(ByRef rConnectionID)
  Dim fnResult

  TraceFunction "gseIMAP4_IsFirstMailEx", ""
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_IsFirstMailEx, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_IsFirstMailEx, warning: email set is not defined yet"
    fnResult = gseStateIMAP4False
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_IsFirstMailEx, warning: email set is empty"
    fnResult = gseStateIMAP4False
  Else
    If (rConnectionID(nCurMail) = 0) Then
      fnResult = gseStateIMAP4True
      PBXScript.OutputTrace "gseIMAP4_IsFirstMailEx, result: True"
    Else
      fnResult = gseStateIMAP4False
      PBXScript.OutputTrace "gseIMAP4_IsFirstMailEx, result: False"
    End If
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_IsFirstMailEx = fnResult
  TraceFunctionResult "gseIMAP4_IsFirstMailEx", gseIMAP4_IsFirstMailEx
End Function


''''''''''''''
'' Function:
''   gseIMAP4_IsLastMail()
'' Description:
''   Check if this is last email or not.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
'' Return value:
''   gseStateIMAP4True - Condition is True
''   gseStateIMAP4False - Condition is False
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_IsLastMail(ByRef rConnectionID)
  gseIMAP4_IsLastMail = gseIMAP4_IsLastMailEx(rConnectionID)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_IsLastMail = gseStateDisconnected) Then
    gseIMAP4_IsLastMail = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_IsLastMailEx(ByRef rConnectionID)
  Dim fnResult

  TraceFunction "gseIMAP4_IsLastMailEx", ""
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_IsLastMailEx, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_IsLastMailEx, warning: email set is not defined yet"
    fnResult = gseStateIMAP4False
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_IsLastMailEx, warning: email set is empty"
    fnResult = gseStateIMAP4False
  Else
    If (rConnectionID(nCurMail) = rConnectionID(nTotalMails) - 1) Then
      fnResult = gseStateIMAP4True
      PBXScript.OutputTrace "gseIMAP4_IsLastMailEx, result: True"
    Else
      fnResult = gseStateIMAP4False
      PBXScript.OutputTrace "gseIMAP4_IsLastMailEx, result: False"
    End If
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_IsLastMailEx = fnResult
  TraceFunctionResult "gseIMAP4_IsLastMailEx", gseIMAP4_IsLastMailEx
End Function


''''''''''''''
'' Function:
''   gseIMAP4_GetMailAtributes()
'' Description:
''   Save chosen mail attributes to variables
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bSaveDate                 - If "True" save Date to variable.
''   [out] rVariableDate            - Variable to store Date
''   [in] bSaveTime                 - If "True" save Time to variable.
''   [out] rVariableTime            - Variable to store Time
''   [in] bSaveCallerNumber         - If "True" save Caller ID to variable.
''   [out] rVariableCallerNumber    - Variable to store Caller ID.
''   [in] bSaveCallerName           - If "True" save Caller Name to variable.
''   [out] rVariableCallerName      - Variable to store Caller Name
''   [in] bSaveIsVoicemail          - If "True" save is this mail is voicemail or not to variable.
''   [out] rVariableIsVoicemail     - Variable to store is this mail is voicemail or not ("1"/"0").
''   [in] bSaveVoicemailLength      - If "True" save length of attachment to variable.
''   [out] rVariableVoicemailLength - Variable to store length of attachment in seconds.
''   [in] bSaveProcessedFlag        - If "True" save is this mail read or unread to variable.
''   [out] rVariableProcessedFlag   - Variable to store if mail is read ("1") or unread ("0").
'' Return value:
''   gseStateIMAP4Success - Attributes saved successfully
''   gseStateIMAP4Failed - Attributes could not be saved because email set is not defined
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_GetMailAtributes(ByRef rConnectionID, bSaveDate, ByRef rVariableDate, ByVal bSaveTime, ByRef rVariableTime, ByVal bSaveCallerNumber, _
                                   ByRef rVariableCallerNumber, ByVal bSaveCallerName, ByRef rVariableCallerName, ByVal bSaveIsVoicemail, _
                                   ByRef rVariableIsVoicemail, ByVal bSaveVoicemailLength, ByRef rVariableVoicemailLength, ByVal bSaveProcessedFlag, _
                                   ByRef rVariableProcessedFlag)
  Dim fnResult, szTraceStr, nTotalLength, nSeconds, nMinutes, nHours, pCurrentMail
  
  AdjustBoolean bSaveDate
  AdjustBoolean bSaveTime
  AdjustBoolean bSaveCallerNumber
  AdjustBoolean bSaveCallerName
  AdjustBoolean bSaveIsVoicemail
  AdjustBoolean bSaveVoicemailLength
  AdjustBoolean bSaveProcessedFlag
  
  TraceFunction "gseIMAP4_GetMailAtributes", bSaveDate & ", " & rVariableDate & ", " & bSaveTime & ", " & rVariableTime & ", " & bSaveCallerNumber & ", " & _
                                   rVariableCallerNumber & ", " & bSaveCallerName & ", " & rVariableCallerName & ", " & bSaveIsVoicemail & ", " & _
                                   rVariableIsVoicemail & ", " & bSaveVoicemailLength & ", " & rVariableVoicemailLength & ", " & bSaveProcessedFlag & ", " & _
                                   rVariableProcessedFlag
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributes, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributes, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributes, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    szTraceStr = "Atributes:"
    Set pCurrentMail = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail)))
    
    If (bSaveDate = True) Then
      rVariableDate = AddLeadingZeros(pCurrentMail.ReceivedDay, 2) & "." & AddLeadingZeros(pCurrentMail.ReceivedMonth, 2) & "." & AddLeadingZeros(pCurrentMail.ReceivedYear, 4)
      szTraceStr = szTraceStr & vbLF & "Date: " & rVariableDate
    End If
    If (bSaveTime = True) Then
      rVariableTime = AddLeadingZeros(pCurrentMail.ReceivedHour, 2) & ":" & AddLeadingZeros(pCurrentMail.ReceivedMinute, 2) & ":" & AddLeadingZeros(pCurrentMail.ReceivedSecond, 2)
      szTraceStr = szTraceStr & vbLF & "Time: " & rVariableTime
    End If
    If (bSaveCallerNumber = True) Then
      rVariableCallerNumber = CStr(pCurrentMail.CallingPartyNumber)
      szTraceStr = szTraceStr & vbLF & "CallerNumber: [" & rVariableCallerNumber & "]"
    End If
    If (bSaveCallerName = True) Then
      rVariableCallerName = pCurrentMail.CallingUsername
      szTraceStr = szTraceStr & vbLF & "CallerName: [" & rVariableCallerName & "]"
    End If
    If (bSaveIsVoicemail = True) Then
      If (pCurrentMail.MessageVoicemail = 1) Then
        rVariableIsVoicemail = "1"
      Else
        rVariableIsVoicemail = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "IsVoicemail: " & rVariableIsVoicemail
    End If
    If (bSaveVoicemailLength = True) Then
      nTotalLength = CIntEx(pCurrentMail.AudioAttachmentLength)
      nSeconds = nTotalLength mod 60
      nMinutes = CIntEx(nTotalLength/60) mod 60
      nHours = CIntEx(nTotalLength/3600)
      rVariableVoicemailLength = AddLeadingZeros(nHours, 2) & ":" & AddLeadingZeros(nMinutes, 2) & ":" & AddLeadingZeros(nSeconds, 2)
      szTraceStr = szTraceStr & vbLF & "VoicemailLength: " & rVariableVoicemailLength
    End If
    If (bSaveProcessedFlag = True) Then
      If (pCurrentMail.MessageProcessed = 1) Then
        rVariableProcessedFlag = "1"
      Else
        rVariableProcessedFlag = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "IsProcessed: " & rVariableProcessedFlag
    End If

    PBXScript.OutputTrace "gseIMAP4_GetMailAtributes, " & szTraceStr
    fnResult = gseStateIMAP4Success
  End If
  
  gseIMAP4_GetMailAtributes = fnResult
  TraceFunctionResult "gseIMAP4_GetMailAtributes", gseIMAP4_GetMailAtributes
End Function


' GSE 4.1.0.51
''''''''''''''
'' Function:
''   gseIMAP4_GetMailAtributesEx()
'' Description:
''   Save chosen mail attributes to variables
''   support "has TEXT/HTML" and "has TEXT/PLAIN"
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bSaveDate                 - If "True" save Date to variable.
''   [out] rVariableDate            - Variable to store Date
''   [in] bSaveTime                 - If "True" save Time to variable.
''   [out] rVariableTime            - Variable to store Time
''   [in] bSaveCallerNumber         - If "True" save Caller ID to variable.
''   [out] rVariableCallerNumber    - Variable to store Caller ID.
''   [in] bSaveCallerName           - If "True" save Caller Name to variable.
''   [out] rVariableCallerName      - Variable to store Caller Name
''   [in] bSaveIsVoicemail          - If "True" save is this mail is voicemail or not to variable.
''   [out] rVariableIsVoicemail     - Variable to store is this mail is voicemail or not ("1"/"0").
''   [in] bSaveVoicemailLength      - If "True" save length of attachment to variable.
''   [out] rVariableVoicemailLength - Variable to store length of attachment in seconds.
''   [in] bSaveProcessedFlag        - If "True" save is this mail read or unread to variable.
''   [out] rVariableProcessedFlag   - Variable to store if mail is read ("1") or unread ("0").
''   [in] bSaveHasHTMLBody          - If "True" save "has TEXT/HTML" to variable.
''   [out] rVariableHasHTMLBody     - Variable to store "has TEXT/HTML" ("1") or ("0").
''   [in] bSaveHasPLAINBody         - If "True" save "has TEXT/PLAIN" to variable.
''   [out] rVariableHasPLAINBody    - Variable to store "has TEXT/PLAIN" ("1") or ("0").
'' Return value:
''   gseStateIMAP4Success - Attributes saved successfully
''   gseStateIMAP4Failed - Attributes could not be saved because email set is not defined
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_GetMailAtributesEx(ByRef rConnectionID, ByVal bSaveDate, ByRef rVariableDate, ByVal bSaveTime, ByRef rVariableTime, ByVal bSaveCallerNumber, _
                                   ByRef rVariableCallerNumber, ByVal bSaveCallerName, ByRef rVariableCallerName, ByVal bSaveIsVoicemail, _
                                   ByRef rVariableIsVoicemail, ByVal bSaveVoicemailLength, ByRef rVariableVoicemailLength, ByVal bSaveProcessedFlag, _
                                   ByRef rVariableProcessedFlag, _
                                   ByVal bSaveHasHTMLBody, ByRef rVariableHasHTMLBody, _
                                   ByVal bSaveHasPLAINBody, ByRef rVariableHasPLAINBody)
  gseIMAP4_GetMailAtributesEx = gseIMAP4_GetMailAtributesEx2(rConnectionID, bSaveDate, rVariableDate, bSaveTime, rVariableTime, bSaveCallerNumber, _
                                   rVariableCallerNumber, bSaveCallerName, rVariableCallerName, bSaveIsVoicemail, _
                                   rVariableIsVoicemail, bSaveVoicemailLength, rVariableVoicemailLength, bSaveProcessedFlag, _
                                   rVariableProcessedFlag, _
                                   bSaveHasHTMLBody, rVariableHasHTMLBody, _
                                   bSaveHasPLAINBody, rVariableHasPLAINBody)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_GetMailAtributesEx = gseStateDisconnected) Then
    gseIMAP4_GetMailAtributesEx = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_GetMailAtributesEx2(ByRef rConnectionID, ByVal bSaveDate, ByRef rVariableDate, ByVal bSaveTime, ByRef rVariableTime, ByVal bSaveCallerNumber, _
                                   ByRef rVariableCallerNumber, ByVal bSaveCallerName, ByRef rVariableCallerName, ByVal bSaveIsVoicemail, _
                                   ByRef rVariableIsVoicemail, ByVal bSaveVoicemailLength, ByRef rVariableVoicemailLength, ByVal bSaveProcessedFlag, _
                                   ByRef rVariableProcessedFlag, _
                                   ByVal bSaveHasHTMLBody, ByRef rVariableHasHTMLBody, _
                                   ByVal bSaveHasPLAINBody, ByRef rVariableHasPLAINBody)
  AdjustBoolean bSaveDate
  AdjustBoolean bSaveTime
  AdjustBoolean bSaveCallerNumber
  AdjustBoolean bSaveCallerName
  AdjustBoolean bSaveIsVoicemail
  AdjustBoolean bSaveVoicemailLength
  AdjustBoolean bSaveProcessedFlag
  AdjustBoolean bSaveHasHTMLBody
  AdjustBoolean bSaveHasPLAINBody
  
  gseIMAP4_GetMailAtributesEx2 = gseIMAP4_GetMailAtributesEx3(rConnectionID, bSaveDate, rVariableDate, bSaveTime, rVariableTime, bSaveCallerNumber, _
                                   rVariableCallerNumber, bSaveCallerName, rVariableCallerName, bSaveIsVoicemail, _
                                   rVariableIsVoicemail, bSaveVoicemailLength, rVariableVoicemailLength, bSaveProcessedFlag, _
                                   rVariableProcessedFlag, _
                                   bSaveHasHTMLBody, rVariableHasHTMLBody, _
                                   bSaveHasPLAINBody, rVariableHasPLAINBody)
End Function

Function gseIMAP4_GetMailAtributesEx3(ByRef rConnectionID, ByVal bSaveDate, ByRef rVariableDate, ByVal bSaveTime, ByRef rVariableTime, ByVal bSaveCallerNumber, _
                                   ByRef rVariableCallerNumber, ByVal bSaveCallerName, ByRef rVariableCallerName, ByVal bSaveIsVoicemail, _
                                   ByRef rVariableIsVoicemail, ByVal bSaveVoicemailLength, ByRef rVariableVoicemailLength, ByVal bSaveProcessedFlag, _
                                   ByRef rVariableProcessedFlag, _
                                   ByVal bSaveHasHTMLBody, ByRef rVariableHasHTMLBody, _
                                   ByVal bSaveHasPLAINBody, ByRef rVariableHasPLAINBody)
  Dim fnResult, szTraceStr, nTotalLength, nSeconds, nMinutes, nHours, pCurrentMail
  Dim szBody, rc
  
  TraceFunction "gseIMAP4_GetMailAtributesEx3", bSaveDate & ", " & rVariableDate & ", " & bSaveTime & ", " & rVariableTime & ", " & bSaveCallerNumber & ", " & _
                                   rVariableCallerNumber & ", " & bSaveCallerName & ", " & rVariableCallerName & ", " & bSaveIsVoicemail & ", " & _
                                   rVariableIsVoicemail & ", " & bSaveVoicemailLength & ", " & rVariableVoicemailLength & ", " & bSaveProcessedFlag & ", " & _
                                   rVariableProcessedFlag & ", " & bSaveHasHTMLBody & ", " & rVariableHasHTMLBody & ", " & _
                                   rVariableHasPLAINBody & ", " & rVariableHasPLAINBody
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributesEx3, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributesEx3, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailAtributesEx3, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    szTraceStr = "Atributes:"
    Set pCurrentMail = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail)))
    
    If (bSaveDate = True) Then
      'rVariableDate = AddLeadingZeros(pCurrentMail.ReceivedDay, 2) & "." & AddLeadingZeros(pCurrentMail.ReceivedMonth, 2) & "." & AddLeadingZeros(pCurrentMail.ReceivedYear, 4)
      rVariableDate = DateSerial(pCurrentMail.ReceivedYear, pCurrentMail.ReceivedMonth, pCurrentMail.ReceivedDay)
      szTraceStr = szTraceStr & vbLF & "Date: " & rVariableDate
    End If
    If (bSaveTime = True) Then
      'rVariableTime = AddLeadingZeros(pCurrentMail.ReceivedHour, 2) & ":" & AddLeadingZeros(pCurrentMail.ReceivedMinute, 2) & ":" & AddLeadingZeros(pCurrentMail.ReceivedSecond, 2)
      rVariableTime = TimeSerial(pCurrentMail.ReceivedHour, pCurrentMail.ReceivedMinute, pCurrentMail.ReceivedSecond)
      szTraceStr = szTraceStr & vbLF & "Time: " & rVariableTime
    End If
    If (bSaveCallerNumber = True) Then
      rVariableCallerNumber = CStr(pCurrentMail.CallingPartyNumber)
      szTraceStr = szTraceStr & vbLF & "CallerNumber: [" & rVariableCallerNumber & "]"
    End If
    If (bSaveCallerName = True) Then
      rVariableCallerName = pCurrentMail.CallingUsername
      szTraceStr = szTraceStr & vbLF & "CallerName: [" & rVariableCallerName & "]"
    End If
    If (bSaveIsVoicemail = True) Then
      If (pCurrentMail.MessageVoicemail = 1) Then
        rVariableIsVoicemail = "1"
      Else
        rVariableIsVoicemail = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "IsVoicemail: " & rVariableIsVoicemail
    End If
    If (bSaveVoicemailLength = True) Then
      nTotalLength = CIntEx(pCurrentMail.AudioAttachmentLength)
      nSeconds = nTotalLength mod 60
      nMinutes = CIntEx(nTotalLength/60) mod 60
      nHours = CIntEx(nTotalLength/3600)
      rVariableVoicemailLength = AddLeadingZeros(nHours, 2) & ":" & AddLeadingZeros(nMinutes, 2) & ":" & AddLeadingZeros(nSeconds, 2)
      szTraceStr = szTraceStr & vbLF & "VoicemailLength: " & rVariableVoicemailLength
    End If
    If (bSaveProcessedFlag = True) Then
      If (pCurrentMail.MessageProcessed = 1) Then
        rVariableProcessedFlag = "1"
      Else
        rVariableProcessedFlag = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "IsProcessed: " & rVariableProcessedFlag
    End If
    ' 4.20
    If (bSaveHasHTMLBody = True) Then
      szBody = ""
      rc = pCurrentMail.GetBody(1, szBody)
      If (Len(szBody) > 0) Then
        rVariableHasHTMLBody = "1"
      Else
        rVariableHasHTMLBody = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "Has TEXT/HTML body: " & rVariableHasHTMLBody
    End If
    If (bSaveHasPLAINBody = True) Then
      szBody = ""
      rc = pCurrentMail.GetBody(0, szBody)
      If (Len(szBody) > 0) Then
        rVariableHasPLAINBody = "1"
      Else
        rVariableHasPLAINBody = "0"
      End If
      szTraceStr = szTraceStr & vbLF & "Has TEXT/PLAIN body: " & rVariableHasPLAINBody
    End If

    PBXScript.OutputTrace "gseIMAP4_GetMailAtributesEx3, " & szTraceStr
    fnResult = gseStateIMAP4Success
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_GetMailAtributesEx3 = fnResult
  TraceFunctionResult "gseIMAP4_GetMailAtributesEx3", gseIMAP4_GetMailAtributesEx3
End Function


' GSE 4.1.0.51
''''''''''''''
'' Function:
''   gseIMAP4_GetMail()
'' Description:
''   Get email FRMO, TO, CC, HEADER, BODY
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bSaveFrom                 - If "True" save FROM to variable.
''   [out] rVariableFrom            - Variable to store FROM
''   [in] bSaveTo                   - If "True" save TO to variable.
''   [out] rVariableTo              - Variable to store TO
''   [in] bSaveCc                   - If "True" save CC to variable.
''   [out] rVariableCc              - Variable to store CC.
''   [in] bSaveSubject              - If "True" save SUBJECT to variable.
''   [out] rVariableSubject         - Variable to store SUBJECT
''   [in] bSaveHTMLBody             - If "True" save TEXT/HTML body to variable.
''   [out] rVariableHTMLBody        - Variable to store TEXT/HTML body.
''   [in] bSavePLAINBody            - If "True" save TEXT/PLAIN body to variable.
''   [out] rVariablePLAINBody       - Variable to store TEXT/PLAIN body.
'' Return value:
''   gseStateIMAP4Success - all saved successfully
''   gseStateIMAP4Failed - Attributes could not be saved because email set is not defined
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_GetMail(ByRef rConnectionID, _
                           ByVal bSaveFrom, ByRef rVariableFrom, ByVal bSaveTo, ByRef rVariableTo, _
                           ByVal bSaveCc, ByRef rVariableCc, ByVal bSaveSubject, ByRef rVariableSubject, _
                           ByVal bSaveHTMLBody, ByRef rVariableHTMLBody, _
                           ByVal bSavePLAINBody, ByRef rVariablePLAINBody)
  gseIMAP4_GetMail = gseIMAP4_GetMailEx(rConnectionID, _
                           bSaveFrom, rVariableFrom, bSaveTo, rVariableTo, _
                           bSaveCc, rVariableCc, bSaveSubject, rVariableSubject, _
                           bSaveHTMLBody, rVariableHTMLBody, _
                           bSavePLAINBody, rVariablePLAINBody)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_GetMail = gseStateDisconnected) Then
    gseIMAP4_GetMail = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_GetMailEx(ByRef rConnectionID, _
                           ByVal bSaveFrom, ByRef rVariableFrom, ByVal bSaveTo, ByRef rVariableTo, _
                           ByVal bSaveCc, ByRef rVariableCc, ByVal bSaveSubject, ByRef rVariableSubject, _
                           ByVal bSaveHTMLBody, ByRef rVariableHTMLBody, _
                           ByVal bSavePLAINBody, ByRef rVariablePLAINBody)
                           
  AdjustBoolean bSaveFrom
  AdjustBoolean bSaveTo
  AdjustBoolean bSaveCc
  AdjustBoolean bSaveSubject
  AdjustBoolean bSaveHTMLBody
  AdjustBoolean bSavePLAINBody
  
  gseIMAP4_GetMailEx = gseIMAP4_GetMailEx2(rConnectionID, _
                           bSaveFrom, rVariableFrom, bSaveTo, rVariableTo, _
                           bSaveCc, rVariableCc, bSaveSubject, rVariableSubject, _
                           bSaveHTMLBody, rVariableHTMLBody, _
                           bSavePLAINBody, rVariablePLAINBody)
End Function

Function gseIMAP4_GetMailEx2(ByRef rConnectionID, _
                           ByVal bSaveFrom, ByRef rVariableFrom, ByVal bSaveTo, ByRef rVariableTo, _
                           ByVal bSaveCc, ByRef rVariableCc, ByVal bSaveSubject, ByRef rVariableSubject, _
                           ByVal bSaveHTMLBody, ByRef rVariableHTMLBody, _
                           ByVal bSavePLAINBody, ByRef rVariablePLAINBody)
  Dim fnResult, szTraceStr, pCurrentMail
  Dim rc
  
  TraceFunction "gseIMAP4_GetMailEx2", bSaveFrom & ", " & _
                                    bSaveTo & ", " & _
                                    bSaveCc & ", " & _
                                    bSaveSubject & ", " & _
                                    bSaveHTMLBody & ", " & _
                                    bSavePLAINBody
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailEx2, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailEx2, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_GetMailEx2, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    szTraceStr = "Mail data:"
    Set pCurrentMail = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail)))
    
    If (bSaveFrom = True) Then
      rVariableFrom = pCurrentMail.From
      szTraceStr = szTraceStr & vbLF & "FROM: " & rVariableFrom
    End If
    If (bSaveTo = True) Then
      rVariableTo = pCurrentMail.To
      szTraceStr = szTraceStr & vbLF & "TO: " & rVariableTo
    End If
    If (bSaveCc = True) Then
      rVariableCc = pCurrentMail.Cc
      szTraceStr = szTraceStr & vbLF & "CC: " & rVariableCc
    End If
    If (bSaveSubject = True) Then
      rVariableSubject = pCurrentMail.Subject
      szTraceStr = szTraceStr & vbLF & "SUBJECT: " & rVariableSubject
    End If

    If (bSaveHTMLBody = True) Then
      rVariableHTMLBody = ""
      rc = pCurrentMail.GetBody(1, rVariableHTMLBody)
      szTraceStr = szTraceStr & vbLF & "TEXT/HTML body length: " & Len(rVariableHTMLBody)
    End If
    If (bSavePLAINBody = True) Then
      rVariablePLAINBody = ""
      rc = pCurrentMail.GetBody(0, rVariablePLAINBody)
      szTraceStr = szTraceStr & vbLF & "TEXT/PLAIN body length: " & Len(rVariablePLAINBody)
    End If

    PBXScript.OutputTrace "gseIMAP4_GetMailEx2, " & szTraceStr
    fnResult = gseStateIMAP4Success
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_GetMailEx2 = fnResult
  TraceFunctionResult "gseIMAP4_GetMailEx2", gseIMAP4_GetMailEx2
End Function


''''''''''''''
'' Function:
''   gseIMAP4_DeleteMail()
'' Description:
''   Deletes the current mail.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
'' Return value:
''   gseStateIMAP4Success - Mail delete
''   gseStateIMAP4Failed - Current email could not be deleted. E.g. email set is empty or access to MailServer failed
Function gseIMAP4_DeleteMail(ByRef rConnectionID)
  gseIMAP4_DeleteMail = gseIMAP4_DeleteMailEx(rConnectionID)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_DeleteMail = gseStateDisconnected) Then
    gseIMAP4_DeleteMail = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_DeleteMailEx(ByRef rConnectionID)
  Dim fnResult, nCur, retVal

  TraceFunction "gseIMAP4_DeleteMailEx", ""
  fnResult = gseStateIMAP4Failed
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, warning: email set is empty"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail))).MessageDeleted = 1
    retVal = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail))).MessageDeleted
    If (retVal = 1) Then
      fnResult = gseStateIMAP4Success
      nCur = CIntEx(rConnectionID(nCurMail))
      Set rConnectionID(nMailSet) = rConnectionID(nMailSession).GetMessages(rConnectionID(nOnlyIpPbxFlag), rConnectionID(nOnlyWithAttachementFlag), rConnectionID(nOnlyUnreadFlag), rConnectionID(nOldestFirstFlag))
      rConnectionID(nTotalMails) = CIntEx(rConnectionID(nMailSet).Count)
      
      If (nCur >= rConnectionID(nTotalMails)) Then
        rConnectionID(nCurMail) = rConnectionID(nTotalMails) - 1
      Else
        rConnectionID(nCurMail) = nCur
      End If
      PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, Deleted sucessfully, current mail is " & CIntEx(rConnectionID(nCurMail) + 1) & "/" & rConnectionID(nTotalMails)
    Else
      fnResult = gseStateIMAP4Failed
      PBXScript.OutputTrace "gseIMAP4_DeleteMailEx, Deletion failed"
    End If
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_DeleteMailEx = fnResult
  TraceFunctionResult "gseIMAP4_DeleteMailEx", gseIMAP4_DeleteMailEx
End Function


''''''''''''''
'' Function:
''   gseIMAP4_SaveVoicemailToTmpFile()
'' Description:
''   Save attachment from current mail to temporary file. This file may be played in PlaySound block. 
''   In case if current email has not an attachment or emails set is empty, output "Failed" will activates.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
'' Return value:
''   gseStateIMAP4Success - Attachment is saved to a temporary file successfully
''   gseStateIMAP4Failed - Current email has not an attachment or emails set is empty
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_SaveVoicemailToTmpFile(ByRef rConnectionID)
  Dim fnResult, retVal, rFilename

  TraceFunction "gseIMAP4_SaveVoicemailToTmpFile", ""
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, warning: email set is empty"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    rFilename = ""
    retVal = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail))).GetAudioFile(rFilename)
    If (retVal = IpPbxMailErrorSuccess) Then
      If (rFilename = "") Then
        PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, File downloading fails, filename is empty"
        fnResult = gseStateIMAP4Failed
      Else
        PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, File downloaded sucessfully, filename [" & rFilename & "]"
        g_szLastDownloadedVoicemail = g_szTmpVoicemailFolder & "\" & rFilename
        fnResult = gseStateIMAP4Success
      End If
    Else
      PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFile, File downloading fails, reason = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
      fnResult = gseStateIMAP4Failed
    End If
  End If
  
  gseIMAP4_SaveVoicemailToTmpFile = fnResult
  TraceFunctionResult "gseIMAP4_SaveVoicemailToTmpFile", gseIMAP4_SaveVoicemailToTmpFile
End Function


' GSE 4.2.0.51
''''''''''''''
'' Function:
''   gseIMAP4_SaveVoicemailToTmpFileEx()
'' Description:
''   Save attachment from current mail to temporary file. This file may be played in PlaySound block. 
''   In case if current email has not an attachment or emails set is empty, output "Failed" will activates.
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bSaveTmpFileNameToVar   - need to save tmp file name or not
''   [out] rVarToSaveTmpFileName  - variable to save tmp file name
'' Return value:
''   gseStateIMAP4Success - Attachment is saved to a temporary file successfully
''   gseStateIMAP4Failed - Current email has not an attachment or emails set is empty
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_SaveVoicemailToTmpFileEx(ByRef rConnectionID, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName)
  gseIMAP4_SaveVoicemailToTmpFileEx = gseIMAP4_SaveVoicemailToTmpFileEx2(rConnectionID, bSaveTmpFileNameToVar, rVarToSaveTmpFileName)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_SaveVoicemailToTmpFileEx = gseStateDisconnected) Then
    gseIMAP4_SaveVoicemailToTmpFileEx = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_SaveVoicemailToTmpFileEx2(ByRef rConnectionID, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName)
  AdjustBoolean bSaveTmpFileNameToVar
  gseIMAP4_SaveVoicemailToTmpFileEx2 = gseIMAP4_SaveVoicemailToTmpFileEx3(rConnectionID, bSaveTmpFileNameToVar, rVarToSaveTmpFileName)
End Function

Function gseIMAP4_SaveVoicemailToTmpFileEx3(ByRef rConnectionID, ByVal bSaveTmpFileNameToVar, ByRef rVarToSaveTmpFileName)
  Dim fnResult, retVal, rFilename

  TraceFunction "gseIMAP4_SaveVoicemailToTmpFileEx3", bSaveTmpFileNameToVar & ", " & rVarToSaveTmpFileName
  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf (rConnectionID(nTotalMails) < 1) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, warning: email set is empty"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    rFilename = ""
    retVal = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail))).GetAudioFile(rFilename)
    If (retVal = IpPbxMailErrorSuccess) Then
      If (rFilename = "") Then
        PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, File downloading fails, filename is empty"
        fnResult = gseStateIMAP4Failed
      Else
        PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, File downloaded sucessfully, filename [" & rFilename & "]"
        g_szLastDownloadedVoicemail = g_szTmpVoicemailFolder & "\" & rFilename
        If (bSaveTmpFileNameToVar = True) Then
          rVarToSaveTmpFileName = g_szLastDownloadedVoicemail
        End If
        fnResult = gseStateIMAP4Success
      End If
    Else
      PBXScript.OutputTrace "gseIMAP4_SaveVoicemailToTmpFileEx3, File downloading fails, reason = " & retVal & " [" & ExtractIpPbxIMAP4RetVal(retVal) & "]"
      fnResult = gseStateIMAP4Failed
    End If
  End If
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_SaveVoicemailToTmpFileEx3 = fnResult
  TraceFunctionResult "gseIMAP4_SaveVoicemailToTmpFileEx3", gseIMAP4_SaveVoicemailToTmpFileEx3
End Function


''''''''''''''
'' Function:
''   gseIMAP4_SetMailAtributes()
'' Description:
''   Update email attributes
'' Parameters:
''   [in/out] rConnectionID - Mail session object.
''   [in] bChangeProcessedFlag - If "True" change the process flag.
''   [in] bNewProcessedFlag   - New state of process flag True(1) or False(0).
'' Return value:
''   gseStateIMAP4Success - Success
''   gseStateIMAP4Failed - Emails set is empty
''   gseStateIMAP4Error - Access to MailServer failed
Function gseIMAP4_SetMailAtributes(ByRef rConnectionID, ByVal bChangeProcessedFlag, ByVal bNewProcessedFlag)
  gseIMAP4_SetMailAtributes = gseIMAP4_SetMailAtributesEx(rConnectionID, bChangeProcessedFlag, bNewProcessedFlag)

  ' Support new 4.31 output "Disconnected"
  If (gseIMAP4_SetMailAtributes = gseStateDisconnected) Then
    gseIMAP4_SetMailAtributes = gseStateIMAP4Error
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateIMAP4Error"
  End If
End Function

Function gseIMAP4_SetMailAtributesEx(ByRef rConnectionID, ByVal bChangeProcessedFlag, ByVal szNewProcessedFlag)
  adjustBoolean bChangeProcessedFlag
  gseIMAP4_SetMailAtributesEx = gseIMAP4_SetMailAtributesEx2(rConnectionID, bChangeProcessedFlag, szNewProcessedFlag)
End Function

Function gseIMAP4_SetMailAtributesEx2(ByRef rConnectionID, ByVal bChangeProcessedFlag, ByVal szNewProcessedFlag)
  Dim fnResult, newVal, pCurrentMail

  TraceFunction "gseIMAP4_SetMailAtributesEx2", bChangeProcessedFlag & ", " & szNewProcessedFlag

  fnResult = gseStateIMAP4Error
  If (rConnectionID(nIsConnected) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SetMailAtributesEx2, error: connection is not established so far"
  ElseIf (rConnectionID(nHasMailSet) = 0) Then
    PBXScript.OutputTrace "gseIMAP4_SetMailAtributesEx2, warning: email set is not defined yet"
    fnResult = gseStateIMAP4Failed
  ElseIf ((rConnectionID(nCurMail) >= rConnectionID(nTotalMails)) Or (rConnectionID(nCurMail) < 0)) Then
    PBXScript.OutputTrace "gseIMAP4_SetMailAtributesEx2, warning: current email number is out of range"
    fnResult = gseStateIMAP4Failed
  Else
    Set pCurrentMail = rConnectionID(nMailSet).Item(CIntEx(rConnectionID(nCurMail)))
    If (bChangeProcessedFlag = True) Then
      newVal = 1
      If (szNewProcessedFlag = "1") Then
        newVal = 0
      End If
      pCurrentMail.MessageProcessed = newVal
    End If
    fnResult = gseStateIMAP4Success
  End If  
  
  CheckIfCallIsDisconnected fnResult
  gseIMAP4_SetMailAtributesEx2 = fnResult
  TraceFunctionResult "gseIMAP4_SetMailAtributesEx2", gseIMAP4_SetMailAtributesEx2
End Function


''''''''''''''
'' Function:
''   gseHold()
'' Description:
''   Put script into "Hold" state
'' Parameters:
''   [in] szSound - Sound file to be played while call on hold state
'' Return value:
''   gseStateOnHold - call successfuly becomes to Hold state (allways)
Function gseHold(ByVal szSound)
  gseHold = gseHoldEx(szSound)

  ' Support new 4.31 output "Disconnected"
  If (gseHold = gseStateDisconnected) Then
    gseHold = gseStateOnHold
    PBXScriptOutputTrace "gseStateDisconnected -> gseStateOnHold"
  End If
End Function

' GSE >= 4.3.1.79
Function gseHoldEx(ByVal szSound)
  Dim retVal
  TraceFunction "gseHoldEx", szSound

  If (Not bCallConnected) Then
    ' Accept call automatically
    retVal = PBXCall.PlayMessage("Announcements/Silence_200ms.wav")
    bCallConnected = True
  End If
  
  retVal = PBXCall.Hold(szSound)
  If (retVal = PBXSuccess) Then
    g_bIsOnHold = True
    gseHoldEx = gseStateOnHold
  Else
    ' Trace return value
    PBXScript.OutputTrace "error in PBXCall.Hold, retVal = " & retVal
    g_bIsOnHold = True
    gseHoldEx = gseStateOnHold
  End If

  CheckIfCallIsDisconnected gseHoldEx

  TraceFunctionResult "gseHoldEx", gseHoldEx
End Function


''''''''''''''
'' Function:
''   gseActivate()
'' Description:
''   Activate call from hold state
'' Parameters:
''   none
'' Return value:
''   gseStateActivated - a call was successfuly activated
''   gseStateDisconnected - call was disconnected (invisible output)
Function gseActivate()
  Dim retVal
  TraceFunction "gseActivate", ""

  retVal = PBXCall.Activate()
  If (retVal = PBXCallTermOriginatorDisconnected) Then
    g_bIsOnHold = False
    gseActivate = gseStateDisconnected
  Else
    g_bIsOnHold = False
    gseActivate = gseStateActivated
  End If

  TraceFunctionResult "gseActivate", gseActivate
End Function


''''''''''''''
'' Function:
''   gseWaitForDisconnect()
'' Description:
''   Wait for disconnect 
'' Parameters:
''   [in] nTimeout - Timeout. A zero timeout waits infinitely
'' Return value:
''   gseStateDisconnected - call was disconnected
''   gseStateTimeout - timeout
Function gseWaitForDisconnect(ByVal nTimeout)
  Dim retVal
  TraceFunction "gseWaitForDisconnect", CStr(nTimeout)

  nTimeout = CInt(nTimeout)
  retVal = PBXCall.WaitForDisconnect(nTimeout)
  
  If (retVal = PBXTimeout) Then
    gseWaitForDisconnect = gseStateTimeout
  Else
    gseWaitForDisconnect = gseStateDisconnected
  End If

  TraceFunctionResult "gseWaitForDisconnect", gseWaitForDisconnect
End Function



'' ************************************* RemoteInquiry for CRM ****************************************
''''''''''''''
'' Function:
''   gseSayName()
'' Description:
''   Pronounce user name
'' Parameters:
''   [in] szName - user name, for directory lookup.
'' Return value:
''   gseSayName = gseStatePlayed

Function gseSayName(ByVal szName)
  Dim nFileNamePos, szFileName, retVal, gseVar_

  TraceFunction "gseSayName", szName

  If (g_bIsOnHold = True) Then
    ' Activate call (ignore return value)
    retVal = gseActivate()
  End If
  
  retVal = PBXCall.PlayMessage("Name.wav", 0, True, szName)
  PBXScript.OutputTrace "gseSayName1, file = [Name.wav], NewState = " & retVal
  If ((retVal = PBXSuccess) Or (retVal = PBXTimeout)) Then
    retVal = gseStatePlayed
  Else
    szFileName = "Names/" & szName & ".wav"
    retVal = gsePlaySound(szFileName, "", False, gseVar_, True)
    PBXScript.OutputTrace "gseSayName2, file = [" & szFileName & "], NewState = " & retVal
  End If
  
  gseSayName = retVal
  TraceFunctionResult "gseSayName", gseSayName
End Function


'' Remote Inquiry for CRM / Standard Redirections (obsolete - for 4.00)
Sub RemoteInquiry(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  crmRemoteInquiryEx bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, g_szStdRiPIN, False
End Sub


'' Remote Inquiry for CRM / Standard Redirections (for 4.10)
Sub crmRemoteInquiryEx(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI)
  Dim retDummy
  AdjustBoolean bUseStdRI
  If (bUseStdRI = True) Then
    ' Use standard
    retDummy = RemoteInquiryEx2(bEnabled, g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, g_bStdRiUsePINPrompt, g_szStdRiPIN)
  Else
    ' Use customized
    retDummy = RemoteInquiryEx2(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN)
  End If
End Sub


'' Remote Inquiry for CRM / Standard Redirections (for 4.30)
Sub crmRemoteInquiryEx2(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  crmRemoteInquiryEx3 bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, False
End Sub


'' 5.00
Sub crmRemoteInquiryEx3(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  If (bEnabled <> "Voicemail.True") Then
    AdjustBoolean bEnabled
  End If  
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
  
  crmRemoteInquiryEx4 bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria
End Sub

Sub crmRemoteInquiryEx4(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  Dim retDummy
  If (bUseStdRI = True) Then
    ' Use standard
    If (bStdRIWithoutPIN) Then
      bUsePINPrompt = False
    Else
      bUsePINPrompt = True
    End If

    retDummy = RemoteInquiryEx4(bEnabled, g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, bUsePINPrompt, g_szStdRiPIN, g_bUseFromCriteria)
  Else
    ' Use customized
    retDummy = RemoteInquiryEx4(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseFromCriteria)
  End If
End Sub

'' Remote Inquiry for GSE (obsolete - for 4.00)
Function gseRemoteInquiry(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  gseRemoteInquiry = RemoteInquiryEx(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt)
End Function


'' Remote Inquiry for GSE (for 4.10)
Function gseRemoteInquiryEx(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI)
  AdjustBoolean bUseStdRI
  If (bUseStdRI = True) Then
    ' Use standard
    gseRemoteInquiryEx = RemoteInquiryEx2(bEnabled, g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, g_bStdRiUsePINPrompt, g_szStdRiPIN)
  Else
    ' Use customized
    gseRemoteInquiryEx = RemoteInquiryEx2(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN)
  End If
End Function


'' Remote Inquiry for GSE (for 4.30)
Function gseRemoteInquiryEx2(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  gseRemoteInquiryEx2 = gseRemoteInquiryEx3(bEnabled, szServerName, szUserName, szPassword, True, _
      szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN)
End Function


'' Remote Inquiry for GSE (for 4.31)
Function gseRemoteInquiryEx3(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN)
  gseRemoteInquiryEx3 = gseRemoteInquiryEx4(bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, False)
End Function

'' Remote Inquiry for GSE (for 5.00)
Function gseRemoteInquiryEx4(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  If (bEnabled <> "Voicemail.True") Then
    AdjustBoolean bEnabled
  End If
  AdjustBoolean bPasswordEncoded
  AdjustBoolean bUseSSL
  AdjustBoolean bUsePINPrompt
  AdjustBoolean bUseStdRI
  AdjustBoolean bStdRIWithoutPIN
  AdjustBoolean bUseFromCriteria
  gseRemoteInquiryEx4 = gseRemoteInquiryEx5(bEnabled, szServerName, szUserName, szPassword, bPasswordEncoded, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseStdRI, bStdRIWithoutPIN, bUseFromCriteria)
End Function

'' Remote Inquiry for GSE (for 6.20)
Function gseRemoteInquiryEx5(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal bPasswordEncoded, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseStdRI, ByVal bStdRIWithoutPIN, ByVal bUseFromCriteria)
  ' TODO: parameter bPasswordEncoded is ignored so far
  If (bUseStdRI = True) Then
    ' Use standard
    If (bStdRIWithoutPIN) Then
      bUsePINPrompt = False
    Else
      bUsePINPrompt = True
    End If

    gseRemoteInquiryEx5 = RemoteInquiryEx4(bEnabled, g_szStdRiServerName, g_szStdRiUserName, g_szStdRiPassword, g_szStdRiMailFolder, g_bStdRiUseSSL, bUsePINPrompt, g_szStdRiPIN, g_bUseFromCriteria)
  Else
    ' Use customized
    gseRemoteInquiryEx5 = RemoteInquiryEx4(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseFromCriteria)
  End If
End Function

'' Support 4.00 scripts
Function RemoteInquiryEx(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt)
  RemoteInquiryEx = RemoteInquiryEx2(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, g_szStdRiPIN)
End Function


''''''''''''''
'' Function:
''   CheckIfCallIsDisconnected()
'' Description:
''   Change current sate to "gseStateDisconnected" if call is disconnected
'' Parameters:
''   [in/out] rCurState - currect state. will be changed to "gseStateDisconnected"
''                        if call is disconnected
Sub CheckIfCallIsDisconnected(ByRef rCurState)
  If (PBXCall.IsOriginatorDisconnected) Then
    rCurState = gseStateDisconnected
  End If
End Sub

'#include "actionStandardRemoteInquiry.vbs"

Function RemoteInquiryEx2(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN)
  RemoteInquiryEx2 = RemoteInquiryEx3(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, False)
End Function

' 5.00
Function RemoteInquiryEx3(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseFromCriteria)
    If (bEnabled <> "Voicemail.True") Then
       AdjustBoolean bEnabled
    End If
    AdjustBoolean bUseSSL
    AdjustBoolean bUsePINPrompt
    AdjustBoolean bUseFromCriteria
    
    RemoteInquiryEx3 = RemoteInquiryEx4(bEnabled, szServerName, szUserName, szPassword, szMailFolder, bUseSSL, bUsePINPrompt, szPIN, bUseFromCriteria)
End Function

' 6.20
Function RemoteInquiryEx4(ByVal bEnabled, ByVal szServerName, ByVal szUserName, ByVal szPassword, ByVal szMailFolder, ByVal bUseSSL, ByVal bUsePINPrompt, ByVal szPIN, ByVal bUseFromCriteria)
        PBXScript.OutputTrace "Remote Inquiry started"
        Dim rInParams_4_actionStandardRemoteInquiry
        Dim fnResult
        
        fnResult = gseStateIMAP4Success
        If (g_bIsOnHold = True) Then
            ' Activate call (ignore return value)
            Dim retHoldVal
            retHoldVal = gseActivate()
        End If
 
 	If ((bEnabled = True) Or (bEnabled = "Voicemail.True")) Then
       
                Set rInParams_4_actionStandardRemoteInquiry = new GSEParamList
                rInParams_4_actionStandardRemoteInquiry.Count = 9
                rInParams_4_actionStandardRemoteInquiry.AddParam "bEnabled", bEnabled
                rInParams_4_actionStandardRemoteInquiry.AddParam "szServerName", szServerName
                rInParams_4_actionStandardRemoteInquiry.AddParam "szUserName", szUserName
                rInParams_4_actionStandardRemoteInquiry.AddParam "szPassword", szPassword
                rInParams_4_actionStandardRemoteInquiry.AddParam "szMailFolder", szMailFolder
                rInParams_4_actionStandardRemoteInquiry.AddParam "bUseSSL", bUseSSL
                rInParams_4_actionStandardRemoteInquiry.AddParam "bUsePINPrompt", bUsePINPrompt
                rInParams_4_actionStandardRemoteInquiry.AddParam "szPIN", szPIN
                rInParams_4_actionStandardRemoteInquiry.AddParam "bUseFromCriteria", bUseFromCriteria
                
                actionStandardRemoteInquiry rInParams_4_actionStandardRemoteInquiry
                
                fnResult = rInParams_4_actionStandardRemoteInquiry.m_FunctionResult

  	End If
  	PBXScript.OutputTrace "Remote Inquiry End, retVal = " & fnResult
  	RemoteInquiryEx4 = fnResult
  	TraceFunctionResult "RemoteInquiryEx4", RemoteInquiryEx4
End Function

'#include "Resources.vbs"


'' ****************************************** TTS Functions *******************************************

'#include "actionInitTTS.vbs"
Function gseInitTTS(ByRef oTTSSession)
  Dim rTTSInParams
  
  Set rTTSInParams = new GSEParamList
  rTTSInParams.Count = 0
  
  actionInitTTS rTTSInParams
  
  ' update oTTSSession
  If Not IsNull(rTTSInParams.m_ReservedRef) Then
    Set oTTSSession = rTTSInParams.m_ReservedRef
  Else
    oTTSSession = Null
  End If

  gseInitTTS = 0 ' allways return 0
End Function

'#include "actionStartTTS.vbs"
Function gseStartTTS(ByRef oTTSSession, ByRef rSessionID, ByVal bWaitUntilTTSFinished, ByVal bUseTimeout, ByVal nTimeout, _
                     ByVal bUseTextFromFile, ByVal szSource, ByVal nLanguageID, ByRef rOutFileName)
  AdjustBoolean bWaitUntilTTSFinished
  AdjustBoolean bUseTimeout
  AdjustBoolean bUseTextFromFile
  gseStartTTS = gseStartTTSEx(oTTSSession, rSessionID, bWaitUntilTTSFinished, bUseTimeout, nTimeout, _
                     bUseTextFromFile, szSource, nLanguageID, rOutFileName)
End Function
                     
Function gseStartTTSEx(ByRef oTTSSession, ByRef rSessionID, ByVal bWaitUntilTTSFinished, ByVal bUseTimeout, ByVal nTimeout, _
                     ByVal bUseTextFromFile, ByVal szSource, ByVal nLanguageID, ByRef rOutFileName)
  PBXScript.OutputTrace "gseStartTTSEx started"
  Dim rTTSInParams
  Dim fnResult

  ' clear value  
  rOutFileName = ""
  
  Set rTTSInParams = new GSEParamList
  rTTSInParams.Count = 8
  rTTSInParams.AddParam "rSessionID",             rSessionID
  rTTSInParams.AddParam "bWaitUntilTTSFinished",  bWaitUntilTTSFinished
  rTTSInParams.AddParam "bUseTimeout",            bUseTimeout
  rTTSInParams.AddParam "nTimeout",               nTimeout
  rTTSInParams.AddParam "bUseTextFromFile",       bUseTextFromFile
  rTTSInParams.AddParam "szSource",               szSource
  rTTSInParams.AddParam "nLanguageID",            nLanguageID
  rTTSInParams.AddParam "rOutFileName",           rOutFileName

  ' set TTS session object using internal variable
  If Not IsNull(oTTSSession) Then
    Set rTTSInParams.m_ReservedRef = oTTSSession
  Else
    Dim rcDummy
    rcDummy = gseInitTTS(oTTSSession)
    
    If Not IsNull(oTTSSession) Then
      Set rTTSInParams.m_ReservedRef = oTTSSession
    Else
      rTTSInParams.m_ReservedRef = Null
    End If
  End If

  actionStartTTS rTTSInParams

  ' update rSessionID
  rSessionID = rTTSInParams.GetParamValueByName("rSessionID", 0)

  ' update output file name
  rOutFileName = rTTSInParams.GetParamValueByName("rOutFileName", "")

  ' select output:
  ' 0 - success
  ' 1 - failed
  ' 2 - timeout
  If (CStr(rTTSInParams.m_FunctionResult) = "0") Then
    fnResult = gseStateExecuted
  ElseIf (CStr(rTTSInParams.m_FunctionResult) = "2") Then
    fnResult = gseStateTimeout
  Else
    fnResult = gseStateFailed
  End If
  
  ' check if call is disconnected
  CheckIfCallIsDisconnected fnResult
  
  PBXScript.OutputTrace "SatrtTTS ended, retVal = " & fnResult
  gseStartTTSEx = fnResult
End Function


'#include "actionWaitForTTS.vbs"
Function gseWaitForTTS(ByRef oTTSSession, ByRef rSessionID, ByVal bUseTimeout, ByVal nTimeout)
  PBXScript.OutputTrace "WaitForTTS started"
  Dim fnResult, szOutFile

  szOutFile = ""
  fnResult = gseWaitForTTSEx(oTTSSession, rSessionID, bUseTimeout, nTimeout, szOutFile)
  
  PBXScript.OutputTrace "WaitForTTS ended, retVal = " & fnResult
  gseWaitForTTS = fnResult
End Function

'5.10
Function gseWaitForTTSEx(ByRef oTTSSession, ByRef rSessionID, ByVal bUseTimeout, ByVal nTimeout, ByRef rOutFileName)
  AdjustBoolean bUseTimeout
  gseWaitForTTSEx = gseWaitForTTSEx2(oTTSSession, rSessionID, bUseTimeout, nTimeout, rOutFileName)
End Function

'6.20
Function gseWaitForTTSEx2(ByRef oTTSSession, ByRef rSessionID, ByVal bUseTimeout, ByVal nTimeout, ByRef rOutFileName)
  PBXScript.OutputTrace "WaitForTTSEx started"
  Dim rTTSInParams
  Dim fnResult

  PBXScript.OutputTrace "WaitForTTSEx starts, rOutFileName = " & rOutFileName

  Set rTTSInParams = new GSEParamList
  rTTSInParams.Count = 4
  rTTSInParams.AddParam "rSessionID",             rSessionID
  rTTSInParams.AddParam "bUseTimeout",            bUseTimeout
  rTTSInParams.AddParam "nTimeout",               nTimeout
  rTTSInParams.AddParam "rOutFileName",           rOutFileName

  ' set TTS session object using internal variable
  If Not IsNull(oTTSSession) Then
    Set rTTSInParams.m_ReservedRef = oTTSSession
  Else
    rTTSInParams.m_ReservedRef = Null
  End If

  actionWaitForTTS rTTSInParams

  ' select output:
  ' 0 - success
  ' 1 - failed
  ' 2 - timeout
  If (CStr(rTTSInParams.m_FunctionResult) = "0") Then
    fnResult = gseStateExecuted
  ElseIf (CStr(rTTSInParams.m_FunctionResult) = "2") Then
    fnResult = gseStateTimeout
  Else
    fnResult = gseStateFailed
  End If

  rOutFileName = rTTSInParams.GetParamValueByName("rOutFileName", "")

  ' check if call is disconnected
  CheckIfCallIsDisconnected fnResult

  PBXScript.OutputTrace "WaitForTTSEx ends, rOutFileName = " & rOutFileName

  PBXScript.OutputTrace "WaitForTTSEx ended, retVal = " & fnResult
  gseWaitForTTSEx2 = fnResult
End Function

'#include "actionCloseTTS.vbs"
Function gseCloseTTS(ByRef oTTSSession)
  Dim rTTSInParams
  
  Set rTTSInParams = new GSEParamList
  rTTSInParams.Count = 0
  
  ' set TTS session object using internal variable
  If Not IsNull(oTTSSession) Then
    Set rTTSInParams.m_ReservedRef = oTTSSession
  Else
    rTTSInParams.m_ReservedRef = Null
  End If

  actionCloseTTS rTTSInParams
  
  gseCloseTTS = 0 ' allways return 0
End Function

Function gseSayText(ByVal bUseTextFromFile, ByVal szSource, ByVal nLanguageID, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, ByVal bPlayControl)
  AdjustBoolean bUseTextFromFile
  AdjustBoolean bStoreToVariable
  AdjustBoolean bResetVariableContent
  AdjustBoolean bPlayControl
  gseSayText = gseSayTextEx(bUseTextFromFile, szSource, nLanguageID, fMask, bStoreToVariable, szVariableName, bResetVariableContent, bPlayControl)
End Function

Function gseSayTextEx(ByVal bUseTextFromFile, ByVal szSource, ByVal nLanguageID, ByVal fMask, ByVal bStoreToVariable, ByRef szVariableName, ByVal bResetVariableContent, ByVal bPlayControl)
  Dim oTTSSession, rSessionID, retVal, szFromWav, retDummy, szReturn
  oTTSSession = Null

  PBXScriptOutputTrace "--> gseSayTextEx"
  retVal = gseInitTTS(oTTSSession)

  PBXScriptOutputTrace "gseSayTextEx: trying to start TTS"
  retVal = gseStartTTSEx(oTTSSession, rSessionID, True, False, "0", bUseTextFromFile, szSource, nLanguageID, szFromWav)
  szReturn = ExtractGseStateValue(retVal)
  PBXScriptOutputTrace "gseSayTextEx: start TTS returned " & szReturn

  If retVal = gseStateFailed Then
    gseSayTextEx = gseStateFailed
    Exit Function
  End If

  PBXScriptOutputTrace "gseSayTextEx: trying to play sound"
  retVal = gsePlaySoundEx2(szFromWav, fMask, bStoreToVariable, szVariableName, bResetVariableContent, False, "0", bPlayControl)
  szReturn = ExtractGseStateValue(retVal)
  PBXScriptOutputTrace "gseSayTextEx: play sound returned " & szReturn

  If retVal = gseStateDisconnected Then
    gseSayTextEx = gseStateDisconnected
    Exit Function
  End If

  retDummy = gseCloseTTS(oTTSSession)
  
  gseSayTextEx = retVal
  szReturn = ExtractGseStateValue(retVal)
  PBXScriptOutputTrace "<-- gseSayTextEx returns " & szReturn
End Function








'' ************************************** CallQueue Functions *****************************************

''''''''''''''
'' Function:
''   gseQueue_CreateQueue()
'' Description:
''   Create a call queue
'' Parameters:
''   QueueID: Queue ID, could be any string
'' Return value:
''   gseStateCreated: A new queue has been created successfully
''   gseStateExists: A queue with this QueueID already exists
''   gseStateFailed: A queue could not be created due to system resource limitations
''   gseStateDisconnected: The actual call has been disconnected
Function gseQueue_CreateQueue(ByVal QueueID)
  TraceFunction "gseQueue_CreateQueue", QueueID
  
  If ( IsNull(g_QueueAccess) ) Then
    ' create an object on first use
    Set g_QueueAccess = PBXScript.CreateObject( "QueueManager.COM.QueueMgrClass" )
    PBXScript.OutputTrace "QueueManager.COM.QueueMgrClass object created!"
  End If
  
  Dim fnResult, retVal
  
  retVal = g_QueueAccess.CreateQueue( CStr(QueueID) )
  
  ' adjust variables type
  retVal = CInt(retVal)
  
  if ( retVal = QueueManagerResultCreated ) Then
    fnResult = gseStateCreated
  ElseIf ( retVal = QueueManagerResultAlreadyExists ) Then
    fnResult = gseStateExists
  Else ' QueueManagerResultNotCreated
    fnResult = gseStateFailed
  End If
  
  CheckIfCallIsDisconnected fnResult
  
  TraceFunctionResult "gseQueue_CreateQueue", fnResult
  gseQueue_CreateQueue = fnResult
End Function



''''''''''''''
'' Function:
''   gseQueue_SetQueueAttributes()
'' Description:
''   Set call queue attributes
'' Parameters:
''   QueueID: Queue ID
''   szDestination: Destination (group or user)
''   nMaxQueueSize: Maximum allowed number of calls in queue
''   nQueueTimeout: How long in seconds a call will stay in the queue maximal
''   szWaitMusic: Wait announcement
''   szSayPositionPre/szSayPositionPost: These WAV-Files will be played to announce the actual position of a call in this queue
''   szSayRemainingTimePre/szSayRemainingTimePost: These WAV-Files will be played to announce the expected waiting time of a call in this queue
''   nTimeToNextAnnouncement: This parameter defines the time interval between playing sounds like say position/remaining time
''   nAverageCallTime: This defines the average call time for this queue in seconds
'' Return value:
''   gseStateOk: The attributes has been set successfully
''   gseStateFailed: A queue with this QueueID does not exist or wrong parameter
''   gseStateDisconnected: The actual call has been disconnected
Function gseQueue_SetQueueAttributes(ByVal QueueID, ByVal szDestination, ByVal nMaxQueueSize, _
                                     ByVal nQueueTimeout, ByVal szWaitMusic, _
                                     ByVal szSayPositionPre, ByVal szSayPositionPost, _
                                     ByVal szSayRemainingTimePre, ByVal szSayRemainingTimePost, _
                                     ByVal nTimeToNextAnnouncement, ByVal nAverageCallTime)
  TraceFunction "gseQueue_SetQueueAttributes", QueueID
  
  If ( IsNull(g_QueueAccess) ) Then
    ' create an object on first use
    Set g_QueueAccess = PBXScript.CreateObject( "QueueManager.COM.QueueMgrClass" )
    PBXScript.OutputTrace "QueueManager.COM.QueueMgrClass object created!"
  End If

  Dim fnResult, retVal

  PBXScript.OutputTrace "Queue (" & QueueID & ") attributes:" & vbLF & _
                        "Destination:            " & szDestination & vbLF & _
                        "MaxQueueSize:           " & nMaxQueueSize & vbLF & _
                        "QueueTimeout:           " & nQueueTimeout & vbLF & _
                        "WaitMisic:              " & szWaitMusic & vbLF & _
                        "SayPositionPre:         " & szSayPositionPre & vbLF & _
                        "SayPositionPost:        " & szSayPositionPost & vbLF & _
                        "SayRemainingTimePre:    " & szSayRemainingTimePre & vbLF & _
                        "SayRemainingTimePost:   " & szSayRemainingTimePost & vbLF & _
                        "TimeToNextAnnouncement: " & nTimeToNextAnnouncement & vbLF & _
                        "AverageCallTime:        " & nAverageCallTime
  
  retVal = g_QueueAccess.SetQueueAttributes(CStr(QueueID), szDestination, nMaxQueueSize, _
                                     nQueueTimeout, szWaitMusic, _
                                     szSayPositionPre, szSayPositionPost, _
                                     szSayRemainingTimePre, szSayRemainingTimePost, _
                                     nTimeToNextAnnouncement, nAverageCallTime)
  
  ' adjust variables type
  retVal = CInt(retVal)
  
  if ( retVal = QueueManagerResultOK ) Then
    fnResult = gseStateOk
  Else ' QueueManagerResultNotOK
    fnResult = gseStateFailed
  End If
  
  CheckIfCallIsDisconnected fnResult
  
  TraceFunctionResult "gseQueue_SetQueueAttributes", fnResult
  gseQueue_SetQueueAttributes = fnResult
End Function


Function gseQueue_GetQueueAttributes(ByVal QueueID, ByVal bGetDestination, ByRef szDestination, _
                                     ByVal bGetAktQueueSize, ByRef nAktQueueSize, _
                                     ByVal bGetMaxQueueSize, ByRef nMaxQueueSize, _
                                     ByVal bGetQueueTimeout, ByRef nQueueTimeout, _
                                     ByVal bGetWaitMusic, ByRef szWaitMusic, _
                                     ByVal bGetSayPositionPre, ByRef szSayPositionPre, _
                                     ByVal bGetSayPositionPost, ByRef szSayPositionPost, _
                                     ByVal bGetSayRemainingTimePre, ByRef szSayRemainingTimePre, _
                                     ByVal bGetSayRemainingTimePost, ByRef szSayRemainingTimePost, _
                                     ByVal bGetTimeToNextAnnouncement, ByRef nTimeToNextAnnouncement, _
                                     ByVal bGetAverageCallTime, ByRef nAverageCallTime)
  AdjustBoolean bGetDestination
  AdjustBoolean bGetAktQueueSize
  AdjustBoolean bGetMaxQueueSize
  AdjustBoolean bGetQueueTimeout
  AdjustBoolean bGetWaitMusic
  AdjustBoolean bGetSayPositionPre
  AdjustBoolean bGetSayPositionPost
  AdjustBoolean bGetSayRemainingTimePre
  AdjustBoolean bGetSayRemainingTimePost
  AdjustBoolean bGetTimeToNextAnnouncement
  AdjustBoolean bGetAverageCallTime
  gseQueue_GetQueueAttributes = gseQueue_GetQueueAttributesEx(QueueID, bGetDestination, szDestination, _
                                     bGetAktQueueSize, nAktQueueSize, _
                                     bGetMaxQueueSize, nMaxQueueSize, _
                                     bGetQueueTimeout, nQueueTimeout, _
                                     bGetWaitMusic, szWaitMusic, _
                                     bGetSayPositionPre, szSayPositionPre, _
                                     bGetSayPositionPost, szSayPositionPost, _
                                     bGetSayRemainingTimePre, szSayRemainingTimePre, _
                                     bGetSayRemainingTimePost, szSayRemainingTimePost, _
                                     bGetTimeToNextAnnouncement, nTimeToNextAnnouncement, _
                                     bGetAverageCallTime, nAverageCallTime)
End Function

''''''''''''''
'' Function:
''   gseQueue_GetQueueAttributesEx()
'' Description:
''   Set call queue attributes
'' Parameters:
''   QueueID: Queue ID
''   szDestination: Variable for destination (if "bGetDestination"="True")
''   nAktQueueSize: Variable for actual queue size (if "bGetAktQueueSize"="True")
''   nMaxQueueSize: Variable for maximum allowed number of calls in queue (if "bGetMaxQueueSize"="True")
''   nQueueTimeout: Variable for queue timeout (if "bGetQueueTimeout"="True")
''   szWaitMusic: Variable for wait announcement (if "bGetWaitMusic"="True")
''   szSayPositionPre/szSayPositionPost: Variables for position announecements (if "bGetSayPositionPre"="True"/"bGetSayPositionPost"="True")
''   szSayRemainingTimePre/szSayRemainingTimePost: Variables for remaining time announecements (if "bGetSayRemainingTimePre"="True"/"bGetSayRemainingTimePost"="True")
''   nTimeToNextAnnouncement: Variable for time to next announcement (if "bGetTimeToNextAnnouncement"="True")
''   nAverageCallTime: Variable for average call time (if "bGetAverageCallTime"="True")
'' Return value:
''   gseStateOk: Information has been stored in the variables
''   gseStateFailed: A queue with this QueueID does not exist
''   gseStateDisconnected: The actual call has been disconnected
Function gseQueue_GetQueueAttributesEx(ByVal QueueID, ByVal bGetDestination, ByRef szDestination, _
                                     ByVal bGetAktQueueSize, ByRef nAktQueueSize, _
                                     ByVal bGetMaxQueueSize, ByRef nMaxQueueSize, _
                                     ByVal bGetQueueTimeout, ByRef nQueueTimeout, _
                                     ByVal bGetWaitMusic, ByRef szWaitMusic, _
                                     ByVal bGetSayPositionPre, ByRef szSayPositionPre, _
                                     ByVal bGetSayPositionPost, ByRef szSayPositionPost, _
                                     ByVal bGetSayRemainingTimePre, ByRef szSayRemainingTimePre, _
                                     ByVal bGetSayRemainingTimePost, ByRef szSayRemainingTimePost, _
                                     ByVal bGetTimeToNextAnnouncement, ByRef nTimeToNextAnnouncement, _
                                     ByVal bGetAverageCallTime, ByRef nAverageCallTime)

  TraceFunction "gseQueue_GetQueueAttributesEx", QueueID & ", " & bGetDestination & ", " & bGetAktQueueSize & ", " & _
                bGetMaxQueueSize & ", " & bGetQueueTimeout & ", " & bGetWaitMusic & ", " & bGetSayPositionPre & ", " & _
                bGetSayPositionPost & ", " & bGetSayRemainingTimePre & ", " & bGetSayRemainingTimePost & ", " & _
                bGetTimeToNextAnnouncement & ", " & bGetAverageCallTime 

  If ( IsNull(g_QueueAccess) ) Then
    ' create an object on first use
    Set g_QueueAccess = PBXScript.CreateObject( "QueueManager.COM.QueueMgrClass" )
    PBXScript.OutputTrace "QueueManager.COM.QueueMgrClass object created!"
  End If

  Dim fnResult, retVal
  
  Dim szDestinationNew, nAktQueueSizeNew, nMaxQueueSizeNew, nQueueTimeoutNew, szWaitMusicNew, szSayPositionPreNew, _
      szSayPositionPostNew, szSayRemainingTimePreNew, szSayRemainingTimePostNew, nTimeToNextAnnouncementNew, nAverageCallTimeNew

  ' adjust variables type
  QueueID = CStr(QueueID)
  szDestinationNew = CStr("")
  nAktQueueSizeNew = CInt(0)
  nMaxQueueSizeNew = CInt(0)
  nQueueTimeoutNew = CInt(0)
  szWaitMusicNew = CStr("")
  szSayPositionPreNew = CStr("")
  szSayPositionPostNew = CStr("")
  szSayRemainingTimePreNew = CStr("")
  szSayRemainingTimePostNew = CStr("")
  nTimeToNextAnnouncementNew = CInt(0)
  nAverageCallTimeNew = CInt(0)
  
  retVal = g_QueueAccess.GetQueueAttributes( QueueID, szDestinationNew, nAktQueueSizeNew, nMaxQueueSizeNew, _
                             nQueueTimeoutNew, szWaitMusicNew, _
                             szSayPositionPreNew, szSayPositionPostNew, _
                             szSayRemainingTimePreNew, szSayRemainingTimePostNew, _
                             nTimeToNextAnnouncementNew, nAverageCallTimeNew)
                             
  ' adjust variables type
  retVal = CInt(retVal)
  szDestinationNew = CStr(szDestinationNew)
  nAktQueueSizeNew = CInt(nAktQueueSizeNew)
  nMaxQueueSizeNew = CInt(nMaxQueueSizeNew)
  nQueueTimeoutNew = CInt(nQueueTimeoutNew)
  szWaitMusicNew = CStr(szWaitMusicNew)
  szSayPositionPreNew = CStr(szSayPositionPreNew)
  szSayPositionPostNew = CStr(szSayPositionPostNew)
  szSayRemainingTimePreNew = CStr(szSayRemainingTimePreNew)
  szSayRemainingTimePostNew = CStr(szSayRemainingTimePostNew)
  nTimeToNextAnnouncementNew = CInt(nTimeToNextAnnouncementNew)
  nAverageCallTimeNew = CInt(nAverageCallTimeNew)
  
  If ( retVal = QueueManagerResultOK ) Then
    PBXScript.OutputTrace "Queue (" & QueueID & ") attributes:" & vbLF & _
                        "Destination:            " & szDestinationNew & vbLF & _
                        "ActualQueueSize:        " & nAktQueueSizeNew & vbLF & _
                        "MaxQueueSize:           " & nMaxQueueSizeNew & vbLF & _
                        "QueueTimeout:           " & nQueueTimeoutNew & vbLF & _
                        "WaitMisic:              " & szWaitMusicNew & vbLF & _
                        "SayPositionPre:         " & szSayPositionPreNew & vbLF & _
                        "SayPositionPost:        " & szSayPositionPostNew & vbLF & _
                        "SayRemainingTimePre:    " & szSayRemainingTimePreNew & vbLF & _
                        "SayRemainingTimePost:   " & szSayRemainingTimePostNew & vbLF & _
                        "TimeToNextAnnouncement: " & nTimeToNextAnnouncementNew & vbLF & _
                        "AverageCallTime:        " & nAverageCallTimeNew
    
    If (bGetDestination = True) Then
      szDestination = szDestinationNew
    End If
    If (bGetAktQueueSize = True) Then
      nAktQueueSize = nAktQueueSizeNew
    End If
    If (bGetMaxQueueSize = True) Then
      nMaxQueueSize = nMaxQueueSizeNew
    End If
    If (bGetQueueTimeout = True) Then
      nQueueTimeout = nQueueTimeoutNew
    End If
    If (bGetWaitMusic = True) Then
      szWaitMusic = szWaitMusicNew
    End If
    If (bGetSayPositionPre = True) Then
      szSayPositionPre = szSayPositionPreNew
    End If
    If (bGetSayPositionPost = True) Then
      szSayPositionPost = szSayPositionPostNew
    End If
    If (bGetSayRemainingTimePre = True) Then
      szSayRemainingTimePre = szSayRemainingTimePreNew
    End If
    If (bGetSayRemainingTimePost = True) Then
      szSayRemainingTimePost = szSayRemainingTimePostNew
    End If
    If (bGetTimeToNextAnnouncement = True) Then
      nTimeToNextAnnouncement = nTimeToNextAnnouncementNew
    End If
    If (bGetAverageCallTime = True) Then
      nAverageCallTime = nAverageCallTimeNew
    End If
    
    fnResult = gseStateOk
  Else ' QueueManagerResultNotOK
    fnResult = gseStateFailed
  End If
  
  CheckIfCallIsDisconnected fnResult

  TraceFunctionResult "gseQueue_GetQueueAttributesEx", fnResult
  gseQueue_GetQueueAttributesEx = fnResult
End Function


''''''''''''''
'' Function:
''   gseQueue_DeleteQueue()
'' Description:
''   Delete a call queue
'' Parameters:
''   QueueID: Queue ID
'' Return value:
''   gseStateOk: A queue has been deleted
''   gseStateFailed: A queue with this QueueID does not exist
''   gseStateDisconnected: The actual call has been disconnected
Function gseQueue_DeleteQueue(ByVal QueueID)
  TraceFunction "gseQueue_DeleteQueue", QueueID
  
  If ( IsNull(g_QueueAccess) ) Then
    ' create an object on first use
    Set g_QueueAccess = PBXScript.CreateObject( "QueueManager.COM.QueueMgrClass" )
    PBXScript.OutputTrace "QueueManager.COM.QueueMgrClass object created!"
  End If

  Dim fnResult, retVal
  
  retVal = g_QueueAccess.DeleteQueue( CStr(QueueID) )
  
  ' adjust variables type
  retVal = CInt(retVal)
  
  if ( retVal = QueueManagerResultOK ) Then
    fnResult = gseStateOk
  Else ' QueueManagerResultNotOK
    fnResult = gseStateFailed
  End If
  
  CheckIfCallIsDisconnected fnResult
  
  TraceFunctionResult "gseQueue_DeleteQueue", fnResult
  gseQueue_DeleteQueue = fnResult
End Function


''''''''''''''
'' Function:
''   gseQueue_ProcessCallByQueue()
'' Description:
''   Put the current call into queue and proceed it
'' Parameters:
''   QueueID: Queue ID
''   nPosition: Position (1=Top, 2=Bottom)
''   nTimeout: Timeout in seconds
'' Return value:
''   gseStateConnected: The call has been proceeded by the queue and connected to the destination
''   gseStateFailed: A queue with this QueueID does not exist or queue was deleted by another script while call was in a queue
''   gseStateDisconnected: The actual call has been disconnected
''   gseStateSizeExceeded: The call could not be added because this would make the AktQueueSize to exceed the MaxQueueSize
''   gseStateDestinationUnreachable: The call could not be added because the destination contains no user with logged in state
''   gseStateTimeout: The timeout has expired; the actual call is removed from the queue
''   gseStateQueueTimeout: The actual call was in the queue too long in the queue.
''                         The QueueTimeout has expired; the actual call is removed from the queue.
Function gseQueue_ProcessCallByQueue(ByVal QueueID, ByVal nPosition, ByVal nTimeout)
                                     
  TraceFunction "gseQueue_ProcessCallByQueue", QueueID & ", " & nPosition & ", " & nTimeout
  
  If ( IsNull(g_QueueAccess) ) Then
    ' create an object on first use
    Set g_QueueAccess = PBXScript.CreateObject( "QueueManager.COM.QueueMgrClass" )
    PBXScript.OutputTrace "QueueManager.COM.QueueMgrClass object created!"
  End If

  Dim fnResult, retVal, nCallID, nRemainingTimeToNextAnnouncement, nThisCallPosition, nQueueTime, rDummy, nExpectedTimeToWait, bIsUserOrGroupBusy, pDummyV, bSkipConnectionAttempts
  Dim tTimeLoopStarted, nSecondsPassedFromStart
  nCallID = CLng(PBXCall.CallId)
  nTimeout = CIntEx(nTimeout)
  
  QueueID = CStr(QueueID)
  
  ' 1) check if call is disconnected
  fnResult = gseStateFailed
  CheckIfCallIsDisconnected fnResult
  If (fnResult = gseStateDisconnected) Then
    ' call is disconnected
    PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected"
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If
  
  ' 2) Activate call if call is on Hold
  retVal = gseActivate()
  
  ' 3) Get queue attributes
  Dim szDestination, nAktQueueSize, nMaxQueueSize, _
      nQueueTimeout, szWaitMusic, _
      szSayPositionPre, szSayPositionPost, _
      szSayRemainingTimePre, szSayRemainingTimePost, _
      nTimeToNextAnnouncement, nAverageCallTime
  retVal = gseQueue_GetQueueAttributesEx(QueueID, True, szDestination, True, nAktQueueSize, True, nMaxQueueSize, _
                                     True, nQueueTimeout, True, szWaitMusic, _
                                     True, szSayPositionPre, True, szSayPositionPost, _
                                     True, szSayRemainingTimePre, True, szSayRemainingTimePost, _
                                     True, nTimeToNextAnnouncement, True, nAverageCallTime)
  If ( retVal <> gseStateOk ) Then
    ' unable to get queue attributes
    PBXScript.OutputTrace "unable to get queue (ID=" & QueueID & ") attributes"
    fnResult = gseStateFailed
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If
  
  ' 3a) Check if we have at least one loggen in user for specified destination
  If ( PBXScript.IsUserOrGroupBusyEx(szDestination) = 2 ) Then
    ' all users matching specified destination are logged off now
    PBXScript.OutputTrace "all users matching specified destination are logged off now"
    fnResult = gseStateDestinationUnreachable
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If

  ' 4) place call to queue
  retVal = g_QueueAccess.AddCallToQueue(QueueID, nCallID, CInt(nPosition))
    
  ' adjust variables type
  retVal = CInt(retVal)
  
  If ( retVal = QueueManagerResultNotOK ) Then
    ' unable to place call to queue
    PBXScript.OutputTrace "unable to place call (ID=" & nCallID & ") to queue (ID=" & QueueID & ")"
    fnResult = gseStateFailed
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  ElseIf ( retVal = QueueManagerResultSizeExceeded ) Then
    ' queue size exeeded
    PBXScript.OutputTrace "queue (ID=" & QueueID & ") size exceeded. call (ID=" & nCallID & ") is not placed to queue"
    fnResult = gseStateSizeExceeded
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If
  
  PBXScript.OutputTrace "call (ID=" & nCallID & ") sucessfully placed to queue (ID=" & QueueID & ")"
  
  ' initialize variables
  nAktQueueSize = 0
  nThisCallPosition = 0
  nQueueTime = 0
  
  ' 5) Accept the call if not accepted
  If (Not bCallConnected) Then
    ' Accept call automatically
    retVal = PBXCall.PlayMessage("Announcements/Silence_200ms.wav")
    bCallConnected = True
  End If
  
  ' 6) Start hold music
  retVal = PBXCall.Hold(szWaitMusic)
  If (retVal <> PBXSuccess) Then
    ' error while putting call on hold
    PBXScript.OutputTrace "error " & ExtractReturnValue(retVal) & " while putting call (ID=" & nCallID & ") on hold"
    retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
    fnResult = gseStateFailed
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If
  
  Do
    
    bSkipConnectionAttempts = False
    
    ' 7) wait nTimeToNextAnnouncement. while this phase try to connect a call if the call on top of queue and destination is free
    nRemainingTimeToNextAnnouncement = nTimeToNextAnnouncement
    
    tTimeLoopStarted = PBXUser.Now
    
    Do While ( nRemainingTimeToNextAnnouncement > 0)
      retVal = g_QueueAccess.GetQueueStatus(QueueID, nCallID, nAktQueueSize, nThisCallPosition, nQueueTime)
      
      ' adjust variables type
      retVal = CInt(retVal)
      nAktQueueSize = CInt(nAktQueueSize)
      nThisCallPosition = CInt(nThisCallPosition)
      nQueueTime = CInt(nQueueTime)
      
      If ( retVal = QueueManagerResultNotOK ) Then
        ' unable get call position in queue
        PBXScript.OutputTrace "unable to get call (ID=" & nCallID & ") position in queue (ID=" & QueueID & ")"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        fnResult = gseStateFailed
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If
      
      ' debug
      'PBXScript.OutputTrace "position " & nThisCallPosition & "/" & nAktQueueSize & ", seconds in queue: " & nQueueTime
      ' debug
      
      ' check queue timeout
      If ( nQueueTime > nQueueTimeout ) Then
        ' call is reached queue timeout
        PBXScript.OutputTrace "call (ID=" & nCallID & ") is reached queue (ID=" & QueueID & ") timeout"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        fnResult = gseStateQueueTimeout
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If
      
      ' check call timeout
      If ( nQueueTime > nTimeout ) Then
        ' call is reached call timeout
        PBXScript.OutputTrace "call (ID=" & nCallID & ") is reached timeout"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        fnResult = gseStateTimeout
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If

      If ( ( nThisCallPosition = 1 ) And (Not bSkipConnectionAttempts) ) Then
        ' check if we destination is free
        bIsUserOrGroupBusy = PBXScript.IsUserOrGroupBusy(szDestination)
        ' debug
        'PBXScript.OutputTrace "user (" & szDestination & ") busy: " & CInt(bIsUserOrGroupBusy)
        ' debug
        
        If ( bIsUserOrGroupBusy = 0 ) Then
          ' user/group is free
          PBXScript.OutputTrace "user (" & szDestination & ") is free, try to establish a call..."
          retVal = PBXCall.Activate()
          retVal = PBXCallConnectToWrapper(szDestination, 15, false, "", "", rDummy, true, 15, false, "", "", pDummyV, false, true)
          If ( retVal = PBXSuccess ) Then
            ' call is connected
            PBXScript.OutputTrace "call (ID=" & nCallID & ") is connected to " & szDestination & " wait while call is ended..."
            ' remove call from queue immediately
            retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
            ' wait while call is diconneced
            retVal = PBXCall.WaitForDisconnect(0)
            PBXScript.OutputTrace "call (ID=" & nCallID & ") is ended (procced by queue)"
            ' retVal = PBXCall.Activate() --> call is already activated
            fnResult = gseStateConnected
            gseQueue_ProcessCallByQueue = fnResult
            TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
            Exit Function
          ElseIf ( retVal = PBXCallTermOriginatorDisconnected ) Then
            ' origination call is disconnected
            PBXScript.OutputTrace "call (ID=" & nCallID & ") - originator is disconnected while connecting to destination"
            retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
            ' retVal = PBXCall.Activate() --> call is already activated
            fnResult = gseStateDisconnected
            gseQueue_ProcessCallByQueue = fnResult
            TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
            Exit Function
          Else
            ' something else - ignore (start hold music)
            retVal = PBXCall.Hold(szWaitMusic)
            If (retVal <> PBXSuccess) Then
                ' error while putting call on hold
                PBXScript.OutputTrace "error " & ExtractReturnValue(retVal) & " while putting call (ID=" & nCallID & ") on hold"
                retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
                fnResult = gseStateFailed
                ' check if call is disconnected
                CheckIfCallIsDisconnected fnResult
                gseQueue_ProcessCallByQueue = fnResult
                TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
                Exit Function
            End If

            ' Call was not picket up, play hold music for defined interval betwen announcements and prevent
            ' next delivering attempts in this cycle
            nRemainingTimeToNextAnnouncement = nTimeToNextAnnouncement
            bSkipConnectionAttempts = True
            
          End If
          
        End If
      End If
      
      ' adjust sleeping time
      nSecondsPassedFromStart = Abs(DateDiff("s", PBXUser.Now, tTimeLoopStarted))
      nRemainingTimeToNextAnnouncement = nRemainingTimeToNextAnnouncement - 1
      
      If ( nSecondsPassedFromStart > (nTimeToNextAnnouncement - nRemainingTimeToNextAnnouncement) ) Then
        ' adjust timer, do not sleep
        nRemainingTimeToNextAnnouncement = nTimeToNextAnnouncement - nSecondsPassedFromStart
      Else
        PBXScript.Sleep(1000)
      End If
      
      ' check if call is disconnected
      fnResult = gseStateFailed
      CheckIfCallIsDisconnected fnResult
      If ( fnResult = gseStateDisconnected ) Then
        ' call is disconnected
        PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected during hold music"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If
    Loop
    
    ' 8) Play position (if files specified)
    If ( ( Len(szSayPositionPre) > 0 ) Or ( Len(szSayPositionPost) > 0 ) ) Then
      If ( Len(szSayPositionPre) > 0 ) Then
        ' play pre sound
        retVal = PBXCall.PlayMessage(szSayPositionPre, 0)
        If ( retVal <> PBXSuccess ) Then
          ' call is disconnected
          PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing szSayPositionPre"
          retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
          retVal = PBXCall.Activate()
          fnResult = gseStateDisconnected
          gseQueue_ProcessCallByQueue = fnResult
          TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
          Exit Function
        End If
      End If
      
      ' say position
      retVal = gseSayNumberEx(CStr(nThisCallPosition), "", False, rDummy, False)
      If ( retVal = gseStateDisconnected ) Then
        ' call is disconnected
        PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing position"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        fnResult = gseStateDisconnected
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If
      
      If ( Len(szSayPositionPost) > 0 ) Then
        ' play post sound
        retVal = PBXCall.PlayMessage(szSayPositionPost, 0)
        If ( retVal <> PBXSuccess ) Then
          ' call is disconnected
          PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing szSayPositionPost"
          retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
          retVal = PBXCall.Activate()
          fnResult = gseStateDisconnected
          gseQueue_ProcessCallByQueue = fnResult
          TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
          Exit Function
        End If
      End If
    Else
      ' skip position playing
      PBXScript.OutputTrace "playing position skipped..."
    End If
  

    ' 9) Play remaining time (if files specified)
    If ( ( Len(szSayRemainingTimePre) > 0 ) Or ( Len(szSayRemainingTimePost) > 0 ) ) Then
      If ( Len(szSayRemainingTimePre) > 0 ) Then
        ' play pre sound
        retVal = PBXCall.PlayMessage(szSayRemainingTimePre, 0)
        If ( retVal <> PBXSuccess ) Then
          ' call is disconnected
          PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing szSayRemainingTimePre"
          retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
          retVal = PBXCall.Activate()
          fnResult = gseStateDisconnected
          gseQueue_ProcessCallByQueue = fnResult
          TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
          Exit Function
        End If
      End If
      
      ' say remaining time
      nExpectedTimeToWait = Int((nAverageCallTime - nQueueTime + 59) / 60)
      If ( nExpectedTimeToWait < 1 ) Then
        nExpectedTimeToWait = 1
      End If
      retVal = gseSayNumber(CStr(nExpectedTimeToWait), "", False, rDummy, False)
      If ( retVal = gseStateDisconnected ) Then
        ' call is disconnected
        PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing position"
        retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
        retVal = PBXCall.Activate()
        fnResult = gseStateDisconnected
        gseQueue_ProcessCallByQueue = fnResult
        TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
        Exit Function
      End If
      
      If ( Len(szSayRemainingTimePost) > 0 ) Then
        ' play post sound
        retVal = PBXCall.PlayMessage(szSayRemainingTimePost, 0)
        If ( retVal <> PBXSuccess ) Then
          ' call is disconnected
          PBXScript.OutputTrace "call (ID=" & nCallID & ") is disconnected while playing szSayRemainingTimePost"
          retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
          retVal = PBXCall.Activate()
          fnResult = gseStateDisconnected
          gseQueue_ProcessCallByQueue = fnResult
          TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
          Exit Function
        End If
      End If
    Else
      ' skip position playing
      PBXScript.OutputTrace "playing remaining time skipped..."
    End If

  Loop

  ' 10) Remove call from queue
  retVal = g_QueueAccess.RemoveCallFromQueue(QueueID, nCallID)
    
  ' adjust variables type
  retVal = CInt(retVal)
  
  If ( retVal = QueueManagerResultNotOK ) Then
    ' unable to remove call from queue
    PBXScript.OutputTrace "unable to remove call (ID=" & nCallID & ") from queue (ID=" & QueueID & ")"
    fnResult = gseStateFailed
    gseQueue_ProcessCallByQueue = fnResult
    TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
    Exit Function
  End If
  
  ' XX) Set state connected (call is handleb by queue)
  fnResult = gseStateConnected
  gseQueue_ProcessCallByQueue = fnResult
  
  TraceFunctionResult "gseQueue_ProcessCallByQueue", fnResult
End Function


'*************************************** Queuing Helper Functions ***************************************

''''''''''''''
'' Function:
''   TranslateUserStateToString()
'' Description:
''   Translate user state to textual representation
'' Parameters:
''   nState: user sate
'' Return value:
''   User state in textual representation
Function TranslateUserStateToString(ByVal nState)
  If ( nState = 0 ) Then
    ' user state not available
    TranslateUserStateToString = "UserStateUnavailable"
  ElseIf ( nState = 1 ) Then
    ' user is logged off
    TranslateUserStateToString = "UserStateLoggedOff"
  ElseIf ( nState = 2 ) Then
    ' user is logged on
    TranslateUserStateToString = "UserStateLoggedOn"
  ElseIf ( nState = 3 ) Then
    ' user is speaking, at least one call has an external origination or destination
    TranslateUserStateToString = "UserStateSpeakingExternal"
  ElseIf ( nState = 4 ) Then
    ' a call is currently alerting at one of the user's devices
    TranslateUserStateToString = "UserStateAlerting"
  ElseIf ( nState = 5 ) Then
    ' user is speaking, none of the calls has an external origination or destination
    TranslateUserStateToString = "UserStateSpeakingInternal"
  Else
    ' unknown state
    TranslateUserStateToString = "Unknown"
  End If
End Function

'' SIG '' Begin Signature
'' SIG '' DZMPMPAPXWNXVSHDNWOKDKPDWZOKVTMWPVDASNLYFOUSQEOROFFPOIASLZUV
'' SIG '' YOBZYERKZRCIKOYHEMZKIUOQHYSLHZENAOMLDKDGJJOVMPFJPLENUKRWMPVN
'' SIG '' IPLMERYXOIOOQOHOOKOSESHIUWZQNYJJWOPWJMRYGXASCLLRZIKYCNCNXJNR
'' SIG '' RWRDJEHHTKOBZIBDGMRZTJCCNAPXKKTADGOKBWTCLOKPFUHJNSHOXEMSQQRU
'' SIG '' DUUKDOZLOJGQGUOEHAHNCRLQBVCLLRTHAMNRNMLVKKNMOMVBNPQFLATUISQY
'' SIG '' AOOIIRLSREBLQDLGLJOCZUOZLGNSPKXXEVQXFLBTBNVSOAWZJMMXWTSOUKKN
'' SIG '' YNOFPFLWINMKNPESLTZAKKQHPANKVBVQBFENWGUMKOJVNIREBISOOEMWMXTK
'' SIG '' YFZIFMLFTQKZLKPVPNOFGYIKTYHCBLKKFOOALKRHLMLKQTROYDMVBOLNRJAQ
'' SIG '' LFIBMNGLRKBGBDZNWWFSCTETKNOHOCNYQIILPYLSREEBLSOUEUEGYWGXHPPX
'' SIG '' HNZDFNELYHGUGZPDVWQPOHCCZPKYPBFJNMKNQKPJGTLRTIRYJKNNABPLONXP
'' SIG '' LCTVKZXWYYKTKZZSUBIVSSTGOJCYIDLDNEEWSZUSJKZWLPMAXKXKFESKIQMJ
'' SIG '' KOBJXLZOPAYNBGYRIIOBJOVWGFLTVZMCOTGNQFLVGYFSLRYMEGFKZQXHYNKG
'' SIG '' KBYEBOHNAZYVSMRMFOOCYLQLZATVMPKMMUKZEFBYWMJWNQCJMHWPSMMLJPSS
'' SIG '' CVRTRROZRQQTZOVZAMJKQPLVBKMPPEEKJRGPIZIUFOMBVLYPVDXWHNLPNHFN
'' SIG '' GNNNCLLOERFCUHPLJPLULHMSVLKLOLGUBINOUUEPMHOISZKZLRICXDNXLMXM
'' SIG '' ONVLLPKIXIMQCMPBMQMKHNLPMKIOBVBYRYSKFNBZYMAHPDVOSZLPMQXPSJTY
'' SIG '' NHPILUOCLOFRHYYNVZYXTANSSEIIGWMRPPJYEPMPOVTRROZQGTFWFLALTVOM
'' SIG '' OPAZ
'' SIG '' End Signature