Advertisement
nonogamer9

OC-TELNET : An Telnet Client For OpenComputers

Aug 7th, 2024 (edited)
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.79 KB | Software | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local internet = component.internet
  5. local computer = require("computer")
  6. local keyboard = require("keyboard")
  7. local gpu = component.gpu
  8.  
  9. local IAC = string.char(255)
  10. local DONT = string.char(254)
  11. local DO = string.char(253)
  12. local WONT = string.char(252)
  13. local WILL = string.char(251)
  14. local SB = string.char(250)
  15. local SE = string.char(240)
  16. local GA = string.char(249)
  17. local EL = string.char(248)
  18. local EC = string.char(247)
  19. local AYT = string.char(246)
  20. local AO = string.char(245)
  21. local IP = string.char(244)
  22. local BREAK = string.char(243)
  23. local DM = string.char(242)
  24. local NOP = string.char(241)
  25.  
  26. local ECHO = string.char(1)
  27. local SUPPRESS_GO_AHEAD = string.char(3)
  28. local TERMINAL_TYPE = string.char(24)
  29. local NAWS = string.char(31)
  30.  
  31. local localEcho = true
  32.  
  33. local function handleTelnetCommand(connection, cmd)
  34.     if cmd:sub(1, 1) == IAC then
  35.         if cmd:len() == 2 then
  36.             local command = cmd:sub(2, 2)
  37.             if command == GA then
  38.             elseif command == EL then
  39.                 io.write("\27[2K")
  40.             elseif command == EC then
  41.                 io.write("\b \b")
  42.             elseif command == AYT then
  43.                 connection.write("\r\nYes, I'm here\r\n")
  44.             elseif command == AO then
  45.                 io.write("\r\nOutput aborted\r\n")
  46.             elseif command == IP then
  47.                 io.write("\r\nProcess interrupted\r\n")
  48.             elseif command == BREAK then
  49.                 io.write("\r\nBreak received\r\n")
  50.             elseif command == DM then
  51.             elseif command == NOP then
  52.             end
  53.         elseif cmd:len() == 3 then
  54.             local command = cmd:sub(2, 2)
  55.             local option = cmd:sub(3, 3)
  56.             if command == DO then
  57.                 if option == TERMINAL_TYPE then
  58.                     connection.write(IAC .. WILL .. TERMINAL_TYPE)
  59.                 elseif option == NAWS then
  60.                     local w, h = gpu.getResolution()
  61.                     connection.write(IAC .. WILL .. NAWS)
  62.                     connection.write(IAC .. SB .. NAWS .. string.char(math.floor(w / 256)) .. string.char(w % 256) .. string.char(math.floor(h / 256)) .. string.char(h % 256) .. IAC .. SE)
  63.                 else
  64.                     connection.write(IAC .. WONT .. option)
  65.                 end
  66.             elseif command == WILL then
  67.                 if option == ECHO then
  68.                     localEcho = false
  69.                     connection.write(IAC .. DO .. option)
  70.                 elseif option == SUPPRESS_GO_AHEAD then
  71.                     connection.write(IAC .. DO .. option)
  72.                 else
  73.                     connection.write(IAC .. DONT .. option)
  74.                 end
  75.             elseif command == WONT then
  76.                 if option == ECHO then
  77.                     localEcho = true
  78.                 end
  79.             elseif command == SB then
  80.                 local subnegotiation = cmd:sub(4, -2)
  81.                 if option == TERMINAL_TYPE then
  82.                     connection.write(IAC .. SB .. TERMINAL_TYPE .. "\0" .. "ANSI-BBS" .. IAC .. SE)
  83.                 elseif option == NAWS then
  84.                     local w, h = gpu.getResolution()
  85.                     connection.write(IAC .. SB .. NAWS .. string.char(math.floor(w / 256)) .. string.char(w % 256) .. string.char(math.floor(h / 256)) .. string.char(h % 256) .. IAC .. SE)
  86.                 end
  87.             end
  88.         end
  89.         return true
  90.     end
  91.     return false
  92. end
  93.  
  94. local function handleANSI(str)
  95.     local i = 1
  96.     while i <= #str do
  97.         local c = str:sub(i, i)
  98.         if c == "\27" then
  99.             local seq, cmd = str:match("\27%[([%d;]*)([A-Za-z])", i)
  100.             if seq and cmd then
  101.                 local params = {}
  102.                 for param in seq:gmatch("%d+") do
  103.                     table.insert(params, tonumber(param))
  104.                 end
  105.  
  106.                 if #params == 0 then
  107.                     params = {1}
  108.                 end
  109.  
  110.                 if cmd == "H" or cmd == "f" then
  111.                     local x, y = params[2] or 1, params[1] or 1
  112.                     term.setCursor(x, y)
  113.                 elseif cmd == "J" then
  114.                     if params[1] == 2 then
  115.                         term.clear()
  116.                     elseif params[1] == 0 then
  117.                         term.clearLine()
  118.                     end
  119.                 elseif cmd == "K" then
  120.                     term.clearLine()
  121.                 elseif cmd == "A" then
  122.                     local x, y = term.getCursor()
  123.                     term.setCursor(x, y - (params[1] or 1))
  124.                 elseif cmd == "B" then
  125.                     local x, y = term.getCursor()
  126.                     term.setCursor(x, y + (params[1] or 1))
  127.                 elseif cmd == "C" then
  128.                     local x, y = term.getCursor()
  129.                     term.setCursor(x + (params[1] or 1), y)
  130.                 elseif cmd == "D" then
  131.                     local x, y = term.getCursor()
  132.                     term.setCursor(x - (params[1] or 1), y)
  133.                 elseif cmd == "m" then
  134.                     for _, param in ipairs(params) do
  135.                         if param == 0 then
  136.                             gpu.setForeground(0xFFFFFF)
  137.                             gpu.setBackground(0x000000)
  138.                         elseif param == 1 then
  139.                         elseif param >= 30 and param <= 37 then
  140.                             local colors = {
  141.                                 0x000000, 0xFF0000, 0x00FF00, 0xFFFF00,
  142.                                 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF
  143.                             }
  144.                             gpu.setForeground(colors[param - 29])
  145.                         elseif param >= 40 and param <= 47 then
  146.                             local colors = {
  147.                                 0x000000, 0xFF0000, 0x00FF00, 0xFFFF00,
  148.                                 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF
  149.                             }
  150.                             gpu.setBackground(colors[param - 39])
  151.                         end
  152.                     end
  153.                 end
  154.                 i = i + #seq + 3
  155.             else
  156.                 io.write(c)
  157.                 i = i + 1
  158.             end
  159.         else
  160.             io.write(c)
  161.             i = i + 1
  162.         end
  163.     end
  164. end
  165.  
  166. local function connectTelnet(host, port)
  167.     local connection = internet.connect(host, port)
  168.     if not connection then
  169.         print("Failed to connect to " .. host .. ":" .. port)
  170.         return
  171.     end
  172.  
  173.     print("Connecting to " .. host .. ":" .. port)
  174.     local timeout = 10
  175.     local start = computer.uptime()
  176.     while not connection.finishConnect() do
  177.         if computer.uptime() - start > timeout then
  178.             print("Connection timed out")
  179.             connection.close()
  180.             return
  181.         end
  182.         os.sleep(0.1)
  183.     end
  184.  
  185.     term.clear()
  186.     print("Connected!")
  187.  
  188.     local buffer = ""
  189.     while true do
  190.         local data = connection.read(1024)
  191.         if data then
  192.             buffer = buffer .. data
  193.             while true do
  194.                 local cmdStart, cmdEnd = buffer:find(IAC .. ".?.?")
  195.                 if cmdStart then
  196.                     local cmd = buffer:sub(cmdStart, cmdEnd)
  197.                     if handleTelnetCommand(connection, cmd) then
  198.                         buffer = buffer:sub(1, cmdStart - 1) .. buffer:sub(cmdEnd + 1)
  199.                     else
  200.                         break
  201.                     end
  202.                 else
  203.                     break
  204.                 end
  205.             end
  206.  
  207.             if #buffer > 0 then
  208.                 handleANSI(buffer)
  209.                 io.flush()
  210.                 buffer = ""
  211.             end
  212.         end
  213.  
  214.         local e = {event.pull(0.05)}
  215.         if e[1] == "key_down" then
  216.             local char, code = e[3], e[4]
  217.             if keyboard.isControlDown() and keyboard.isAltDown() and char == 46 then
  218.                 print("\nDisconnecting...")
  219.                 break
  220.             elseif keyboard.isControlDown() then
  221.                 if char >= 1 and char <= 26 then
  222.                     connection.write(string.char(char))
  223.                     if localEcho then
  224.                         io.write("^" .. string.char(char + 64))
  225.                     end
  226.                 end
  227.             elseif code == 28 then
  228.                 connection.write("\r\n")
  229.                 if localEcho then
  230.                     io.write("\r\n")
  231.                 end
  232.             elseif code == 14 then
  233.                 connection.write("\b")
  234.                 if localEcho then
  235.                     local x, y = term.getCursor()
  236.                     if x > 1 then
  237.                         term.setCursor(x - 1, y)
  238.                         term.write(" ")
  239.                         term.setCursor(x - 1, y)
  240.                     end
  241.                 end
  242.             else
  243.                 connection.write(string.char(char))
  244.                 if localEcho then
  245.                     io.write(string.char(char))
  246.                 end
  247.             end
  248.             io.flush()
  249.         end
  250.     end
  251.  
  252.     connection.close()
  253.     print("Disconnected. Press any key to exit.")
  254.     event.pull("key_down")
  255. end
  256.  
  257. local function displayLogo()
  258.     local maxResolution = {gpu.getResolution()}
  259.     local tier = (maxResolution[1] >= 160 and maxResolution[2] >= 50) and 3 or (maxResolution[1] >= 80 and maxResolution[2] >= 25) and 2 or 1
  260.     term.clear()
  261.  
  262.     if tier == 1 then
  263.         print([[
  264.             ░█▀█░█▀▀░░░░░▀█▀░█▀▀░█░░░█▀█░█▀▀░▀█▀
  265.             ░█░█░█░░░▄▄▄░░█░░█▀▀░█░░░█░█░█▀▀░░█░
  266.             ░▀▀▀░▀▀▀░░░░░░▀░░▀▀▀░▀▀▀░▀░▀░▀▀▀░░▀░
  267.         ]])
  268.     else
  269.         print([[
  270. ________________   ___________________________   __________________
  271. __  __ \_  ____/   ___  __/__  ____/__  /___  | / /__  ____/__  __/
  272. _  / / /  / _________  /  __  __/  __  / __   |/ /__  __/  __  /
  273. / /_/ // /___/_____/  /   _  /___  _  /___  /|  / _  /___  _  /
  274. \____/ \____/      /_/    /_____/  /_____/_/ |_/  /_____/  /_/
  275.         ]])
  276.     end
  277.  
  278.     print("OC-TELNET Client made by nonogamer9")
  279. end
  280.  
  281. while true do
  282.     displayLogo()
  283.     print("Enter the host and port to connect (e.g., example.com 23):")
  284.     print("Or type 'exit' to quit the program.")
  285.     local input = io.read()
  286.     if input:lower() == "exit" then
  287.         break
  288.     end
  289.  
  290.     local host, port = input:match("(%S+)%s+(%d+)")
  291.     if host and port then
  292.         connectTelnet(host, tonumber(port))
  293.     else
  294.         print("Invalid input. Please provide a host and port.")
  295.         os.sleep(2)
  296.     end
  297. end
  298.  
  299. print("Thank you for using OC-TELNET. Goodbye!")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement