
Public Class httpd

    Dim mstrURL As String = "*" 'listen on URL "*" is all
    Dim mintPort As Integer = 80 'listen port
    Dim mcolUserDB As New netSMSgw.httpUserDB
    Dim mbolNoAuth As Boolean = True
    Dim mlistener As New System.Net.HttpListener
    Dim mbolHalt As Boolean = False

    Event Log(ByVal pstrLog As String, ByVal penuLogLevel As netSMSgw.logUtils.LogLevels)
    Event GotSMSMsg(ByVal sms As smsMsg)


    Private Structure smsReq
        Dim username As String
        Dim password As String
        Dim priority As String
        Dim message As String
        Dim number As String
    End Structure

#Region "properties"

    Public ReadOnly Property IsSupported() As Boolean
        Get
            Return Net.HttpListener.IsSupported
        End Get
    End Property

    Public Property DisableUserAuth() As Boolean
        Get
            Return mbolNoAuth
        End Get
        Set(ByVal value As Boolean)
            mbolNoAuth = value
        End Set
    End Property

    Public Property UserCollection() As netSMSgw.httpUserDB
        Get
            Return mcolUserDB
        End Get
        Set(ByVal value As netSMSgw.httpUserDB)
            mcolUserDB = value
        End Set
    End Property


    Public Property ListenOnURL() As String
        Get
            Return mstrURL
        End Get
        Set(ByVal value As String)
            mstrURL = value
        End Set
    End Property

    Public Property ListenPort() As Integer
        Get
            Return mintPort
        End Get
        Set(ByVal value As Integer)
            mintPort = value
        End Set
    End Property

#End Region

    Public Sub StopHTTPd()
        RaiseEvent Log(gstrStop, logUtils.LogLevels.Notice)

        mlistener.Abort()
        mlistener.Stop()
        mlistener.Close()

        mbolHalt = True
    End Sub


    Public Sub StartHTTPd()
        Try


            If Not Net.HttpListener.IsSupported Then Exit Sub

            mbolHalt = False

            RaiseEvent Log(gstrListenOn, logUtils.LogLevels.Debug)
            mlistener.Prefixes.Add("http://" & mstrURL & ":" & mintPort & "/")
            RaiseEvent Log(gstrStart, logUtils.LogLevels.Notice)
            mlistener.Start()


            Do While True
                If mlistener.IsListening Then
                    Dim context As Net.HttpListenerContext = mlistener.GetContext
                    'YES correct URL :-)
                    If LCase(context.Request.Url.LocalPath) = "/netsmsgwd" Then

                        Dim bolUserOK As Boolean
                        Dim smsReq As smsReq

                        'get sms request from context (clients request)
                        'This should contain all the parameters: username, password, msg, number, priority
                        smsReq = ParseParams(context.Request.Url.Query.Split("?")(1))

                        'check if user is allowed to send sms's
                        bolUserOK = chkUser(smsReq)

                        'if user denied, log and return failure.
                        If Not bolUserOK Then
                            RaiseEvent Log(gstrInvalidUserPass, logUtils.LogLevels.Warnings)
                            SendResponse(context, gstrInvalidUserPass, True)
                            GoTo TheEnd
                        End If

                        'chk if number is empty
                        If smsReq.number = "" Then
                            RaiseEvent Log(gstrNoNumber, logUtils.LogLevels.Warnings)
                            SendResponse(context, gstrNoNumber, True)
                            GoTo TheEnd
                        End If


                        'make a warning if there is no message:
                        If smsReq.message = "" Then RaiseEvent Log(gstrNoMessage, logUtils.LogLevels.Warnings)

                        'send SMS now.
                        RaiseEvent GotSMSMsg(AssembleSMS(smsReq.number, smsReq.message, smsReq.priority))

                        SendResponse(context, gstrSuccess, True)
                    Else
                        SendResponse(context, gstrUnknownURI, True)
                    End If

                End If
TheEnd:
                If mbolHalt Then Exit Do
            Loop

        Catch ex As System.Net.HttpListenerException
            If ex.ErrorCode = 995 Then
                RaiseEvent Log(gstrHttpdStoped, logUtils.LogLevels.Warnings)
            Else
                RaiseEvent Log(gstrUnhandledErr & ex.Message.ToString, logUtils.LogLevels.Critical)
            End If
        Catch ex As Exception
            RaiseEvent Log(gstrUnhandledErr & ex.Message.ToString, logUtils.LogLevels.Critical)
        End Try

    End Sub

    Private Sub SendResponse(ByVal pContext As Net.HttpListenerContext, ByVal pstrString As String, ByVal pbolClose As Boolean)
        Dim b() As Byte
        b = System.Text.Encoding.ASCII.GetBytes(pstrString)
        pContext.Response.OutputStream.Write(b, 0, b.Length)
        If pbolClose Then pContext.Response.Close()

    End Sub

    Private Function ParseParams(ByVal pParamslist As String) As smsReq
        Dim strParms As String
        Dim strTmp As String
        Dim smsReq As New smsReq
        Dim params() As String = pParamslist.Split("&")
        For Each strParms In params
            strTmp = strParms.Split("=")(1)
            RaiseEvent Log(gstrGotCmd, logUtils.LogLevels.Debug)
            Select Case strParms.Split("=")(0)
                Case "username" : smsReq.username = strTmp
                Case "password" : smsReq.password = strTmp
                Case "msg" : smsReq.message = strTmp
                Case "number" : smsReq.number = strTmp
                Case "priority" : smsReq.priority = strTmp
                Case Else
                    RaiseEvent Log(gstrUnknownCmd & strTmp, logUtils.LogLevels.Warnings)
            End Select
        Next

        Return smsReq


    End Function

    Private Function chkUser(ByVal psmsReq As smsReq) As Boolean

        'if auth is turned on, check db else return msg
        If Not mbolNoAuth Then
            'if the user is in database then return message
            If UserAuth(psmsReq.username, psmsReq.password) Then
                RaiseEvent Log(gstrReturnMsg, logUtils.LogLevels.Debug)
                Return True
                'if not return a warning
            Else
                RaiseEvent Log(gstrInvalidUserPass, logUtils.LogLevels.Warnings)
                Return False
            End If
        Else
            RaiseEvent Log(gstrReturnMsg, logUtils.LogLevels.Debug)
            Return True
        End If

    End Function

    Private Function AssembleSMS(ByVal pstrTlf As String, ByVal pstrMsg As String, ByVal pstrPriority As String) As smsMsg

        Dim sms As New smsMsg

        sms.Number = pstrTlf
        sms.Message = pstrMsg
        Select Case LCase(pstrPriority)
            Case "high" : sms.Priority = smsUtils.smsPriority.High
            Case "normal" : sms.Priority = smsUtils.smsPriority.Normal
            Case "low" : sms.Priority = smsUtils.smsPriority.Low
            Case Else
                sms.Priority = smsUtils.smsPriority.Normal
                RaiseEvent Log(gstrPriorityParseErr, logUtils.LogLevels.Warnings)
        End Select

        Return sms
    End Function


    Private Function UserAuth(ByVal pstrUser As String, ByVal pstrPass As String) As Boolean

        'Dim user As netSMSgw.httpd.httpdUser
        'Dim user As Object
        Dim i As Integer

        For i = 0 To mcolUserDB.Count - 1
            If LCase(mcolUserDB.Item(i).Username) = LCase(pstrUser) And mcolUserDB.Item(i).Password = pstrPass Then Return True
        Next

        Return False

    End Function

End Class
