' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Meta
'

OPTION _EXPLICIT

$SCREENHIDE
$CONSOLE
_DEST _CONSOLE
$CONSOLE:ONLY

DO UNTIL _SCREENEXISTS: LOOP
_TITLE "QLiza64"

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Dependencies: *.bi
'

REM $Include: 'eliza.bi'

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Load arguments and set running mode.
'
REDIM ArgumentList(100) AS STRING
ArgumentList(1) = "10314"
ArgumentList(2) = "10315"
REDIM _PRESERVE ArgumentList(2)

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Line feed and carriage return.
'
DIM SHARED LF$
DIM SHARED CR$
LF$ = CHR$(10)
CR$ = CHR$(13)

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Main text buffer.
'
DIM SHARED TextBuffer(10000) AS STRING
DIM SHARED TextBufferCount AS INTEGER
TextBufferCount = 0

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Prime and begin main loop.
'

CALL MainHost(ArgumentList())

SYSTEM

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalProcess$ (TheRequestIn AS STRING, TheKeyIn AS STRING)
    DIM TheReturn AS STRING
    DIM TheKey AS STRING
    DIM TheRequest AS STRING
    DIM temp AS STRING
    TheReturn = ""
    TheKey = TheKeyIn
    TheRequest = TheRequestIn
    IF (LEFT$(TheRequest, LEN(TheKey)) = TheKey) THEN
        temp = TheRequest
        temp = (RIGHT$(temp, LEN(temp) - LEN(TheKey)))
        SELECT CASE TheKey
            CASE "#="
                PRINT "Processing...";
                temp = ShellProcess$(temp, 128, 10)
                PRINT " Done."
            CASE "' "
                temp = Eliza$(temp)
        END SELECT
    ELSE
        temp = TheRequest
    END IF
    TheReturn = temp
    InternalProcess$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ShellProcess$ (TheInputIn AS STRING, TheOutputWidthIn AS INTEGER, TheTimeoutIn AS DOUBLE)
    DIM TheReturn AS STRING
    DIM TheInput AS STRING
    DIM TheOutputWidth AS INTEGER
    DIM TheTimeout AS DOUBLE
    DIM TheFileName AS STRING
    DIM tmp AS STRING
    DIM t AS DOUBLE
    TheInput = TheInputIn
    TheOutputWidth = TheOutputWidthIn
    TheTimeout = TheTimeoutIn
    TheFileName = LEFT$("Rqst" + LTRIM$(RTRIM$(STR$(INT(RND * (10 ^ 6))))), 10) + ".txt"
    IF (_FILEEXISTS(TheFileName)) THEN KILL TheFileName
    TheInput = "external.exe" + " " + CHR$(34) + TheInput + CHR$(34) + " " + TheFileName
    SHELL _HIDE TheInput
    t = INT(TIMER)
    DO UNTIL _FILEEXISTS(TheFileName)
        _DELAY .25
        IF (INT(TIMER) > t + TheTimeout) THEN EXIT DO
    LOOP
    CALL TextBufferClear
    IF _FILEEXISTS(TheFileName) THEN
        OPEN TheFileName FOR INPUT AS #1
        DO WHILE NOT EOF(1)
            LINE INPUT #1, tmp
            CALL TextBufferAdd(tmp, TheOutputWidth)
        LOOP
        CLOSE #1
        KILL TheFileName
        TheReturn = TextBufferExport$(LF$)
    ELSE
        TheReturn = "Timed out."
    END IF
    ShellProcess$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB MainHost (ArgumentList() AS STRING)
    REDIM LoadedPort(100) AS STRING
    REDIM TheOpenHost(100) AS LONG
    REDIM WorkingConnection(0) AS LONG
    DIM tmp AS LONG
    DIM k AS INTEGER
    FOR k = 1 TO UBOUND(ArgumentList)
        LoadedPort(k) = ArgumentList(k)
    NEXT
    REDIM _PRESERVE LoadedPort(UBOUND(ArgumentList))
    FOR k = 1 TO UBOUND(LoadedPort)
        TheOpenHost(k) = _OPENHOST("TCP/IP:" + LoadedPort(k))
        _DELAY .1
        PRINT "Listening to port: " + LoadedPort(k)
    NEXT
    PRINT "To test server, navigate in browser to: http://127.0.0.1:" + LoadedPort(1)
    PRINT
    REDIM _PRESERVE TheOpenHost(UBOUND(LoadedPort))
    DO
        FOR k = 1 TO UBOUND(TheOpenHost)
            tmp = _OPENCONNECTION(TheOpenHost(k))
            IF (tmp) THEN
                PRINT "New Connection."
                tmp = IterateHost(tmp, 1)
                k = UBOUND(WorkingConnection)
                k = k + 1
                REDIM _PRESERVE WorkingConnection(k)
                WorkingConnection(k) = tmp
            END IF
        NEXT
        IF (UBOUND(WorkingConnection) > 0) THEN
            FOR k = 1 TO UBOUND(WorkingConnection)
                IF (WorkingConnection(k) <> 0) THEN
                    IF (IterateHost(WorkingConnection(k), 1) = 0) THEN
                        WorkingConnection(k) = 0
                        PRINT "Active connection closed."
                    END IF
                END IF
                IF (WorkingConnection(k) <> 0) THEN
                    IF (NOT _CONNECTED(WorkingConnection(k))) THEN
                        WorkingConnection(k) = 0
                        PRINT "Active connection disconnected."
                    END IF
                END IF
            NEXT
        END IF
        _LIMIT 1
    LOOP
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION IterateHost (TheConnectionIn AS LONG, AutoSendIn AS INTEGER)
    DIM TheReturn AS LONG
    DIM ClientConnection AS LONG
    DIM AutoSend AS INTEGER
    DIM ClientInput AS STRING
    DIM ClientMode AS STRING
    DIM WorkingRequest AS STRING
    DIM ProcessTrigger AS STRING
    DIM tmp AS STRING
    DIM k AS INTEGER
    DIM a AS STRING
    DIM b AS STRING
    DIM HTML64Data(10) AS STRING
    ClientConnection = TheConnectionIn
    AutoSend = AutoSendIn
    TheReturn = ClientConnection
    ClientMode = ""
    _DELAY .1
    IF (ClientConnection <> 0) THEN
        ClientInput = GetInput$(ClientConnection, .05)
        IF (LEN(ClientInput) > 0) THEN
            PRINT "Incoming data from: "; _CONNECTIONADDRESS(ClientConnection)
            PRINT "Input length:"; LEN(ClientInput)

            a = "GET /"
            b = " HTTP/1.1"
            k = INSTR(ClientInput, b)
            IF ((ClientMode = "") AND (LEFT$(ClientInput, LEN(a)) = a) AND (k <> 0)) THEN
                ClientMode = "http"
                PRINT "Interpreted as HTTP input."
                WorkingRequest = ClientInput
                WorkingRequest = LEFT$(WorkingRequest, k - 1)
                WorkingRequest = RIGHT$(WorkingRequest, LEN(WorkingRequest) - LEN(a))
                ProcessTrigger = "?q="
                IF (LEFT$(WorkingRequest, LEN(ProcessTrigger)) = ProcessTrigger) THEN
                    WorkingRequest = RIGHT$(WorkingRequest, LEN(WorkingRequest) - LEN(ProcessTrigger))
                    WorkingRequest = LTRIM$(RTRIM$(DecodeURL$(WorkingRequest)))
                    PRINT "Working request: " + WorkingRequest
                ELSE
                    PRINT "No working request."
                END IF
                PRINT "Original input: " + LEFT$(ManageWhiteness$(ClientInput), 50)
                CALL TextBufferClear
                CALL TextBufferAdd("HTTP/1.0 200" + CR$ + LF$ + CR$, 128)
                CALL TextBufferAdd("<!DOCTYPE html>", 128)
                CALL TextBufferModify("", LF$)
                CALL SendBuffer(ClientConnection, 0)

                tmp = WorkingRequest
                tmp = InternalProcess$(tmp, "#=")
                tmp = InternalProcess$(tmp, "' ")
                HTML64Data(1) = WorkingRequest
                HTML64Data(2) = tmp
                tmp = ""

                CALL TextBufferClear
                OPEN "index.html" FOR INPUT AS #1
                DO WHILE NOT EOF(1)
                    LINE INPUT #1, tmp
                    IF ((LEFT$(tmp, 2) = "[[") AND (RIGHT$(tmp, 2) = "]]")) THEN
                        tmp = LEFT$(tmp, LEN(tmp) - 2)
                        tmp = RIGHT$(tmp, LEN(tmp) - 2)
                        k = VAL(tmp)
                        tmp = HTML64Data(k)
                    END IF
                    CALL TextBufferAdd(tmp, 128)
                LOOP
                CLOSE #1
                CALL TextBufferModify("", LF$)
                CALL SendBuffer(ClientConnection, 0)
                CALL TextBufferClear
                PRINT "Sent response."
                PRINT "Done processing HTTP input."
                CLOSE ClientConnection
                PRINT "Connection closed."
                PRINT
                TheReturn = 0
            END IF

        END IF
    END IF
    IterateHost = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION GetInput$ (TheConnectionIn AS LONG, TheDelayIn AS DOUBLE)
    DIM TheReturn AS STRING
    DIM TheConnection AS LONG
    DIM TheDelay AS DOUBLE
    DIM k AS INTEGER
    DIM tmp AS STRING
    TheConnection = TheConnectionIn
    TheDelay = TheDelayIn
    TheReturn = ""
    FOR k = 1 TO 5
        DO
            tmp = ""
            GET TheConnection, , tmp
            _DELAY TheDelay
            IF (LTRIM$(RTRIM$(tmp)) <> "") THEN
                TheReturn = TheReturn + tmp
            END IF
        LOOP UNTIL EOF(TheConnection) = 0
        _DELAY TheDelay
    NEXT
    GetInput$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB SendLive (TheConnectionIn AS LONG, ThePrefixIn AS STRING, TextOutgoingIn AS STRING, TheSuffixIn AS STRING, TheWidthIn AS INTEGER, TheDelayIn AS DOUBLE)
    DIM TheConnection AS LONG
    DIM ThePrefix AS STRING
    DIM TextOutgoing AS STRING
    DIM TheSuffix AS STRING
    DIM TheWidth AS INTEGER
    DIM TheDelay AS DOUBLE
    TheConnection = TheConnectionIn
    ThePrefix = ThePrefixIn
    TextOutgoing = TextOutgoingIn
    TheDelay = TheDelayIn
    TheSuffix = TheSuffixIn
    TheWidth = TheWidthIn
    CALL TextBufferClear
    CALL TextBufferAdd(TextOutgoing, TheWidth)
    CALL TextBufferModify(ThePrefix, TheSuffix)
    CALL SendBuffer(TheConnection, TheDelay)
    CALL TextBufferClear
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB SendBuffer (TheConnectionIn AS LONG, TheDelayIn AS DOUBLE)
    DIM TheConnection AS LONG
    DIM TheDelay AS DOUBLE
    DIM k AS INTEGER
    DIM tmp AS STRING
    TheConnection = TheConnectionIn
    TheDelay = TheDelayIn
    FOR k = 1 TO TextBufferCount
        tmp = TextBuffer(k)
        PUT TheConnection, , tmp
        _DELAY TheDelay
    NEXT
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB TextBufferAdd (TheTextIn AS STRING, TheWidthIn AS INTEGER)
    DIM TheText AS STRING
    DIM TheWidth AS INTEGER
    DIM TextOverfill AS STRING
    DIM TextNextline AS STRING
    DIM k AS INTEGER
    DIM tmp AS STRING
    TheText = TheTextIn
    TheWidth = TheWidthIn
    TextOverfill = ""
    TextNextline = ""

    IF (TheText <> "") THEN
        ' Manage line break(s).
        TheText = ReplaceChars$(TheText, CR$, LF$)
        TheText = ReplaceChars$(TheText, LF$ + LF$, LF$)

        ' If text contains a break, split string into two parts.
        k = INSTR(TheText, LF$)
        IF (k > 0) THEN
            tmp = LEFT$(TheText, k)
            TextNextline = RIGHT$(TheText, LEN(TheText) - k)
            TheText = tmp
        END IF

        ' If text length is over buffer width, break string into two parts.
        k = LEN(TheText)
        IF (k > TheWidth) THEN
            tmp = LEFT$(TheText, TheWidth)
            TextOverfill = RIGHT$(TheText, LEN(TheText) - TheWidth)
            TheText = tmp
        END IF

        ' Add to array.
        TextBufferCount = TextBufferCount + 1
        TextBuffer(TextBufferCount) = TheText

        ' Recurse as needed.
        IF (TextOverfill <> "") THEN
            CALL TextBufferAdd(TextOverfill, TheWidth)
        END IF
        IF (TextNextline <> "") THEN
            CALL TextBufferAdd(TextNextline, TheWidth)
        END IF

    END IF
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB TextBufferModify (ThePrefixIn AS STRING, TheSuffixIn AS STRING)
    DIM ThePrefix AS STRING
    DIM TheSuffix AS STRING
    DIM k AS INTEGER
    ThePrefix = ThePrefixIn
    TheSuffix = TheSuffixIn
    IF (TextBufferCount > 0) THEN
        FOR k = 1 TO TextBufferCount
            TextBuffer(k) = ThePrefix + TextBuffer(k) + TheSuffix
        NEXT
    END IF
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

