Attribute VB_Name = "modRanks"
'-----------------------------------------------------
' MirageBot Rank Manager Module
' Written by Christopher Nevin (lancergli@gmail.com)
'-----------------------------------------------------

Option Explicit

Private RankPath As String
Public Ranking() As RankingStruct
Public Type RankingStruct
    HasColor As Boolean
    Color As Long
    RankName As String
    Alias As String
    Safe As Boolean
    UserGroup As Boolean
    Commands() As String
    Inherits() As String
    Message As String
    Flagged As Boolean
    Manages() As String
    PatternMatch As Boolean
End Type

Public Function GetAccess2(Username As String, Index As Integer) As RankingStruct
    Dim CS As New objCmdSet
        CS.Username = Username
        CS.Index = Index
    GetAccess2 = GetAccess(CS)
End Function

Public Function GetAccess(CS As objCmdSet) As RankingStruct
On Error GoTo hErr:
1   If LenB(CS.Username) = 0 Then Exit Function
    Dim r As RankingStruct, findUser As Integer, oUser As objDbUser
3   With CS.Bot
        'Check Actual Access
        'Check if on Gateway
        Dim ToFind As String
        findUser = -1
        ToFind = Suffix(CS.Username)
        If IsOnGateway(ToFind) Then
            'Check if Gateway matches current server's name
            If GatewayMatch(ToFind, CS.Bot.Config.ServerName) Then
                'Strip Gateway and match against database entries
                ToFind = StripGateway(ToFind)
                findUser = .Database.Find(ToFind)
            End If
        End If
        'Username@Gateway not found, look for Username only
        If findUser = -1 Then findUser = .Database.Find(ToFind)
        'Get Users' Rank
        Set oUser = Nothing
        If findUser > -1 Then Set oUser = .Database.GetUser(findUser)
        If Not oUser Is Nothing Then r = GetRankByID(oUser.RankID)
        'Check Clan Access
6       If LenB(r.RankName) = 0 Then
7           If .Clan.Count <> 0 Then
8               Dim CI As Integer, CR As Long
9               CI = .Clan.Find(CS.Username)
10              If CI > -1 Then
                    Select Case .Clan.GetByIndex(CI).Rank
                    Case crChieftain
11                      CR = GetIDByRank(.Config.ARChieftain)
                    Case crGrunt
12                      CR = GetIDByRank(.Config.ARGrunt)
                    Case crPeon
13                      CR = GetIDByRank(.Config.ARPeon)
                    Case crShaman
14                      CR = GetIDByRank(.Config.ARShaman)
                    Case crInitiate
15                      CR = GetIDByRank(.Config.ARInitiate)
                    End Select
16                  If CR > -1 Then r = GetRankByID(CR)
                Else
                    CR = GetIDByRank(.Config.ARUnclan)
                End If
            End If
        End If
        'Check Friend Access
17      If Len(r.RankName) = 0 Then
18          If .Friends.Count <> 0 Then
19              Dim FI As Integer, FR As Long, FO As objFriend
20              For FI = 1 To .Friends.Count
21                  Set FO = .Friends(FI)
22                  If LCase$(FO.Username) = LCase$(Suffix(CS.Username)) Then
23                      FR = GetIDByRank(.Config.ARFriend)
24                      If FR > -1 Then
25                          r = GetRankByID(FR)
                        End If
                    End If
                Next
            End If
        End If
    End With
26  GetAccess = r
    Exit Function
hErr:
    ErrorHandler Err.Number, Err.Description, Erl, "CommandManagement", "GetAccess"
End Function

Public Function IsRank(Rank1 As String, Rank2 As RankingStruct) As Boolean
    IsRank = ((LCase$(Rank1) = LCase$(Rank2.RankName) Or LCase$(Rank1) = LCase$(Rank2.Alias)))
End Function

Private Function BoolYesNo(yn As String) As Boolean
    If UCase$(yn) = "Y" Then BoolYesNo = True Else BoolYesNo = False
