Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local term = require("term")
- local internet = component.internet
- local keyboard = require("keyboard")
- local gpu = component.gpu
- -- Telnet Constants (Handshake protocol)
- local IAC, DONT, DO, WONT, WILL = "\255", "\254", "\253", "\252", "\251"
- local SB, SE, IS, SEND, AYT = "\250", "\240", "\0", "\1", "\246"
- local BINARY, ECHO, TTYPE, NAWS, TSPEED, ENVIRON = "\0", "\1", "\24", "\31", "\32", "\36"
- -- CP437 Mapping (Extended set 127-255)
- local cp437 = {[127]="⌂", [128]="Ç", [129]="ü", [130]="é", [131]="â", [132]="ä", [133]="à", [134]="å", [135]="ç", [136]="ê", [137]="ë", [138]="è", [139]="ï", [140]="î", [141]="ì", [142]="Ä", [143]="Å", [144]="É", [145]="æ", [146]="Æ", [147]="ô", [148]="ö", [149]="ò", [150]="û", [151]="ù", [152]="ÿ", [153]="Ö", [154]="Ü", [155]="¢", [156]="£", [157]="¥", [158]="₧", [159]="ƒ", [160]="á", [161]="í", [162]="ó", [163]="ú", [164]="ñ", [165]="Ñ", [166]="ª", [167]="º", [168]="¿", [169]="⌐", [170]="¬", [171]="½", [172]="¼", [173]="¡", [174]="«", [175]="»", [176]="░", [177]="▒", [178]="▓", [179]="│", [180]="┤", [181]="╡", [182]="╢", [183]="╖", [184]="╕", [185]="╣", [186]="║", [187]="╗", [188]="╝", [189]="╜", [190]="╛", [191]="┐", [192]="└", [193]="┴", [194]="┬", [195]="├", [196]="─", [197]="┼", [198]="╞", [199]="╟", [200]="╚", [201]="╔", [202]="╩", [203]="╦", [204]="╠", [205]="═", [206]="╬", [207]="╧", [208]="╨", [209]="╤", [210]="╥", [211]="╙", [212]="╘", [213]="╒", [214]="₧", [215]="╫", [216]="╪", [217]="┘", [218]="┌", [219]="█", [220]="▄", [221]="▌", [222]="▐", [223]="▀", [224]="α", [225]="ß", [226]="Γ", [227]="π", [228]="Σ", [229]="σ", [230]="µ", [231]="τ", [232]="Φ", [233]="Θ", [234]="Ω", [235]="δ", [236]="∞", [237]="φ", [238]="ε", [239]="∩", [240]="≡", [241]="±", [242]="≥", [243]="≤", [244]="⌠", [245]="⌡", [246]="÷", [247]="≈", [248]="°", [249]="∙", [250]="·", [251]="√", [252]="ⁿ", [253]="²", [254]="■", [255]=" "}
- -- Palette Generation
- local palette = {[0]=0x000000, 0xAA0000, 0x00AA00, 0xAA5500, 0x0000AA, 0xAA00AA, 0x00AAAA, 0xAAAAAA, 0x555555, 0xFF5555, 0x55FF55, 0xFFFF55, 0x5555FF, 0xFF55FF, 0x55FFFF, 0xFFFFFF}
- for r=0,5 do for g=0,5 do for b=0,5 do table.insert(palette, (r*51*65536) + (g*51*256) + (b*51)) end end end
- -- State and Formatting
- local state = { mode = "TEXT", params = {}, curr = "", private = false }
- local style = { fg = 7, bg = 0, bold = false, inv = false }
- local lastFG, lastBG = -1, -1
- local buf = ""
- --- RENDERING CORE ---
- local function apply()
- local f, b = style.fg, style.bg
- local fg = (style.bold and f < 8) and palette[f+8] or palette[f]
- local bg = palette[b]
- if style.inv then fg, bg = bg, fg end
- if fg ~= lastFG then gpu.setForeground(fg or 0xFFFFFF); lastFG = fg end
- if bg ~= lastBG then gpu.setBackground(bg or 0x000000); lastBG = bg end
- end
- local function flush() if #buf > 0 then io.write(buf); buf = "" end end
- local function handleSGR()
- flush()
- if #state.params == 0 then table.insert(state.params, 0) end
- local i = 1
- while i <= #state.params do
- local p = state.params[i]
- if p == 0 then style.bold, style.inv, style.fg, style.bg = false, false, 7, 0
- elseif p == 1 then style.bold = true
- elseif p == 7 then style.inv = true
- elseif p == 38 or p == 48 then
- local val = state.params[i+2]; if p == 38 then style.fg = val else style.bg = val end
- i = i + 2
- elseif p >= 30 and p <= 37 then style.fg = p - 30
- elseif p >= 40 and p <= 47 then style.bg = p - 40
- elseif p >= 90 and p <= 97 then style.fg = p - 82
- end
- i = i + 1
- end
- apply()
- end
- local function parse(char)
- if state.mode == "TEXT" then
- if char == "\27" then flush(); state.mode = "ESC"
- elseif char == "\r" then flush(); local _, y = term.getCursor(); term.setCursor(1, y)
- elseif char == "\n" then flush(); io.write("\n")
- elseif char == "\b" then flush(); local x, y = term.getCursor(); term.setCursor(math.max(1, x-1), y)
- else local b = char:byte(); buf = buf .. (cp437[b] or (b >= 32 and char or "")) end
- elseif state.mode == "ESC" then
- if char == "[" then state.mode = "CSI"; state.params = {}; state.curr = ""; state.private = false
- else state.mode = "TEXT" end
- elseif state.mode == "CSI" then
- if char == "?" then state.private = true
- elseif char:match("%d") then state.curr = state.curr .. char
- elseif char == ";" then table.insert(state.params, tonumber(state.curr) or 0); state.curr = ""
- else
- table.insert(state.params, tonumber(state.curr) or 0)
- local p1, p2 = state.params[1] or 1, state.params[2] or 1
- if char == "m" then handleSGR()
- elseif char == "H" or char == "f" then term.setCursor(p2, p1)
- elseif char == "A" then term.setCursor(term.getCursor(), math.max(1, select(2, term.getCursor()) - p1))
- elseif char == "B" then term.setCursor(term.getCursor(), select(2, term.getCursor()) + p1)
- elseif char == "C" then term.setCursor(term.getCursor() + p1, select(2, term.getCursor()))
- elseif char == "D" then term.setCursor(math.max(1, term.getCursor() - p1), select(2, term.getCursor()))
- elseif char == "J" then
- local w, h = gpu.getResolution(); local x, y = term.getCursor()
- if p1 == 2 then term.clear()
- elseif p1 == 0 then gpu.fill(x, y, w-x+1, 1, " "); if y < h then gpu.fill(1, y+1, w, h-y, " ") end end
- elseif char == "K" then
- local x, y = term.getCursor(); local w, _ = gpu.getResolution()
- if p1 == 0 then gpu.fill(x, y, w-x+1, 1, " ")
- elseif p1 == 2 then gpu.fill(1, y, w, 1, " ") end
- end
- state.mode = "TEXT"
- end
- end
- end
- --- TELNET NEGOTIATION ---
- local function handleTelnet(conn, cmd)
- local command = cmd:sub(2,2)
- local option = cmd:sub(3,3)
- if command == DO then
- if option == TTYPE then conn.write(IAC .. WILL .. TTYPE)
- elseif option == BINARY then conn.write(IAC .. WILL .. BINARY)
- elseif option == NAWS then
- local w, h = gpu.getResolution()
- conn.write(IAC .. WILL .. NAWS .. IAC .. SB .. NAWS .. string.char(math.floor(w/256), w%256, math.floor(h/256), h%256) .. IAC .. SE)
- elseif option == TSPEED then conn.write(IAC .. WILL .. TSPEED)
- elseif option == ENVIRON then conn.write(IAC .. WILL .. ENVIRON)
- else conn.write(IAC .. WONT .. option) end
- elseif command == WILL then
- if option == BINARY or option == ECHO then conn.write(IAC .. DO .. option) end
- elseif command == AYT then
- conn.write(" ") -- Reply to AYT probe
- elseif command == SB then
- if option == TTYPE then
- conn.write(IAC .. SB .. TTYPE .. IS .. "xterm-256color" .. IAC .. SE)
- elseif option == TSPEED then
- conn.write(IAC .. SB .. TSPEED .. IS .. "38400,38400" .. IAC .. SE)
- end
- end
- end
- --- MAIN CONNECTION ---
- local function connect(host, port)
- local conn = internet.connect(host, port)
- if not conn then return end
- while not conn.finishConnect() do os.sleep(0.05) end
- -- Force start the handshake
- conn.write(IAC .. WILL .. BINARY)
- conn.write(IAC .. WILL .. TTYPE)
- conn.write(IAC .. WILL .. NAWS)
- conn.write(IAC .. WILL .. TSPEED)
- local telnetBuf = ""
- while true do
- local data = conn.read(8192)
- if data then
- telnetBuf = telnetBuf .. data
- while true do
- local s, e = telnetBuf:find(IAC .. "[^" .. IAC .. "][^" .. IAC .. "]")
- if not s then s, e = telnetBuf:find(IAC .. IAC) end
- if s then
- handleTelnet(conn, telnetBuf:sub(s, e))
- telnetBuf = telnetBuf:sub(1, s-1) .. telnetBuf:sub(e+1)
- else break end
- end
- for i=1, #telnetBuf do parse(telnetBuf:sub(i,i)) end
- flush(); io.flush(); telnetBuf = ""
- end
- local ev, _, char, code = event.pull(0)
- if ev == "key_down" then
- if char == 0 and code == 46 then break -- Ctrl+C fallback
- elseif code == 28 then conn.write("\r\n")
- elseif code == 14 then conn.write("\b")
- elseif char > 0 then conn.write(string.char(char)) end
- elseif ev == "interrupted" then break end
- end
- conn.close()
- end
- -- Start Script
- term.clear()
- print("OC-TELNET 3 | ULTRA-HANDSHAKE MODE")
- print("Target Host/Port:")
- local inp = io.read()
- if inp then
- local h, p = inp:match("(%S+)%s+(%d+)")
- if h and p then connect(h, tonumber(p)) end
- end
Advertisement
Add Comment
Please, Sign In to add comment