SUB TextBufferClear
    DIM k AS INTEGER
    IF (TextBufferCount > 0) THEN
        FOR k = 1 TO TextBufferCount
            TextBuffer(k) = ""
        NEXT
    END IF
    TextBufferCount = 0
END SUB

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION TextBufferExport$ (EOLIn AS STRING)
    DIM TheReturn AS STRING
    DIM EOL AS STRING
    DIM k AS INTEGER
    EOL = EOLIn
    TheReturn = ""
    IF (TextBufferCount > 0) THEN
        FOR k = 1 TO TextBufferCount
            TheReturn = TheReturn + TextBuffer(k)
            IF (k < TextBufferCount) THEN TheReturn = TheReturn + EOL
        NEXT
    END IF
    TextBufferExport$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReplaceChars$ (TheStringIn AS STRING, TheWordIn AS STRING, TheReplacementIn AS STRING)
    DIM TheReturn AS STRING
    DIM TheString AS STRING
    DIM TheWord AS STRING
    DIM TheReplacement AS STRING
    DIM k AS INTEGER
    DIM c AS STRING
    TheString = TheStringIn
    TheWord = TheWordIn
    TheReplacement = TheReplacementIn
    TheReturn = TheString
    IF (INSTR(TheReturn, TheWord) > 0) THEN
        FOR k = 1 TO LEN(TheReturn) - LEN(TheWord) + 1
            c = MID$(TheReturn, k, LEN(TheWord))
            IF (c = TheWord) THEN
                TheReturn = LEFT$(TheReturn, k - 1) + TheReplacement + RIGHT$(TheReturn, LEN(TheReturn) - k - LEN(TheWord) + 1)
                EXIT FOR
            END IF
        NEXT
    END IF
    IF (TheReturn <> TheString) THEN
        TheReturn = ReplaceChars$(TheReturn, TheWord, TheReplacement)
    END IF
    ReplaceChars$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ManageWhiteness$ (TheStringIn AS STRING)
    DIM TheReturn AS STRING
    DIM TheString AS STRING
    DIM QuoteBal AS INTEGER
    DIM k AS INTEGER
    DIM c AS STRING
    TheString = TheStringIn
    TheReturn = ""
    QuoteBal = 0
    FOR k = 1 TO LEN(TheString)
        c = MID$(TheString, k, 1)
        IF ((c <> CHR$(9)) AND (c <> LF$) AND (c <> CR$)) THEN
            TheReturn = TheReturn + c
        END IF
    NEXT
    ManageWhiteness$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION DecodeURL$ (TheStringIn AS STRING)
    DIM TheString AS STRING
    DIM Code1 AS STRING
    DIM Code2 AS STRING
    DIM a AS STRING
    DIM b AS STRING
    TheString = TheStringIn
    Code1 = TheString
    Code2 = TheString
    DO
        a = "+": b = "%20": Code1 = DecodeSubStep$(Code1, a, b)
        IF Code2 = Code1 THEN EXIT DO
        Code2 = Code1
    LOOP
    TheString = Code1
    Code1 = TheString
    Code2 = TheString
    DO
        a = "%22": b = CHR$(34): Code1 = DecodeSubStep$(Code1, a, b)
        a = "%20": b = " ": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%21": b = "!": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%23": b = "#": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%24": b = "$": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%25": b = "%": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%26": b = "&": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%27": b = "'": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%28": b = "(": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%29": b = ")": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2A": b = "*": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2B": b = "+": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2C": b = ",": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2D": b = "-": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2E": b = ".": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%2F": b = "/": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%30": b = "0": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%31": b = "1": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%32": b = "2": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%33": b = "3": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%34": b = "4": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%35": b = "5": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%36": b = "6": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%37": b = "7": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%38": b = "8": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%39": b = "9": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3A": b = ":": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3B": b = ";": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3C": b = "<": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3D": b = "=": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3E": b = ">": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%3F": b = "?": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%40": b = "@": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%41": b = "A": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%42": b = "B": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%43": b = "C": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%44": b = "D": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%45": b = "E": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%46": b = "F": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%47": b = "G": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%48": b = "H": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%49": b = "I": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4A": b = "J": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4B": b = "K": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4C": b = "L": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4D": b = "M": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4E": b = "N": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%4F": b = "O": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%50": b = "P": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%51": b = "Q": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%52": b = "R": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%53": b = "S": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%54": b = "T": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%55": b = "U": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%56": b = "V": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%57": b = "W": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%58": b = "X": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%59": b = "Y": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5A": b = "Z": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5B": b = "[": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5C": b = "\": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5D": b = "]": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5E": b = "^": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%5F": b = "_": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%60": b = "`": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%61": b = "a": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%62": b = "b": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%63": b = "c": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%64": b = "d": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%65": b = "e": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%66": b = "f": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%67": b = "g": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%68": b = "h": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%69": b = "i": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6A": b = "j": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6B": b = "k": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6C": b = "l": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6D": b = "m": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6E": b = "n": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%6F": b = "o": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%70": b = "p": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%71": b = "q": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%72": b = "r": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%73": b = "s": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%74": b = "t": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%75": b = "u": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%76": b = "v": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%77": b = "w": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%78": b = "x": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%79": b = "y": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%7A": b = "z": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%7B": b = "{": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%7C": b = "|": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%7D": b = "}": Code1 = DecodeSubStep$(Code1, a, b)
        a = "%7E": b = "~": Code1 = DecodeSubStep$(Code1, a, b)
        IF Code2 = Code1 THEN EXIT DO
        Code2 = Code1
    LOOP
    DecodeURL$ = Code1
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION DecodeSubStep$ (TheStringIn AS STRING, TheCodeIn AS STRING, TheKeyIn AS STRING)
    DIM TheString AS STRING
    DIM TheCode AS STRING
    DIM TheKey AS STRING
    DIM Temp AS STRING
    DIM c AS INTEGER
    TheString = TheStringIn
    TheCode = TheCodeIn
    TheKey = TheKeyIn
    Temp$ = TheString
    c = INSTR(Temp, TheCode)
    IF (c <> 0) THEN
        Temp$ = LEFT$(Temp$, c - 1) + TheKey + MID$(Temp$, c + LEN(TheCode))
    END IF
    DecodeSubStep$ = Temp$
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
' Dependencies: *.bm
'

REM $Include: 'eliza.bm'