End Function
'
'Public Sub SaveRanks()
'On Error GoTo hErr:
'    RankPath = AppData & "Ranks.ini"
'    Dim FF As Integer
'    FF = FreeFile
'    Open RankPath For Append As #FF
'    Close #FF
'    Open RankPath For Output As #FF
'        Dim I As Integer, Temp As String
'        For I = 0 To UBound(Ranking)
'            With Ranking(I)
'            If LenB(.RankName) > 0 Then
'                Print #FF, "[" & Ranking(I).RankName & "]"
'                Print #FF, "Flagged      = " & YesNo(.Flagged)
'                Print #FF, "PatternMatch = " & YesNo(.PatternMatch)
'                Print #FF, "HasColor     = " & YesNo(.HasColor)
'                Print #FF, "Color        = " & Color2Hex(CStr(.Color))
'                Print #FF, "Safe         = " & YesNo(.Safe)
'                Print #FF, "UserGroup    = " & YesNo(.UserGroup)
'                Temp = .Alias
'                    If LenB(Temp) > 0 Then Print #FF, "Alias        = " & Temp
'                Temp = Join(.Inherits, "; ")
'                    If LenB(Temp) > 0 Then Print #FF, "Inherits     = " & Temp
'                Temp = Join(.Manages, "; ")
'                    If LenB(Temp) > 0 Then Print #FF, "Manages      = " & Temp
'                Temp = .Message
'                    If LenB(Temp) > 0 Then Print #FF, "Message      = " & Temp
'                Print #FF, vbNS
'
'                If LenB(.Commands(0)) Then
'                    Dim FF2 As Integer, CommPath As String
'                    FF2 = FreeFile
'                    CommPath = AppData & "\Commands\" & Ranking(I).RankName & ".ini"
'                    Open CommPath For Append As #FF2
'                    Close #FF2
'                    Open CommPath For Output As #FF2
'                        Print #FF2, Join(.Commands, vbNewLine)
'                    Close #FF2
'                End If
'            End If
'            End With
'        Next
'    Close #FF
'    Exit Sub
'hErr:
'End Sub

Private Function StringFormat(ByVal Text As String, ParamArray Args() As Variant) As String
    Dim i As Integer
    For i = 0 To UBound(Args)
        Text = Replace$(Text, "{" & i & "}", Args(i))
    Next
    Text = Replace$(Text, "'", """")
    Text = Replace$(Text, "\n", vbNewLine)
    Text = Replace$(Text, "\t", vbTab)
    StringFormat = Text
End Function

Public Sub SaveRanksXML()
    Dim xmlFile As String, xmlDoc As New DOMDocument

'    xmlFile = AppData & "Ranks.xml"

'    xmlDoc.loadXML "<Ranks></Ranks>"
'    xmlDoc.preserveWhiteSpace = True
'    xmlDoc.async = False

'    Dim Child As IXMLDOMNode, Attr() As IXMLDOMAttribute, Node() As IXMLDOMElement

    Dim OutStr As String
    OutStr = "<Ranks>"
    Dim x As Integer
    For x = 0 To UBound(Ranking)
        'ReDim Attr(7), Node(3)

        OutStr = OutStr & StringFormat("\n\t<Rank ID='{0}' Alias='{1}' Color='{2}' Flagged='{3}' Group='{4}' " & _
            "HasColor='{5}' Pattern='{6}' Safe='{7}'>\n\t\t" & _
            "<Message>{8}</Message>\n\t\t" & _
            "<Manages>{9}</Manages>\n\t\t" & _
            "<Inherits>{10}</Inherits>\n\t\t" & _
            "<Commands>{11}</Commands>\n</Rank>\n", _
            Ranking(x).RankName, _
            Ranking(x).Alias, _
            Color2Hex(CStr(Ranking(x).Color)), _
            YesNo(Ranking(x).Flagged), _
            YesNo(Ranking(x).UserGroup), _
            YesNo(Ranking(x).HasColor), _
            YesNo(Ranking(x).PatternMatch), _
            YesNo(Ranking(x).Safe), _
            Ranking(x).Message, _
            Join(Ranking(x).Manages, ", "), _
            Join(Ranking(x).Inherits, ", "), _
            Join(Ranking(x).Commands, ", "))
'
'        Set Child = xmlDoc.createElement("Rank")
'
'        Set Attr(0) = xmlDoc.createAttribute("ID"): Attr(0).Text = Ranking(X).RankName
'        Set Attr(1) = xmlDoc.createAttribute("Alias"): Attr(1).Text = Ranking(X).Alias
'        Set Attr(2) = xmlDoc.createAttribute("Color"): Attr(2).Text = Color2Hex(CStr(Ranking(X).Color))
'        Set Attr(3) = xmlDoc.createAttribute("Flagged"): Attr(3).Text = YesNo(Ranking(X).Flagged)
'        Set Attr(4) = xmlDoc.createAttribute("Group"): Attr(4).Text = YesNo(Ranking(X).UserGroup)
'        Set Attr(5) = xmlDoc.createAttribute("HasColor"): Attr(5).Text = YesNo(Ranking(X).HasColor)
'        Set Attr(6) = xmlDoc.createAttribute("Pattern"): Attr(6).Text = YesNo(Ranking(X).PatternMatch)
'        Set Attr(7) = xmlDoc.createAttribute("Safe"): Attr(7).Text = YesNo(Ranking(X).Safe)
'
'        Set Node(0) = xmlDoc.createElement("Message"): Node(0).Text = Ranking(X).Message
'        Set Node(1) = xmlDoc.createElement("Manages"): Node(1).Text = Join(Ranking(X).Manages, ", ")
'        Set Node(2) = xmlDoc.createElement("Inherits"): Node(2).Text = Join(Ranking(X).Inherits, ", ")
'        Set Node(3) = xmlDoc.createElement("Commands"): Node(3).Text = Join(Ranking(X).Commands, ", ")
'
'        xmlDoc.childNodes(0).appendChild Child
'        With xmlDoc.childNodes(0).lastChild
'            Dim I As Integer
'            For I = 0 To UBound(Attr)
'                .Attributes.setNamedItem Attr(I)
'            Next
'            For I = 0 To UBound(Node)
'                .appendChild Node(I)
'            Next
'
'            '.childNodes(0).appendChild (xmlDoc.createElement("Message"))
'        End With
    Next
    
    OutStr = OutStr & "</Ranks>"
    xmlDoc.loadXML OutStr
    xmlDoc.Save AppData & "Ranks.xml"

End Sub

Public Sub LoadRanksXML()
On Error Resume Next
    Dim XY As Integer, xmlFile As String, xmlDoc As New DOMDocument, xmlNodes As IXMLDOMNodeList, xmlNode As IXMLDOMNode
    xmlFile = AppData & "Ranks.xml"
    xmlDoc.Load xmlFile
    For XY = frmBotMenu.mnuRank.UBound To 1 Step -1
        Unload frmBotMenu.mnuRank(XY)
    Next
    frmBotMenu.mnuRank(0).Caption = vbNS
    If xmlDoc.parseError.errorCode <> 0 Then
        MsgBox "Error: Ranks.xml is missing!", vbExclamation
        Exit Sub
    End If
    Set xmlNodes = xmlDoc.documentElement.getElementsByTagName("Rank")
    ReDim Ranking(0)
    If xmlNodes.Length > 0 Then
        For Each xmlNode In xmlNodes
            Dim ID As String, Alias As String, Color As Long, _
                Flagged As Boolean, Group As Boolean, _
                Pattern As Boolean, Safe As Boolean, HasColor As Boolean, _
                Message As String, Inherits() As String, _
                Manages() As String, Commands() As String

            ID = xmlNode.Attributes.getNamedItem("ID").Text
            Alias = xmlNode.Attributes.getNamedItem("Alias").Text
            Color = Hex2Color(xmlNode.Attributes.getNamedItem("Color").Text)
            Flagged = (xmlNode.Attributes.getNamedItem("Flagged").Text = "Y")
            Group = (xmlNode.Attributes.getNamedItem("Group").Text = "Y")
            Pattern = (xmlNode.Attributes.getNamedItem("Pattern").Text = "Y")
            Safe = (xmlNode.Attributes.getNamedItem("Safe").Text = "Y")
            HasColor = (xmlNode.Attributes.getNamedItem("HasColor").Text = "Y")

            If xmlNode.hasChildNodes Then
                Dim xmlChild As IXMLDOMNode
                For Each xmlChild In xmlNode.childNodes
                    Select Case xmlChild.nodeName
                    Case "Message"
                        Message = xmlChild.Text
                    Case "Inherits"
                        Inherits = Split(xmlChild.Text, ", ")
                    Case "Commands"
                        Commands = Split(xmlChild.Text, ", ")
                    Case "Manages"
                        Manages = Split(xmlChild.Text, ", ")
                    End Select
                Next
            End If
            
            AddRanking ID, Alias, Commands, _
                Inherits, Manages, Group, _
                Flagged, Pattern, Safe, _
                Message, HasColor, Color

            If Group Then
                If LenB(frmBotMenu.mnuRank(0).Caption) = 0 Then
                    frmBotMenu.mnuRank(0).Caption = ID
                Else
                    Load frmBotMenu.mnuRank(frmBotMenu.mnuRank.Count)
                    frmBotMenu.mnuRank(frmBotMenu.mnuRank.UBound).Caption = ID
                End If
            End If
        Next
    End If
End Sub

Public Sub LoadRanks()
On Error GoTo hErr:
    RankPath = AppData & "Ranks.ini"
    ReDim Ranking(0)
    Dim TS As TextStream, Content As String, Section As String, Flagged As Boolean, Safe As Boolean, UserGroup As Boolean, PatternMatch As Boolean, _
        Inherits() As String, Commands() As String, Manages() As String, Alias As String, Message As String, XY As Integer, HasColor As Boolean, Color As Long

    Dim FSO As New FileSystemObject
1   Set TS = FSO.OpenTextFile(RankPath, ForReading, True)
    Set FSO = Nothing
2   Do Until TS.AtEndOfStream Or Err
3       Content = TS.ReadLine()
4       If LenB(Content) <> 0 Then
5           If Left$(Content, 1) = "[" And Right$(Content, 1) = "]" Then
6               If LenB(Section) <> 0 Then
                    Dim K As Integer, CF As String, CL As String
                    CF = AppData & "\Commands\" & Section & ".ini"
                    K = FreeFile
                    ReDim Commands(0)
                    If FSO.FileExists(CF) Then
                        Open CF For Input As #K
                        Do Until EOF(K)
                        Line Input #K, CL
                            If LenB(CL) > 0 Then
                                If LenB(Commands(0)) Then ReDim Preserve Commands(UBound(Commands) + 1)
                                Commands(UBound(Commands)) = CL
                            End If
                        Loop
                        Close #K
                    End If
7                   AddRanking Section, Alias, Commands, Inherits, Manages, UserGroup, Flagged, PatternMatch, Safe, Message, HasColor, Color
                    If UserGroup Then
                        If LenB(frmBotMenu.mnuRank(0).Caption) = 0 Then
                            frmBotMenu.mnuRank(0).Caption = Section
                        Else
                            Load frmBotMenu.mnuRank(frmBotMenu.mnuRank.Count)
                            frmBotMenu.mnuRank(frmBotMenu.mnuRank.UBound).Caption = Section
                        End If
                    End If
                End If
8               Section = Mid$(Content, 2, Len(Content) - 2)
                Flagged = False
                HasColor = False
                Color = vbWhite
                PatternMatch = False
                Safe = True
                UserGroup = True
9               ReDim Commands(0), Inherits(0), Manages(0)
                Message = vbNS
                Alias = vbNS
            End If

            If LenB(Section) <> 0 Then
                If Left$(Content, 1) <> "/" Then
                    If InStrB(Content, "=") <> 0 Then
                        Dim Splt() As String
                        Splt() = Split(Content, "=", 2)
                        Select Case UCase$(Trim$(Splt(0)))
                        Case "ALIAS"
                            Alias = Trim$(Splt(1))
                        Case "MESSAGE"
                            Message = Trim$(Splt(1))
                        Case "USERGROUP"
                            UserGroup = BoolYesNo(Trim$(Splt(1)))
                        Case "FLAGGED"
                            Flagged = BoolYesNo(Trim$(Splt(1)))
                        Case "PATTERNMATCH"
                            PatternMatch = BoolYesNo(Trim$(Splt(1)))
                        Case "SAFE"
                            Safe = BoolYesNo(Trim$(Splt(1)))
                        Case "INHERITS"
12                           Inherits = Split(Trim$(Splt(1)), "; ")
                        Case "MANAGES"
13                           Manages = Split(Trim$(Splt(1)), "; ")
                        Case "HASCOLOR"
                            HasColor = BoolYesNo(Trim$(Splt(1)))
                        Case "COLOR"
                            Color = Hex2Color(Trim$(Splt(1)))
                        End Select
                    End If
                End If
            End If
        End If
    Loop
    If LenB(Section) <> 0 Then
        CF = AppData & "\Commands\" & Section & ".ini"
        K = FreeFile
        ReDim Commands(0)
        If FSO.FileExists(CF) Then
            Open CF For Input As #K
            Do Until EOF(K)
            Line Input #K, CL
                If LenB(CL) > 0 Then
                    If LenB(Commands(0)) Then ReDim Preserve Commands(UBound(Commands) + 1)
                    Commands(UBound(Commands)) = CL
                End If
            Loop
            Close #K
        End If
14      AddRanking Section, Alias, Commands, Inherits, Manages, UserGroup, Flagged, PatternMatch, Safe, Message, HasColor, Color
    End If
    TS.Close
    Exit Sub
hErr:
    ErrorHandler Err.Number, Err.Description, Erl, "Ranking", "Load" & "." & Erl
End Sub

Public Function GetIDByRank(RankOrAlias As String) As Long
    Dim i As Integer
    For i = 0 To UBound(Ranking)
        If LCase$(Ranking(i).RankName) = LCase$(RankOrAlias) Or LCase$(Ranking(i).Alias) = LCase$(RankOrAlias) Then _
            GetIDByRank = i: Exit Function
    Next i
    GetIDByRank = -1
End Function

Public Function GetRankByID(ID As Long) As RankingStruct
    If ID > -1 And ID < UBound(Ranking) + 1 Then
        GetRankByID = Ranking(ID)
    End If
End Function

Public Sub AddRanking(Rank As String, Alias As String, _
    Commands() As String, Inherits() As String, Manages() As String, _
    UserGroup As Boolean, Flagged As Boolean, PatternMatch As Boolean, _
    Safe As Boolean, Message As String, HasColor As Boolean, Color As Long)
    
    Dim Index As Integer
    If LenB(Ranking(0).RankName) = 0 Then
        Index = 0
    Else
        ReDim Preserve Ranking(UBound(Ranking) + 1)
        Index = UBound(Ranking)
    End If
    
    With Ranking(Index)
        .HasColor = HasColor
        .Color = Color
        .RankName = Replace$(Rank, " ", vbNS)
        .Alias = Alias
        .PatternMatch = PatternMatch
        .Safe = Safe
        .Flagged = Flagged
        .UserGroup = UserGroup
        .Message = Message
        If Not ArrayInit(Not Commands) Then
            ReDim .Commands(0)
        Else
            .Commands = Commands
        End If
        If Not ArrayInit(Not Inherits) Then
            ReDim .Inherits(0)
        Else
            .Inherits = Inherits
        End If
        If Not ArrayInit(Not Manages) Then
            ReDim .Manages(0)
        Else
            .Manages = Manages
        End If
    End With
End Sub

Public Function RankInherited(YourRank As RankingStruct, TheirRank As RankingStruct) As Boolean
    If LenB(YourRank.RankName) = 0 Then Exit Function
    Dim i As Integer
    For i = 0 To UBound(YourRank.Inherits)
        If IsRank(YourRank.Inherits(i), TheirRank) Then
            RankInherited = True
            Exit Function
        End If
    Next i
End Function

Public Function RankManaged(YourRank As RankingStruct, TheirRank As RankingStruct) As Boolean
    If LenB(YourRank.RankName) = 0 Then Exit Function
    Dim i As Integer
    For i = 0 To UBound(YourRank.Manages)
        If IsRank(YourRank.Manages(i), TheirRank) Then
            RankManaged = True
            Exit Function
        End If
    Next i
End Function

Public Function GetRanking(Rank As String) As RankingStruct
    Dim i As Integer
    For i = 0 To UBound(Ranking)
        If IsRank(Rank, Ranking(i)) Then
            GetRanking = Ranking(i)
            Exit Function
        End If
    Next i
End Function

Public Function RankingIndex(Rank As String) As Integer
    Dim i As Integer
    For i = 0 To UBound(Ranking)
        If IsRank(Rank, Ranking(i)) Then
            RankingIndex = i
            Exit Function
        End If
    Next i
End Function

Public Function RankingExists(Rank As String) As Boolean
    Dim i As Integer
    For i = 0 To UBound(Ranking)
        If IsRank(Rank, Ranking(i)) Then
            RankingExists = True
            Exit Function
        End If
    Next i
End Function

Public Function RankingMessage(Rank As String) As String
    Dim i As Integer
    For i = 0 To UBound(Ranking)
        If IsRank(Rank, Ranking(i)) Then
            RankingMessage = Ranking(i).Message
            Exit Function
        End If
    Next i
End Function

Public Function CommandExists(ByVal Index As Integer, ByVal Command As String) As Boolean
    If LenB(Command) = 0 Then Exit Function
    CommandExists = Not frmBot.Bot(Index).Commands.OpenCommand(Command) Is Nothing
End Function

Public Function CommandDefined(ByVal Command As String, Optional Index As Integer = -1) As Boolean
    Dim i As Integer, Cmd As String, cmdAlias As String
    Command = LCase$(Command)
    GetCommandAlias Command, Cmd, cmdAlias, Index
    If Len(Cmd) > 0 Then
        For i = 0 To UBound(Ranking)
            If Len(Ranking(i).RankName) > 0 Then
                Dim x As Integer
                For x = 0 To UBound(Ranking(i).Commands)
                    If LenB(Ranking(i).Commands(x)) Then
                        If Cmd = LCase$(Ranking(i).Commands(x)) Then
                            CommandDefined = True
                            Exit Function
                        End If
                        If Len(cmdAlias) > 0 Then
                            If cmdAlias = LCase$(Ranking(i).Commands(x)) Then
                                CommandDefined = True
                                Exit Function
                            End If
                        End If
                    End If
                Next x
            End If
        Next i
    End If
    CommandDefined = False
End Function

Public Function CommandRank(ByVal Command As String, Optional Index As Integer = -1) As String
    Dim i As Integer, J As Integer, Cmd As String, cmdAlias As String
    Command = LCase$(Command)
    GetCommandAlias Command, Cmd, cmdAlias, Index
    If Len(Cmd) > 0 Then
        For i = 0 To UBound(Ranking)
            If Len(Ranking(i).RankName) <> 0 Then
                For J = 0 To UBound(Ranking(i).Commands)
                    If Len(cmdAlias) > 0 Then
                        If cmdAlias = LCase$(Ranking(i).Commands(J)) Then
                            CommandRank = Ranking(i).RankName
                            Exit Function
                        End If
                    End If
                    If Cmd = LCase$(Ranking(i).Commands(J)) Then
                        CommandRank = Ranking(i).RankName
                        Exit Function
                    End If
                Next J
            End If
        Next i
    End If
    CommandRank = "<Unranked>"
End Function

Public Function GetCommandAlias(ByVal Value As String, ByRef Command As String, ByRef Alias As String, Optional Index As Integer = -1) As String
On Error Resume Next
    Dim CmdObj As objCmd, B As BNCS
    If Index = -1 Then
        For Each B In frmBot.Bot
            If B.IsLoaded Then
                Set CmdObj = B.Commands.OpenCommand(Value)
                If Not CmdObj Is Nothing Then
                    Command = CmdObj.Cmd
                    Alias = CmdObj.Alias
                    Exit For
                End If
            End If
        Next
    Else
        Set CmdObj = frmBot.Bot(Index).Commands.OpenCommand(Value)
        If Not CmdObj Is Nothing Then
            Command = CmdObj.Cmd
            Alias = CmdObj.Alias
        End If
    End If
End Function

Public Function CommandCount(Rank As String) As Long
    Dim i As Integer, x As Integer, y As Integer, CC As Long
    For i = 0 To UBound(Ranking)
        If Len(Ranking(i).RankName) <> 0 Then
            If IsRank(Rank, Ranking(i)) Then
                CC = CC + UBound(Ranking(i).Commands()) + 1
                For x = 0 To UBound(Ranking(i).Inherits)
                    For y = 0 To UBound(Ranking)
                        If IsRank(Ranking(i).Inherits(x), Ranking(y)) Then
                            CC = CC + UBound(Ranking(y).Commands()) + 1
                        End If
                    Next y
                Next x
            End If
        End If
    Next i
    CommandCount = CC
End Function

Public Function CommandCapable(ByVal Command As String, Rank As String, Optional Index As Integer = -1, Optional TryAlias As Boolean = True) As Boolean
    Dim i As Integer, Cmd As String, cmdAlias As String
    Command = LCase$(Command)
    If TryAlias = True Then
        GetCommandAlias Command, Cmd, cmdAlias, Index
    Else
        Cmd = Command
    End If
    If Len(Cmd) > 0 Then
        For i = 0 To UBound(Ranking)
            If Len(Ranking(i).RankName) <> 0 Then
                If IsRank(Rank, Ranking(i)) Then
                    Dim x As Integer, y As Integer, Z As Integer
                    For x = 0 To UBound(Ranking(i).Commands)
                        If Len(Ranking(i).Commands(x)) > 0 Then
                            If Cmd = LCase$(Ranking(i).Commands(x)) Then
                                CommandCapable = True
                                Exit Function
                            End If
                            If Len(cmdAlias) > 0 Then
                                If cmdAlias = LCase$(Ranking(i).Commands(x)) Then
                                    CommandCapable = True
                                    Exit Function
                                End If
                            End If
                        End If
                    Next x
                    For x = 0 To UBound(Ranking(i).Inherits)
                        For y = 0 To UBound(Ranking)
                            If IsRank(Ranking(i).Inherits(x), Ranking(y)) Then
                                For Z = 0 To UBound(Ranking(y).Commands)
                                    If Len(Ranking(y).Commands(Z)) > 0 Then
                                        If Cmd = LCase$(Ranking(y).Commands(Z)) Then
                                            CommandCapable = True
                                            Exit Function
                                        End If
                                        If Len(cmdAlias) > 0 Then
                                            If cmdAlias = LCase$(Ranking(y).Commands(Z)) Then
                                                CommandCapable = True
                                                Exit Function
                                            End If
                                        End If
                                    End If
                                Next Z
                            End If
                        Next y
                    Next x
                End If
            End If
        Next i
    End If
    CommandCapable = False
End Function
