Advertisement
HydrantHunter

gtHost

Apr 8th, 2014
2,722
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 59.51 KB | None | 0 0
  1. --[[      gtHost       ]]--
  2. --[[      by Dog       ]]--
  3. --[[ aka HydrantHunter ]]--
  4. --[[ pastebin WzrdKVxm ]]--
  5. local gtHver = "2.0.05"
  6. --[[
  7. Tested with/requires:
  8.   - Minecraft 1.6.4+
  9.   - ComputerCraft 1.63+
  10.     - A Wireless Turtle (standard or advanced)
  11.     - gtRemote running on an Advanced Wireless Pocket Computer
  12.  
  13. Special thanks to: Anavrins   (pbkdf2/sha256 hashing)
  14.                    SquidDev   (AES encryption/decryption)
  15.                    Alex Kloss (base64 encoder/decoder)
  16. ]]--
  17. local tArgs = { ... }
  18. --# CONFIGURATION
  19. --# Default Settings
  20. local termX, termY = term.getSize()
  21. local thisCC = tostring(os.getComputerID())
  22. local config = "/data/gtHostCfg"
  23. local gtSettings = {
  24.   name = "gtHost";
  25.   note = "short note";
  26.   color = "I";
  27.   password = false;
  28.   newColors = true;
  29.   hashedPWs = false;
  30. }
  31. local loc = { x = "No GPS Fix", y = "No GPS Fix", z = "No GPS Fix" }
  32. local gtInventory, unlockedClients = { }, { }
  33. unlockedClients.count = 0
  34. local netSide, slotContents = "none", "Unknown"
  35. local client, gtHostKernel
  36. local up, down, forward = false, false, false
  37. local fuelAmount, coal, fuelPercent, turtleFuelLimit, selectedSlot = 0, 0, 0, 0, 1
  38. local lockState, fuelState, dirCheck, redraw, gtRedstone, gtSuccess, shellCommand = false, false, false, false, false, false, false
  39. --# Color Definitions
  40. local white = colors.white
  41. local black = colors.black
  42. local silver = colors.lightGray
  43. local gray = colors.gray
  44. local brown = colors.brown
  45. local yellow = colors.yellow
  46. local orange = colors.orange
  47. local red = colors.red
  48. local magenta = colors.magenta
  49. local purple = colors.purple
  50. local blue = colors.blue
  51. local sky = colors.lightBlue
  52. local cyan = colors.cyan
  53. local lime = colors.lime
  54. local green = colors.green
  55. if not term.isColor() then
  56.   silver = colors.white
  57.   gray = colors.black
  58.   brown = colors.white
  59.   yellow = colors.white
  60.   orange = colors.white
  61.   red = colors.white
  62.   magenta = colors.white
  63.   purple = colors.white
  64.   green = colors.white
  65.   blue = colors.black
  66.   sky = colors.white
  67.   cyan = colors.white
  68.   lime = colors.white
  69.   green = colors.white
  70. end
  71. local colorBurst = {
  72.   P = { "Purple", purple };
  73.   B = { "Blue", blue };
  74.   S = { "Sky", sky };
  75.   G = { "Green", green };
  76.   R = { "Red", red };
  77.   O = { "Orange", orange };
  78.   N = { "Brown", brown };
  79.   I = { "Silver", silver };
  80. }
  81. --# END CONFIGURATION
  82.  
  83. -- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
  84. -- licensed under the terms of the LGPL2
  85. -- http://lua-users.org/wiki/BaseSixtyFour
  86. -- character table string
  87. local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  88. -- encoding
  89. function encode(data)
  90.   return ((data:gsub('.', function(x)
  91.     local r,b='',x:byte()
  92.     for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
  93.     return r;
  94.   end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
  95.     if (#x < 6) then return '' end
  96.     local c=0
  97.     for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
  98.     return b:sub(c+1,c+1)
  99.   end)..({ '', '==', '=' })[#data%3+1])
  100. end
  101. -- decoding
  102. function decode(data)
  103.   data = string.gsub(data, '[^'..b..'=]', '')
  104.   return (data:gsub('.', function(x)
  105.     if (x == '=') then return '' end
  106.     local r,f='',(b:find(x)-1)
  107.     for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
  108.     return r;
  109.   end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
  110.     if (#x ~= 8) then return '' end
  111.     local c=0
  112.     for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
  113.     return string.char(c)
  114.   end))
  115. end
  116.  
  117. -- AES Lua implementation by SquidDev
  118. -- https://gist.github.com/SquidDev/86925e07cbabd70773e53d781bd8b2fe
  119. local encrypt, decrypt
  120. do
  121.   local function _W(f) local e=setmetatable({}, {__index = _ENV or getfenv()}) if setfenv then setfenv(f, e) end return f(e) or e end
  122.   local bit=_W(function(_ENV, ...)
  123.   --[[
  124.     This bit API is designed to cope with unsigned integers instead of normal integers
  125.     To do this we add checks for overflows: (x > 2^31 ? x - 2 ^ 32 : x)
  126.     These are written in long form because no constant folding.
  127.   ]]
  128.   local floor = math.floor
  129.   local lshift, rshift
  130.  
  131.   rshift = function(a,disp)
  132.     return floor(a % 4294967296 / 2^disp)
  133.   end
  134.  
  135.   lshift = function(a,disp)
  136.     return (a * 2^disp) % 4294967296
  137.   end
  138.  
  139.   return {
  140.     -- bit operations
  141.     bnot = bit32 and bit32.bnot or bit.bnot,
  142.     band = bit32 and bit32.band or bit.band,
  143.     bor  = bit32 and bit32.bor or bit.bor,
  144.     bxor = bit32 and bit32.bxor or bit.bxor,
  145.     rshift = rshift,
  146.     lshift = lshift,
  147.   }
  148.   end)
  149.  
  150.   local gf=_W(function(_ENV, ...)
  151.   -- finite field with base 2 and modulo irreducible polynom x^8+x^4+x^3+x+1 = 0x11d
  152.   local bxor = bit32 and bit32.bxor or bit.bxor
  153.   local lshift = bit.lshift
  154.   -- private data of gf
  155.   local n = 0x100
  156.   local ord = 0xff
  157.   local irrPolynom = 0x11b
  158.   local exp = {}
  159.   local log = {}
  160.   --
  161.   -- add two polynoms (its simply xor)
  162.   --
  163.   local function add(operand1, operand2)
  164.     return bxor(operand1,operand2)
  165.   end
  166.   --
  167.   -- subtract two polynoms (same as addition)
  168.   --
  169.   local function sub(operand1, operand2)
  170.     return bxor(operand1,operand2)
  171.   end
  172.   --
  173.   -- inverts element
  174.   -- a^(-1) = g^(order - log(a))
  175.   --
  176.   local function invert(operand)
  177.     -- special case for 1
  178.     if (operand == 1) then
  179.       return 1
  180.     end
  181.     -- normal invert
  182.     local exponent = ord - log[operand]
  183.     return exp[exponent]
  184.   end
  185.   --
  186.   -- multiply two elements using a logarithm table
  187.   -- a*b = g^(log(a)+log(b))
  188.   --
  189.   local function mul(operand1, operand2)
  190.     if (operand1 == 0 or operand2 == 0) then
  191.       return 0
  192.     end
  193.     local exponent = log[operand1] + log[operand2]
  194.     if (exponent >= ord) then
  195.       exponent = exponent - ord
  196.     end
  197.     return exp[exponent]
  198.   end
  199.   --
  200.   -- divide two elements
  201.   -- a/b = g^(log(a)-log(b))
  202.   --
  203.   local function div(operand1, operand2)
  204.     if (operand1 == 0)  then
  205.       return 0
  206.     end
  207.     -- TODO: exception if operand2 == 0
  208.     local exponent = log[operand1] - log[operand2]
  209.     if (exponent < 0) then
  210.       exponent = exponent + ord
  211.     end
  212.     return exp[exponent]
  213.   end
  214.   --
  215.   -- print logarithmic table
  216.   --
  217.   local function printLog()
  218.     for i = 1, n do
  219.       print("log(", i-1, ")=", log[i-1])
  220.     end
  221.   end
  222.   --
  223.   -- print exponentiation table
  224.   --
  225.   local function printExp()
  226.     for i = 1, n do
  227.       print("exp(", i-1, ")=", exp[i-1])
  228.     end
  229.   end
  230.   --
  231.   -- calculate logarithmic and exponentiation table
  232.   --
  233.   local function initMulTable()
  234.     local a = 1
  235.     for i = 0,ord-1 do
  236.       exp[i] = a
  237.       log[a] = i
  238.       -- multiply with generator x+1 -> left shift + 1
  239.       a = bxor(lshift(a, 1), a)
  240.       -- if a gets larger than order, reduce modulo irreducible polynom
  241.       if a > ord then
  242.         a = sub(a, irrPolynom)
  243.       end
  244.     end
  245.   end
  246.  
  247.   initMulTable()
  248.  
  249.   return {
  250.     add = add,
  251.     sub = sub,
  252.     invert = invert,
  253.     mul = mul,
  254.     div = div,
  255.     printLog = printLog,
  256.     printExp = printExp,
  257.   }
  258.   end)
  259.  
  260.   util=_W(function(_ENV, ...)
  261.   -- Cache some bit operators
  262.   local bxor = bit.bxor
  263.   local rshift = bit.rshift
  264.   local band = bit.band
  265.   local lshift = bit.lshift
  266.   local sleepCheckIn
  267.   --
  268.   -- calculate the parity of one byte
  269.   --
  270.   local function byteParity(byte)
  271.     byte = bxor(byte, rshift(byte, 4))
  272.     byte = bxor(byte, rshift(byte, 2))
  273.     byte = bxor(byte, rshift(byte, 1))
  274.     return band(byte, 1)
  275.   end
  276.   --
  277.   -- get byte at position index
  278.   --
  279.   local function getByte(number, index)
  280.     return index == 0 and band(number,0xff) or band(rshift(number, index*8),0xff)
  281.   end
  282.   --
  283.   -- put number into int at position index
  284.   --
  285.   local function putByte(number, index)
  286.     return index == 0 and band(number,0xff) or lshift(band(number,0xff),index*8)
  287.   end
  288.   --
  289.   -- convert byte array to int array
  290.   --
  291.   local function bytesToInts(bytes, start, n)
  292.     local ints = {}
  293.     for i = 0, n - 1 do
  294.       ints[i + 1] =
  295.           putByte(bytes[start + (i*4)], 3) +
  296.           putByte(bytes[start + (i*4) + 1], 2) +
  297.           putByte(bytes[start + (i*4) + 2], 1) +
  298.           putByte(bytes[start + (i*4) + 3], 0)
  299.       if n % 10000 == 0 then sleepCheckIn() end
  300.     end
  301.     return ints
  302.   end
  303.   --
  304.   -- convert int array to byte array
  305.   --
  306.   local function intsToBytes(ints, output, outputOffset, n)
  307.     n = n or #ints
  308.     for i = 0, n - 1 do
  309.       for j = 0,3 do
  310.         output[outputOffset + i*4 + (3 - j)] = getByte(ints[i + 1], j)
  311.       end
  312.       if n % 10000 == 0 then sleepCheckIn() end
  313.     end
  314.     return output
  315.   end
  316.   --
  317.   -- convert bytes to hexString
  318.   --
  319.   local function bytesToHex(bytes)
  320.     local hexBytes = ""
  321.     for i,byte in ipairs(bytes) do
  322.       hexBytes = hexBytes .. string.format("%02x ", byte)
  323.     end
  324.     return hexBytes
  325.   end
  326.  
  327.   local function hexToBytes(bytes)
  328.     local out = {}
  329.     for i = 1, #bytes, 2 do
  330.       out[#out + 1] = tonumber(bytes:sub(i, i + 1), 16)
  331.     end
  332.     return out
  333.   end
  334.   --
  335.   -- convert data to hex string
  336.   --
  337.   local function toHexString(data)
  338.     local type = type(data)
  339.     if (type == "number") then
  340.       return string.format("%08x",data)
  341.     elseif (type == "table") then
  342.       return bytesToHex(data)
  343.     elseif (type == "string") then
  344.       local bytes = {string.byte(data, 1, #data)}
  345.       return bytesToHex(bytes)
  346.     else
  347.       return data
  348.     end
  349.   end
  350.  
  351.   local function padByteString(data)
  352.     local dataLength = #data
  353.     local random1 = math.random(0,255)
  354.     local random2 = math.random(0,255)
  355.     local prefix = string.char(random1,
  356.       random2,
  357.       random1,
  358.       random2,
  359.       getByte(dataLength, 3),
  360.       getByte(dataLength, 2),
  361.       getByte(dataLength, 1),
  362.       getByte(dataLength, 0)
  363.     )
  364.     data = prefix .. data
  365.     local padding, paddingLength = "", math.ceil(#data/16)*16 - #data
  366.     for i=1,paddingLength do
  367.       padding = padding .. string.char(math.random(0,255))
  368.     end
  369.     return data .. padding
  370.   end
  371.  
  372.   local function properlyDecrypted(data)
  373.     local random = {string.byte(data,1,4)}
  374.  
  375.     if (random[1] == random[3] and random[2] == random[4]) then
  376.       return true
  377.     end
  378.  
  379.     return false
  380.   end
  381.  
  382.   local function unpadByteString(data)
  383.     if (not properlyDecrypted(data)) then
  384.       return nil
  385.     end
  386.     local dataLength = putByte(string.byte(data,5), 3)
  387.              + putByte(string.byte(data,6), 2)
  388.              + putByte(string.byte(data,7), 1)
  389.              + putByte(string.byte(data,8), 0)
  390.     return string.sub(data,9,8+dataLength)
  391.   end
  392.  
  393.   local function xorIV(data, iv)
  394.     for i = 1,16 do
  395.       data[i] = bxor(data[i], iv[i])
  396.     end
  397.   end
  398.  
  399.   local function increment(data)
  400.     local i = 16
  401.     while true do
  402.       local value = data[i] + 1
  403.       if value >= 256 then
  404.         data[i] = value - 256
  405.         i = (i - 2) % 16 + 1
  406.       else
  407.         data[i] = value
  408.         break
  409.       end
  410.     end
  411.   end
  412.  
  413.   -- Called every encryption cycle
  414.   local push, pull, time = os.queueEvent, coroutine.yield, os.time
  415.   local oldTime = time()
  416.   local function sleepCheckIn()
  417.     local newTime = time()
  418.     if newTime - oldTime >= 0.03 then -- (0.020 * 1.5)
  419.       oldTime = newTime
  420.       push("sleep")
  421.       pull("sleep")
  422.     end
  423.   end
  424.  
  425.   local function getRandomData(bytes)
  426.     local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
  427.     local result = {}
  428.     for i=1,bytes do
  429.       insert(result, random(0,255))
  430.       if i % 10240 == 0 then sleep() end
  431.     end
  432.     return result
  433.   end
  434.  
  435.   local function getRandomString(bytes)
  436.     local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
  437.     local result = {}
  438.     for i=1,bytes do
  439.       insert(result, char(random(0,255)))
  440.       if i % 10240 == 0 then sleep() end
  441.     end
  442.     return table.concat(result)
  443.   end
  444.  
  445.   return {
  446.     byteParity = byteParity,
  447.     getByte = getByte,
  448.     putByte = putByte,
  449.     bytesToInts = bytesToInts,
  450.     intsToBytes = intsToBytes,
  451.     bytesToHex = bytesToHex,
  452.     hexToBytes = hexToBytes,
  453.     toHexString = toHexString,
  454.     padByteString = padByteString,
  455.     properlyDecrypted = properlyDecrypted,
  456.     unpadByteString = unpadByteString,
  457.     xorIV = xorIV,
  458.     increment = increment,
  459.     sleepCheckIn = sleepCheckIn,
  460.     getRandomData = getRandomData,
  461.     getRandomString = getRandomString,
  462.   }
  463.   end)
  464.  
  465.   aes=_W(function(_ENV, ...)
  466.   -- Implementation of AES with nearly pure lua
  467.   -- AES with lua is slow, really slow :-)
  468.   local putByte = util.putByte
  469.   local getByte = util.getByte
  470.   -- some constants
  471.   local ROUNDS = 'rounds'
  472.   local KEY_TYPE = "type"
  473.   local ENCRYPTION_KEY=1
  474.   local DECRYPTION_KEY=2
  475.   -- aes SBOX
  476.   local SBox = {}
  477.   local iSBox = {}
  478.   -- aes tables
  479.   local table0 = {}
  480.   local table1 = {}
  481.   local table2 = {}
  482.   local table3 = {}
  483.   local tableInv0 = {}
  484.   local tableInv1 = {}
  485.   local tableInv2 = {}
  486.   local tableInv3 = {}
  487.   -- round constants
  488.   local rCon = {
  489.     0x01000000,
  490.     0x02000000,
  491.     0x04000000,
  492.     0x08000000,
  493.     0x10000000,
  494.     0x20000000,
  495.     0x40000000,
  496.     0x80000000,
  497.     0x1b000000,
  498.     0x36000000,
  499.     0x6c000000,
  500.     0xd8000000,
  501.     0xab000000,
  502.     0x4d000000,
  503.     0x9a000000,
  504.     0x2f000000,
  505.   }
  506.   --
  507.   -- affine transformation for calculating the S-Box of AES
  508.   --
  509.   local function affinMap(byte)
  510.     mask = 0xf8
  511.     result = 0
  512.     for i = 1,8 do
  513.       result = bit.lshift(result,1)
  514.       parity = util.byteParity(bit.band(byte,mask))
  515.       result = result + parity
  516.       -- simulate roll
  517.       lastbit = bit.band(mask, 1)
  518.       mask = bit.band(bit.rshift(mask, 1),0xff)
  519.       mask = lastbit ~= 0 and bit.bor(mask, 0x80) or bit.band(mask, 0x7f)
  520.     end
  521.     return bit.bxor(result, 0x63)
  522.   end
  523.   --
  524.   -- calculate S-Box and inverse S-Box of AES
  525.   -- apply affine transformation to inverse in finite field 2^8
  526.   --
  527.   local function calcSBox()
  528.     for i = 0, 255 do
  529.       inverse = i ~= 0 and gf.invert(i) or i
  530.       mapped = affinMap(inverse)
  531.       SBox[i] = mapped
  532.       iSBox[mapped] = i
  533.     end
  534.   end
  535.   --
  536.   -- Calculate round tables
  537.   -- round tables are used to calculate shiftRow, MixColumn and SubBytes
  538.   -- with 4 table lookups and 4 xor operations.
  539.   --
  540.   local function calcRoundTables()
  541.     for x = 0,255 do
  542.       byte = SBox[x]
  543.       table0[x] = putByte(gf.mul(0x03, byte), 0)
  544.                 + putByte(             byte , 1)
  545.                 + putByte(             byte , 2)
  546.                 + putByte(gf.mul(0x02, byte), 3)
  547.       table1[x] = putByte(             byte , 0)
  548.                 + putByte(             byte , 1)
  549.                 + putByte(gf.mul(0x02, byte), 2)
  550.                 + putByte(gf.mul(0x03, byte), 3)
  551.       table2[x] = putByte(             byte , 0)
  552.                 + putByte(gf.mul(0x02, byte), 1)
  553.                 + putByte(gf.mul(0x03, byte), 2)
  554.                 + putByte(             byte , 3)
  555.       table3[x] = putByte(gf.mul(0x02, byte), 0)
  556.                 + putByte(gf.mul(0x03, byte), 1)
  557.                 + putByte(             byte , 2)
  558.                 + putByte(             byte , 3)
  559.     end
  560.   end
  561.   --
  562.   -- Calculate inverse round tables
  563.   -- does the inverse of the normal roundtables for the equivalent
  564.   -- decryption algorithm.
  565.   --
  566.   local function calcInvRoundTables()
  567.     for x = 0,255 do
  568.       byte = iSBox[x]
  569.       tableInv0[x] = putByte(gf.mul(0x0b, byte), 0)
  570.                  + putByte(gf.mul(0x0d, byte), 1)
  571.                  + putByte(gf.mul(0x09, byte), 2)
  572.                  + putByte(gf.mul(0x0e, byte), 3)
  573.       tableInv1[x] = putByte(gf.mul(0x0d, byte), 0)
  574.                  + putByte(gf.mul(0x09, byte), 1)
  575.                  + putByte(gf.mul(0x0e, byte), 2)
  576.                  + putByte(gf.mul(0x0b, byte), 3)
  577.       tableInv2[x] = putByte(gf.mul(0x09, byte), 0)
  578.                  + putByte(gf.mul(0x0e, byte), 1)
  579.                  + putByte(gf.mul(0x0b, byte), 2)
  580.                  + putByte(gf.mul(0x0d, byte), 3)
  581.       tableInv3[x] = putByte(gf.mul(0x0e, byte), 0)
  582.                  + putByte(gf.mul(0x0b, byte), 1)
  583.                  + putByte(gf.mul(0x0d, byte), 2)
  584.                  + putByte(gf.mul(0x09, byte), 3)
  585.     end
  586.   end
  587.   --
  588.   -- rotate word: 0xaabbccdd gets 0xbbccddaa
  589.   -- used for key schedule
  590.   --
  591.   local function rotWord(word)
  592.     local tmp = bit.band(word,0xff000000)
  593.     return (bit.lshift(word,8) + bit.rshift(tmp,24))
  594.   end
  595.   --
  596.   -- replace all bytes in a word with the SBox.
  597.   -- used for key schedule
  598.   --
  599.   local function subWord(word)
  600.     return putByte(SBox[getByte(word,0)],0)
  601.       + putByte(SBox[getByte(word,1)],1)
  602.       + putByte(SBox[getByte(word,2)],2)
  603.       + putByte(SBox[getByte(word,3)],3)
  604.   end
  605.   --
  606.   -- generate key schedule for aes encryption
  607.   --
  608.   -- returns table with all round keys and
  609.   -- the necessary number of rounds saved in [ROUNDS]
  610.   --
  611.   local function expandEncryptionKey(key)
  612.     local keySchedule = {}
  613.     local keyWords = math.floor(#key / 4)
  614.     if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then
  615.       error("Invalid key size: " .. tostring(keyWords))
  616.       return nil
  617.     end
  618.     keySchedule[ROUNDS] = keyWords + 6
  619.     keySchedule[KEY_TYPE] = ENCRYPTION_KEY
  620.     for i = 0,keyWords - 1 do
  621.       keySchedule[i] = putByte(key[i*4+1], 3)
  622.                + putByte(key[i*4+2], 2)
  623.                + putByte(key[i*4+3], 1)
  624.                + putByte(key[i*4+4], 0)
  625.     end
  626.     for i = keyWords, (keySchedule[ROUNDS] + 1)*4 - 1 do
  627.       local tmp = keySchedule[i-1]
  628.       if ( i % keyWords == 0) then
  629.         tmp = rotWord(tmp)
  630.         tmp = subWord(tmp)
  631.         local index = math.floor(i/keyWords)
  632.         tmp = bit.bxor(tmp,rCon[index])
  633.       elseif (keyWords > 6 and i % keyWords == 4) then
  634.         tmp = subWord(tmp)
  635.       end
  636.       keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp)
  637.     end
  638.     return keySchedule
  639.   end
  640.   --
  641.   -- Inverse mix column
  642.   -- used for key schedule of decryption key
  643.   --
  644.   local function invMixColumnOld(word)
  645.     local b0 = getByte(word,3)
  646.     local b1 = getByte(word,2)
  647.     local b2 = getByte(word,1)
  648.     local b3 = getByte(word,0)
  649.     return putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1),
  650.                          gf.mul(0x0d, b2)),
  651.                          gf.mul(0x09, b3)),
  652.                          gf.mul(0x0e, b0)),3)
  653.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2),
  654.                          gf.mul(0x0d, b3)),
  655.                          gf.mul(0x09, b0)),
  656.                          gf.mul(0x0e, b1)),2)
  657.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3),
  658.                          gf.mul(0x0d, b0)),
  659.                          gf.mul(0x09, b1)),
  660.                          gf.mul(0x0e, b2)),1)
  661.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0),
  662.                          gf.mul(0x0d, b1)),
  663.                          gf.mul(0x09, b2)),
  664.                          gf.mul(0x0e, b3)),0)
  665.   end
  666.   --
  667.   -- Optimized inverse mix column
  668.   -- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
  669.   -- TODO: make it work
  670.   --
  671.   local function invMixColumn(word)
  672.     local b0 = getByte(word,3)
  673.     local b1 = getByte(word,2)
  674.     local b2 = getByte(word,1)
  675.     local b3 = getByte(word,0)
  676.     local t = bit.bxor(b3,b2)
  677.     local u = bit.bxor(b1,b0)
  678.     local v = bit.bxor(t,u)
  679.     v = bit.bxor(v,gf.mul(0x08,v))
  680.     w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0)))
  681.     v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1)))
  682.     return putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0)
  683.        + putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t              )), 1)
  684.        + putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2)
  685.        + putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u              )), 3)
  686.   end
  687.   --
  688.   -- generate key schedule for aes decryption
  689.   --
  690.   -- uses key schedule for aes encryption and transforms each
  691.   -- key by inverse mix column.
  692.   --
  693.   local function expandDecryptionKey(key)
  694.     local keySchedule = expandEncryptionKey(key)
  695.     if (keySchedule == nil) then
  696.       return nil
  697.     end
  698.     keySchedule[KEY_TYPE] = DECRYPTION_KEY
  699.     for i = 4, (keySchedule[ROUNDS] + 1)*4 - 5 do
  700.       keySchedule[i] = invMixColumnOld(keySchedule[i])
  701.     end
  702.     return keySchedule
  703.   end
  704.   --
  705.   -- xor round key to state
  706.   --
  707.   local function addRoundKey(state, key, round)
  708.     for i = 0, 3 do
  709.       state[i + 1] = bit.bxor(state[i + 1], key[round*4+i])
  710.     end
  711.   end
  712.   --
  713.   -- do encryption round (ShiftRow, SubBytes, MixColumn together)
  714.   --
  715.   local function doRound(origState, dstState)
  716.     dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
  717.           table0[getByte(origState[1],3)],
  718.           table1[getByte(origState[2],2)]),
  719.           table2[getByte(origState[3],1)]),
  720.           table3[getByte(origState[4],0)])
  721.     dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
  722.           table0[getByte(origState[2],3)],
  723.           table1[getByte(origState[3],2)]),
  724.           table2[getByte(origState[4],1)]),
  725.           table3[getByte(origState[1],0)])
  726.     dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
  727.           table0[getByte(origState[3],3)],
  728.           table1[getByte(origState[4],2)]),
  729.           table2[getByte(origState[1],1)]),
  730.           table3[getByte(origState[2],0)])
  731.     dstState[4] =  bit.bxor(bit.bxor(bit.bxor(
  732.           table0[getByte(origState[4],3)],
  733.           table1[getByte(origState[1],2)]),
  734.           table2[getByte(origState[2],1)]),
  735.           table3[getByte(origState[3],0)])
  736.   end
  737.   --
  738.   -- do last encryption round (ShiftRow and SubBytes)
  739.   --
  740.   local function doLastRound(origState, dstState)
  741.     dstState[1] = putByte(SBox[getByte(origState[1],3)], 3)
  742.           + putByte(SBox[getByte(origState[2],2)], 2)
  743.           + putByte(SBox[getByte(origState[3],1)], 1)
  744.           + putByte(SBox[getByte(origState[4],0)], 0)
  745.     dstState[2] = putByte(SBox[getByte(origState[2],3)], 3)
  746.           + putByte(SBox[getByte(origState[3],2)], 2)
  747.           + putByte(SBox[getByte(origState[4],1)], 1)
  748.           + putByte(SBox[getByte(origState[1],0)], 0)
  749.     dstState[3] = putByte(SBox[getByte(origState[3],3)], 3)
  750.           + putByte(SBox[getByte(origState[4],2)], 2)
  751.           + putByte(SBox[getByte(origState[1],1)], 1)
  752.           + putByte(SBox[getByte(origState[2],0)], 0)
  753.     dstState[4] = putByte(SBox[getByte(origState[4],3)], 3)
  754.           + putByte(SBox[getByte(origState[1],2)], 2)
  755.           + putByte(SBox[getByte(origState[2],1)], 1)
  756.           + putByte(SBox[getByte(origState[3],0)], 0)
  757.   end
  758.   --
  759.   -- do decryption round
  760.   --
  761.   local function doInvRound(origState, dstState)
  762.     dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
  763.           tableInv0[getByte(origState[1],3)],
  764.           tableInv1[getByte(origState[4],2)]),
  765.           tableInv2[getByte(origState[3],1)]),
  766.           tableInv3[getByte(origState[2],0)])
  767.     dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
  768.           tableInv0[getByte(origState[2],3)],
  769.           tableInv1[getByte(origState[1],2)]),
  770.           tableInv2[getByte(origState[4],1)]),
  771.           tableInv3[getByte(origState[3],0)])
  772.     dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
  773.           tableInv0[getByte(origState[3],3)],
  774.           tableInv1[getByte(origState[2],2)]),
  775.           tableInv2[getByte(origState[1],1)]),
  776.           tableInv3[getByte(origState[4],0)])
  777.     dstState[4] =  bit.bxor(bit.bxor(bit.bxor(
  778.           tableInv0[getByte(origState[4],3)],
  779.           tableInv1[getByte(origState[3],2)]),
  780.           tableInv2[getByte(origState[2],1)]),
  781.           tableInv3[getByte(origState[1],0)])
  782.   end
  783.   --
  784.   -- do last decryption round
  785.   --
  786.   local function doInvLastRound(origState, dstState)
  787.     dstState[1] = putByte(iSBox[getByte(origState[1],3)], 3)
  788.           + putByte(iSBox[getByte(origState[4],2)], 2)
  789.           + putByte(iSBox[getByte(origState[3],1)], 1)
  790.           + putByte(iSBox[getByte(origState[2],0)], 0)
  791.     dstState[2] = putByte(iSBox[getByte(origState[2],3)], 3)
  792.           + putByte(iSBox[getByte(origState[1],2)], 2)
  793.           + putByte(iSBox[getByte(origState[4],1)], 1)
  794.           + putByte(iSBox[getByte(origState[3],0)], 0)
  795.     dstState[3] = putByte(iSBox[getByte(origState[3],3)], 3)
  796.           + putByte(iSBox[getByte(origState[2],2)], 2)
  797.           + putByte(iSBox[getByte(origState[1],1)], 1)
  798.           + putByte(iSBox[getByte(origState[4],0)], 0)
  799.     dstState[4] = putByte(iSBox[getByte(origState[4],3)], 3)
  800.           + putByte(iSBox[getByte(origState[3],2)], 2)
  801.           + putByte(iSBox[getByte(origState[2],1)], 1)
  802.           + putByte(iSBox[getByte(origState[1],0)], 0)
  803.   end
  804.   --
  805.   -- encrypts 16 Bytes
  806.   -- key           encryption key schedule
  807.   -- input         array with input data
  808.   -- inputOffset   start index for input
  809.   -- output        array for encrypted data
  810.   -- outputOffset  start index for output
  811.   --
  812.   local function encrypt(key, input, inputOffset, output, outputOffset)
  813.     --default parameters
  814.     inputOffset = inputOffset or 1
  815.     output = output or {}
  816.     outputOffset = outputOffset or 1
  817.     local state = {}
  818.     local tmpState = {}
  819.     if (key[KEY_TYPE] ~= ENCRYPTION_KEY) then
  820.       error("No encryption key: " .. tostring(key[KEY_TYPE]) .. ", expected " .. ENCRYPTION_KEY)
  821.       return
  822.     end
  823.     state = util.bytesToInts(input, inputOffset, 4)
  824.     addRoundKey(state, key, 0)
  825.     local round = 1
  826.     while (round < key[ROUNDS] - 1) do
  827.       -- do a double round to save temporary assignments
  828.       doRound(state, tmpState)
  829.       addRoundKey(tmpState, key, round)
  830.       round = round + 1
  831.       doRound(tmpState, state)
  832.       addRoundKey(state, key, round)
  833.       round = round + 1
  834.     end
  835.     doRound(state, tmpState)
  836.     addRoundKey(tmpState, key, round)
  837.     round = round +1
  838.     doLastRound(tmpState, state)
  839.     addRoundKey(state, key, round)
  840.     util.sleepCheckIn()
  841.     return util.intsToBytes(state, output, outputOffset)
  842.   end
  843.   --
  844.   -- decrypt 16 bytes
  845.   -- key           decryption key schedule
  846.   -- input         array with input data
  847.   -- inputOffset   start index for input
  848.   -- output        array for decrypted data
  849.   -- outputOffset  start index for output
  850.   ---
  851.   local function decrypt(key, input, inputOffset, output, outputOffset)
  852.     -- default arguments
  853.     inputOffset = inputOffset or 1
  854.     output = output or {}
  855.     outputOffset = outputOffset or 1
  856.     local state = {}
  857.     local tmpState = {}
  858.     if (key[KEY_TYPE] ~= DECRYPTION_KEY) then
  859.       error("No decryption key: " .. tostring(key[KEY_TYPE]))
  860.       return
  861.     end
  862.     state = util.bytesToInts(input, inputOffset, 4)
  863.     addRoundKey(state, key, key[ROUNDS])
  864.     local round = key[ROUNDS] - 1
  865.     while (round > 2) do
  866.       -- do a double round to save temporary assignments
  867.       doInvRound(state, tmpState)
  868.       addRoundKey(tmpState, key, round)
  869.       round = round - 1
  870.       doInvRound(tmpState, state)
  871.       addRoundKey(state, key, round)
  872.       round = round - 1
  873.     end
  874.     doInvRound(state, tmpState)
  875.     addRoundKey(tmpState, key, round)
  876.     round = round - 1
  877.     doInvLastRound(tmpState, state)
  878.     addRoundKey(state, key, round)
  879.     util.sleepCheckIn()
  880.     return util.intsToBytes(state, output, outputOffset)
  881.   end
  882.  
  883.   -- calculate all tables when loading this file
  884.   calcSBox()
  885.   calcRoundTables()
  886.   calcInvRoundTables()
  887.  
  888.   return {
  889.     ROUNDS = ROUNDS,
  890.     KEY_TYPE = KEY_TYPE,
  891.     ENCRYPTION_KEY = ENCRYPTION_KEY,
  892.     DECRYPTION_KEY = DECRYPTION_KEY,
  893.     expandEncryptionKey = expandEncryptionKey,
  894.     expandDecryptionKey = expandDecryptionKey,
  895.     encrypt = encrypt,
  896.     decrypt = decrypt,
  897.   }
  898.   end)
  899.  
  900.   local buffer=_W(function(_ENV, ...)
  901.   local function new ()
  902.     return {}
  903.   end
  904.  
  905.   local function addString (stack, s)
  906.     table.insert(stack, s)
  907.   end
  908.  
  909.   local function toString (stack)
  910.     return table.concat(stack)
  911.   end
  912.  
  913.   return {
  914.     new = new,
  915.     addString = addString,
  916.     toString = toString,
  917.   }
  918.   end)
  919.  
  920.   ciphermode=_W(function(_ENV, ...)
  921.   local public = {}
  922.   --
  923.   -- Encrypt strings
  924.   -- key - byte array with key
  925.   -- string - string to encrypt
  926.   -- modefunction - function for cipher mode to use
  927.   --
  928.   local random, unpack = math.random, unpack or table.unpack
  929.   function public.encryptString(key, data, modeFunction, iv)
  930.     if iv then
  931.       local ivCopy = {}
  932.       for i = 1, 16 do ivCopy[i] = iv[i] end
  933.       iv = ivCopy
  934.     else
  935.       iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  936.     end
  937.     local keySched = aes.expandEncryptionKey(key)
  938.     local encryptedData = buffer.new()
  939.     for i = 1, #data/16 do
  940.       local offset = (i-1)*16 + 1
  941.       local byteData = {string.byte(data,offset,offset +15)}
  942.       iv = modeFunction(keySched, byteData, iv)
  943.       buffer.addString(encryptedData, string.char(unpack(byteData)))
  944.     end
  945.     return buffer.toString(encryptedData)
  946.   end
  947.   --
  948.   -- the following 4 functions can be used as
  949.   -- modefunction for encryptString
  950.   --
  951.   -- Electronic code book mode encrypt function
  952.   function public.encryptECB(keySched, byteData, iv)
  953.     aes.encrypt(keySched, byteData, 1, byteData, 1)
  954.   end
  955.  
  956.   -- Cipher block chaining mode encrypt function
  957.   function public.encryptCBC(keySched, byteData, iv)
  958.     util.xorIV(byteData, iv)
  959.     aes.encrypt(keySched, byteData, 1, byteData, 1)
  960.     return byteData
  961.   end
  962.  
  963.   -- Output feedback mode encrypt function
  964.   function public.encryptOFB(keySched, byteData, iv)
  965.     aes.encrypt(keySched, iv, 1, iv, 1)
  966.     util.xorIV(byteData, iv)
  967.     return iv
  968.   end
  969.  
  970.   -- Cipher feedback mode encrypt function
  971.   function public.encryptCFB(keySched, byteData, iv)
  972.     aes.encrypt(keySched, iv, 1, iv, 1)
  973.     util.xorIV(byteData, iv)
  974.     return byteData
  975.   end
  976.  
  977.   function public.encryptCTR(keySched, byteData, iv)
  978.     local nextIV = {}
  979.     for j = 1, 16 do nextIV[j] = iv[j] end
  980.     aes.encrypt(keySched, iv, 1, iv, 1)
  981.     util.xorIV(byteData, iv)
  982.     util.increment(nextIV)
  983.     return nextIV
  984.   end
  985.   --
  986.   -- Decrypt strings
  987.   -- key - byte array with key
  988.   -- string - string to decrypt
  989.   -- modefunction - function for cipher mode to use
  990.   --
  991.   function public.decryptString(key, data, modeFunction, iv)
  992.     if iv then
  993.       local ivCopy = {}
  994.       for i = 1, 16 do ivCopy[i] = iv[i] end
  995.       iv = ivCopy
  996.     else
  997.       iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  998.     end
  999.     local keySched
  1000.     if modeFunction == public.decryptOFB or modeFunction == public.decryptCFB or modeFunction == public.decryptCTR then
  1001.       keySched = aes.expandEncryptionKey(key)
  1002.     else
  1003.       keySched = aes.expandDecryptionKey(key)
  1004.     end
  1005.     local decryptedData = buffer.new()
  1006.     for i = 1, #data/16 do
  1007.       local offset = (i-1)*16 + 1
  1008.       local byteData = {string.byte(data,offset,offset +15)}
  1009.       iv = modeFunction(keySched, byteData, iv)
  1010.       buffer.addString(decryptedData, string.char(unpack(byteData)))
  1011.     end
  1012.     return buffer.toString(decryptedData)
  1013.   end
  1014.   --
  1015.   -- the following 4 functions can be used as
  1016.   -- modefunction for decryptString
  1017.   --
  1018.   -- Electronic code book mode decrypt function
  1019.   function public.decryptECB(keySched, byteData, iv)
  1020.     aes.decrypt(keySched, byteData, 1, byteData, 1)
  1021.     return iv
  1022.   end
  1023.  
  1024.   -- Cipher block chaining mode decrypt function
  1025.   function public.decryptCBC(keySched, byteData, iv)
  1026.     local nextIV = {}
  1027.     for j = 1, 16 do nextIV[j] = byteData[j] end
  1028.     aes.decrypt(keySched, byteData, 1, byteData, 1)
  1029.     util.xorIV(byteData, iv)
  1030.     return nextIV
  1031.   end
  1032.  
  1033.   -- Output feedback mode decrypt function
  1034.   function public.decryptOFB(keySched, byteData, iv)
  1035.     aes.encrypt(keySched, iv, 1, iv, 1)
  1036.     util.xorIV(byteData, iv)
  1037.     return iv
  1038.   end
  1039.  
  1040.   -- Cipher feedback mode decrypt function
  1041.   function public.decryptCFB(keySched, byteData, iv)
  1042.     local nextIV = {}
  1043.     for j = 1, 16 do nextIV[j] = byteData[j] end
  1044.     aes.encrypt(keySched, iv, 1, iv, 1)
  1045.     util.xorIV(byteData, iv)
  1046.     return nextIV
  1047.   end
  1048.  
  1049.   public.decryptCTR = public.encryptCTR
  1050.   return public
  1051.   end)
  1052.  
  1053.   -- Simple API for encrypting strings.
  1054.   --
  1055.   AES128 = 16
  1056.   AES192 = 24
  1057.   AES256 = 32
  1058.   ECBMODE = 1
  1059.   CBCMODE = 2
  1060.   OFBMODE = 3
  1061.   CFBMODE = 4
  1062.   CTRMODE = 4
  1063.  
  1064.   local function pwToKey(password, keyLength, iv)
  1065.     local padLength = keyLength
  1066.     if (keyLength == AES192) then
  1067.       padLength = 32
  1068.     end
  1069.     if (padLength > #password) then
  1070.       local postfix = ""
  1071.       for i = 1,padLength - #password do
  1072.         postfix = postfix .. string.char(0)
  1073.       end
  1074.       password = password .. postfix
  1075.     else
  1076.       password = string.sub(password, 1, padLength)
  1077.     end
  1078.     local pwBytes = {string.byte(password,1,#password)}
  1079.     password = ciphermode.encryptString(pwBytes, password, ciphermode.encryptCBC, iv)
  1080.     password = string.sub(password, 1, keyLength)
  1081.     return {string.byte(password,1,#password)}
  1082.   end
  1083.   --
  1084.   -- Encrypts string data with password password.
  1085.   -- password  - the encryption key is generated from this string
  1086.   -- data      - string to encrypt (must not be too large)
  1087.   -- keyLength - length of aes key: 128(default), 192 or 256 Bit
  1088.   -- mode      - mode of encryption: ecb, cbc(default), ofb, cfb
  1089.   --
  1090.   -- mode and keyLength must be the same for encryption and decryption.
  1091.   --
  1092.   function encrypt(password, data, keyLength, mode, iv)
  1093.     assert(password ~= nil, "Empty password.")
  1094.     assert(data ~= nil, "Empty data.")
  1095.     local mode = mode or CBCMODE
  1096.     local keyLength = keyLength or AES128
  1097.     local key = pwToKey(password, keyLength, iv)
  1098.     local paddedData = util.padByteString(data)
  1099.     if mode == ECBMODE then
  1100.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptECB, iv)
  1101.     elseif mode == CBCMODE then
  1102.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCBC, iv)
  1103.     elseif mode == OFBMODE then
  1104.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptOFB, iv)
  1105.     elseif mode == CFBMODE then
  1106.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCFB, iv)
  1107.     elseif mode == CTRMODE then
  1108.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCTR, iv)
  1109.     else
  1110.       error("Unknown mode", 2)
  1111.     end
  1112.   end
  1113.   --
  1114.   -- Decrypts string data with password password.
  1115.   -- password  - the decryption key is generated from this string
  1116.   -- data      - string to encrypt
  1117.   -- keyLength - length of aes key: 128(default), 192 or 256 Bit
  1118.   -- mode      - mode of decryption: ecb, cbc(default), ofb, cfb
  1119.   --
  1120.   -- mode and keyLength must be the same for encryption and decryption.
  1121.   --
  1122.   function decrypt(password, data, keyLength, mode, iv)
  1123.     local mode = mode or CBCMODE
  1124.     local keyLength = keyLength or AES128
  1125.     local key = pwToKey(password, keyLength, iv)
  1126.     local plain
  1127.     if mode == ECBMODE then
  1128.       plain = ciphermode.decryptString(key, data, ciphermode.decryptECB, iv)
  1129.     elseif mode == CBCMODE then
  1130.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCBC, iv)
  1131.     elseif mode == OFBMODE then
  1132.       plain = ciphermode.decryptString(key, data, ciphermode.decryptOFB, iv)
  1133.     elseif mode == CFBMODE then
  1134.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCFB, iv)
  1135.     elseif mode == CTRMODE then
  1136.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCTR, iv)
  1137.     else
  1138.       error("Unknown mode", 2)
  1139.     end
  1140.     result = util.unpadByteString(plain)
  1141.     if (result == nil) then
  1142.       return nil
  1143.     end
  1144.     return result
  1145.   end
  1146. end
  1147.  
  1148. -- SHA-256, HMAC and PBKDF2 functions in ComputerCraft
  1149. -- By Anavrins
  1150. -- For help and details, you can PM me on the CC forums
  1151. -- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins
  1152. -- Pastebin: http://pastebin.com/6UV4qfNF
  1153. -- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact
  1154. local digest, hmac, pbkdf2
  1155. do
  1156.   local mod32 = 2^32
  1157.   local sha_hashlen = 32
  1158.   local sha_blocksize = 64
  1159.   local band    = bit32 and bit32.band or bit.band
  1160.   local bnot    = bit32 and bit32.bnot or bit.bnot
  1161.   local bxor    = bit32 and bit32.bxor or bit.bxor
  1162.   local blshift = bit32 and bit32.lshift or bit.blshift
  1163.   local upack   = unpack
  1164.  
  1165.   local function rrotate(n, b)
  1166.     local s = n/(2^b)
  1167.     local f = s%1
  1168.     return (s-f) + f*mod32
  1169.   end
  1170.  
  1171.   local function brshift(int, by) -- Thanks bit32 for bad rshift
  1172.     local s = int / (2^by)
  1173.     return s - s%1
  1174.   end
  1175.  
  1176.   local H = {
  1177.     0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  1178.     0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
  1179.   }
  1180.  
  1181.   local K = {
  1182.     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  1183.     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  1184.     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  1185.     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  1186.     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  1187.     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  1188.     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  1189.     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
  1190.   }
  1191.  
  1192.   local function counter(incr)
  1193.     local t1, t2 = 0, 0
  1194.     if 0xFFFFFFFF - t1 < incr then
  1195.       t2 = t2 + 1
  1196.       t1 = incr - (0xFFFFFFFF - t1) - 1    
  1197.     else t1 = t1 + incr
  1198.     end
  1199.     return t2, t1
  1200.   end
  1201.  
  1202.   local function BE_toInt(bs, i)
  1203.     return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0)
  1204.   end
  1205.  
  1206.   local function preprocess(data)
  1207.     local len = #data
  1208.     local proc = {}
  1209.     data[#data+1] = 0x80
  1210.     while #data%64~=56 do data[#data+1] = 0 end
  1211.     local blocks = math.ceil(#data/64)
  1212.     for i = 1, blocks do
  1213.       proc[i] = {}
  1214.       for j = 1, 16 do
  1215.         proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4))
  1216.       end
  1217.     end
  1218.     proc[blocks][15], proc[blocks][16] = counter(len*8)
  1219.     return proc
  1220.   end
  1221.  
  1222.   local function digestblock(w, C)
  1223.     for j = 17, 64 do
  1224.       local v = w[j-15]
  1225.       local s0 = bxor(bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18)), brshift(w[j-15], 3))
  1226.       local s1 = bxor(bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19)), brshift(w[j-2], 10))
  1227.       w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32
  1228.     end
  1229.     local a, b, c, d, e, f, g, h = upack(C)
  1230.     for j = 1, 64 do
  1231.       local S1 = bxor(bxor(rrotate(e, 6), rrotate(e, 11)), rrotate(e, 25))
  1232.       local ch = bxor(band(e, f), band(bnot(e), g))
  1233.       local temp1 = (h + S1 + ch + K[j] + w[j])%mod32
  1234.       local S0 = bxor(bxor(rrotate(a, 2), rrotate(a, 13)), rrotate(a, 22))
  1235.       local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c))
  1236.       local temp2 = (S0 + maj)%mod32
  1237.       h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32
  1238.     end
  1239.     C[1] = (C[1] + a)%mod32
  1240.     C[2] = (C[2] + b)%mod32
  1241.     C[3] = (C[3] + c)%mod32
  1242.     C[4] = (C[4] + d)%mod32
  1243.     C[5] = (C[5] + e)%mod32
  1244.     C[6] = (C[6] + f)%mod32
  1245.     C[7] = (C[7] + g)%mod32
  1246.     C[8] = (C[8] + h)%mod32
  1247.     return C
  1248.   end
  1249.  
  1250.   local mt = {
  1251.     __tostring = function(a) return string.char(unpack(a)) end,
  1252.     __index = {
  1253.       toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end,
  1254.       isEqual = function(self, t)
  1255.         if type(t) ~= "table" then return false end
  1256.         if #self ~= #t then return false end
  1257.         local ret = 0
  1258.         for i = 1, #self do
  1259.           ret = bit32.bor(ret, bxor(self[i], t[i]))
  1260.         end
  1261.         return ret == 0
  1262.       end
  1263.     }
  1264.   }
  1265.  
  1266.   local function toBytes(t, n)
  1267.     local b = {}
  1268.     for i = 1, n do
  1269.       b[(i-1)*4+1] = band(brshift(band(t[i], 0xFF000000), 24), 0xFF)
  1270.       b[(i-1)*4+2] = band(brshift(band(t[i], 0xFF0000), 16), 0xFF)
  1271.       b[(i-1)*4+3] = band(brshift(band(t[i], 0xFF00), 8), 0xFF)
  1272.       b[(i-1)*4+4] = band(t[i], 0xFF)
  1273.     end
  1274.     return setmetatable(b, mt)
  1275.   end
  1276.  
  1277.   digest = function(data)
  1278.     data = data or ""
  1279.     data = type(data) == "string" and {data:byte(1,-1)} or data
  1280.     data = preprocess(data)
  1281.     local C = {upack(H)}
  1282.     for i = 1, #data do C = digestblock(data[i], C) end
  1283.     return toBytes(C, 8)
  1284.   end
  1285.  
  1286.   hmac = function(data, key)
  1287.     local data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)}
  1288.     local key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)}
  1289.     local blocksize = sha_blocksize
  1290.     key = #key > blocksize and digest(key) or key
  1291.     local ipad = {}
  1292.     local opad = {}
  1293.     local padded_key = {}
  1294.     for i = 1, blocksize do
  1295.       ipad[i] = bxor(0x36, key[i] or 0)
  1296.       opad[i] = bxor(0x5C, key[i] or 0)
  1297.     end
  1298.     for i = 1, #data do
  1299.       ipad[blocksize+i] = data[i]
  1300.     end
  1301.     ipad = digest(ipad)
  1302.     for i = 1, blocksize do
  1303.       padded_key[i] = opad[i]
  1304.       padded_key[blocksize+i] = ipad[i]
  1305.     end
  1306.     return digest(padded_key)
  1307.   end
  1308.  
  1309.   pbkdf2 = function(pass, salt, iter, dklen)
  1310.     local out = {}
  1311.     local hashlen = sha_hashlen
  1312.     local block = 1
  1313.     dklen = dklen or 32
  1314.     while dklen > 0 do
  1315.       local ikey = {}
  1316.       local isalt = type(salt) == "table" and {upack(salt)} or {tostring(salt):byte(1,-1)}
  1317.       local clen = dklen > hashlen and hashlen or dklen
  1318.       local iCount = #isalt
  1319.       isalt[iCount+1] = band(brshift(band(block, 0xFF000000), 24), 0xFF)
  1320.       isalt[iCount+2] = band(brshift(band(block, 0xFF0000), 16), 0xFF)
  1321.       isalt[iCount+3] = band(brshift(band(block, 0xFF00), 8), 0xFF)
  1322.       isalt[iCount+4] = band(block, 0xFF)
  1323.       for j = 1, iter do
  1324.         isalt = hmac(isalt, pass)
  1325.         for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end
  1326.         if j % 200 == 0 then os.queueEvent("PBKDF2", j) coroutine.yield("PBKDF2") end
  1327.       end
  1328.       dklen = dklen - clen
  1329.       block = block+1
  1330.       for k = 1, clen do out[#out+1] = ikey[k] end
  1331.     end
  1332.     return setmetatable(out, mt)
  1333.   end
  1334. end
  1335.  
  1336. local function getFuelLevel()
  1337.   fuelAmount, fuelPercent, coal, fuelState = turtle.getFuelLevel(), 0, 0, false
  1338.   local bFuelAmount = type(fuelAmount) == "string"
  1339.   if bFuelAmount or fuelAmount > 0 then
  1340.     fuelPercent = bFuelAmount and 101 or math.floor((fuelAmount / turtleFuelLimit) * 100)
  1341.     coal = bFuelAmount and 0 or math.floor(fuelAmount / 80)
  1342.     fuelState = true
  1343.   end
  1344.   return true
  1345. end
  1346.  
  1347. local function getSlotContents()
  1348.   local contents = turtle.getItemDetail(selectedSlot)
  1349.   slotContents = contents and contents.name:sub(contents.name:find(":") + 1, contents.name:find(":") + 18) or "<empty>"
  1350. end
  1351.  
  1352. local function inventorySlots()
  1353.   for i = 1, 16 do
  1354.     gtInventory[i] = { }
  1355.     gtInventory[i].count = turtle.getItemCount(i)
  1356.     if gtInventory[i].count > 0 then
  1357.       turtle.select(i)
  1358.       selectedSlot = i
  1359.       gtInventory[i].isFuel = turtle.refuel(0)
  1360.     else
  1361.       gtInventory[i].isFuel = false
  1362.     end
  1363.   end
  1364.   if _CC_VERSION or _HOST then getSlotContents() end
  1365. end
  1366.  
  1367. local function saveData()
  1368.   local turtleConfig = fs.open(config, "w") or error("saveData(): Cannot open " .. config .. " for writing", 0)
  1369.   turtleConfig.write(textutils.serialize(gtSettings))
  1370.   turtleConfig.close()
  1371. end
  1372.  
  1373. local function clearTerm()
  1374.   term.setBackgroundColor(black)
  1375.   term.setTextColor(white)
  1376.   term.clear()
  1377.   term.setCursorPos(1, 1)
  1378. end
  1379.  
  1380. local function drawElement(x, y, w, h, txtColor, bgColor, text)
  1381.   text = text and tostring(text) or ""
  1382.   local txtLen = #text
  1383.   w = math.max(w, txtLen)
  1384.   local spacer = (w - txtLen) / 2
  1385.   local txtLine = string.rep(" ", math.floor(spacer)) .. text .. string.rep(" ", math.ceil(spacer))
  1386.   if txtColor then term.setTextColor(txtColor) end
  1387.   if bgColor then term.setBackgroundColor(bgColor) end
  1388.   if h == 1 then
  1389.     term.setCursorPos(x, y)
  1390.     term.write(txtLine)
  1391.   else
  1392.     local line, textRow = string.rep(" ", w), y + math.floor(h / 2)
  1393.     for i = y, y + h - 1 do
  1394.       term.setCursorPos(x, i)        
  1395.       term.write(i == textRow and txtLine or line) --# Draw one line of the 'element' (box/rectangle/line-seg)
  1396.     end
  1397.   end
  1398. end
  1399.  
  1400. local function shutDown()
  1401.   rednet.unhost("gtRemote", gtSettings.name .. thisCC)
  1402.   if rednet.isOpen(netSide) then rednet.close(netSide) end
  1403.   term.write("gtHost is OFFLINE")
  1404.   term.setCursorPos(1, 5)
  1405. end
  1406.  
  1407. local function foregroundShell()
  1408.   clearTerm()
  1409.   if fs.exists(tArgs[1]) then
  1410.     local unpack = unpack or table.unpack
  1411.       shell.run(unpack(tArgs))
  1412.     clearTerm()
  1413.   else
  1414.     term.write(tArgs[1] .. " missing")
  1415.     term.setCursorPos(1, 3)
  1416.   end
  1417.   shutDown()
  1418. end
  1419.  
  1420. local function charInput()
  1421.   local _, char
  1422.   while true do
  1423.     _, char = os.pullEvent("char")
  1424.     if char:lower() == "q" and not shellCommand then
  1425.       clearTerm()
  1426.       return shutDown()
  1427.     end
  1428.   end
  1429. end
  1430.  
  1431. do
  1432.   local validActions = {
  1433.     move = {         --# Movement
  1434.       forward = function() return turtle.forward() end;
  1435.       back = function() return turtle.back() end;
  1436.       left = function() return turtle.turnLeft() end;
  1437.       right = function() return turtle.turnRight() end;
  1438.       up = function() return turtle.up() end;
  1439.       down = function() return turtle.down() end;
  1440.     };
  1441.     atk = true;      --# Action - attack
  1442.     dig = {          --# Action - break
  1443.       Forward = function() return turtle.dig() end;
  1444.       Up = function() return turtle.digUp() end;
  1445.       Down = function() return turtle.digDown() end;
  1446.     };
  1447.     dcToggle = true; --# Toggle obstacle check
  1448.     sCmd = true;     --# Shell command
  1449.     put = {          --# Action - place
  1450.       Forward = function() return turtle.place() end;
  1451.       Up = function() return turtle.placeUp() end;
  1452.       Down = function() return turtle.placeDown() end;
  1453.     };
  1454.     inv = true;      --# Refresh inventory
  1455.     sel = true;      --# Select slot (slot)
  1456.     eqp = {          --# Equip item in slot (side)
  1457.       left = function() return turtle.equipLeft() end;
  1458.       right = function() return turtle.equipRight() end;
  1459.     };
  1460.     rds = true;      --# Toggle redstone signal
  1461.     name = true;     --# change name
  1462.     note = true;     --# change description
  1463.     color = true;    --# change color
  1464.     gpsLoc = true;   --# GPS fix
  1465.     refuel = true;   --# refuel
  1466.     gtrQRY = true;   --# QRY
  1467.     lock = true;     --# lock turtle
  1468.     unlock = true;   --# unlock turtle
  1469.   }
  1470.  
  1471.   local function checkDirections()
  1472.     up = turtle.detectUp()
  1473.     down = turtle.detectDown()
  1474.     forward = turtle.detect()
  1475.   end
  1476.  
  1477.   local function doAction(command, action)
  1478.     if lockState and command ~= "gtrQRY" and command ~= "unlock" then return false end
  1479.     local tAction = false
  1480.     if command == "move" then
  1481.       if validActions.move[action] then tAction = validActions.move[action]() end
  1482.       if tAction then
  1483.         if dirCheck then checkDirections() end
  1484.         if gtRedstone then
  1485.           rs.setOutput("front", false)
  1486.           gtRedstone = false
  1487.         end
  1488.         if action ~= "left" and action ~= "right" then getFuelLevel() end
  1489.       end
  1490.     elseif command == "dig" then
  1491.       if validActions.dig[action] then tAction = validActions.dig[action]() end
  1492.       if tAction then
  1493.         inventorySlots()
  1494.         if dirCheck then checkDirections() end
  1495.       end
  1496.     elseif command == "atk" then
  1497.       tAction = turtle.attack()
  1498.       if tAction then
  1499.         turtle.suck()
  1500.         inventorySlots()
  1501.       end
  1502.     elseif command == "dcToggle" then
  1503.       dirCheck = action
  1504.       if dirCheck then
  1505.         checkDirections()
  1506.       else
  1507.         up, down, forward = false, false, false
  1508.       end
  1509.       tAction = true
  1510.     elseif command == "sCmd" then
  1511.       if tArgs[1] or shellCommand then return false end
  1512.       shellCommand = true
  1513.       clearTerm()
  1514.       tAction = shell.run(action)
  1515.       shellCommand, redraw = false, true
  1516.       if tAction then
  1517.         gtRedstone = rs.getOutput("front")
  1518.         getFuelLevel()
  1519.         inventorySlots()
  1520.         if dirCheck then checkDirections() end
  1521.       end
  1522.     elseif command == "put" then
  1523.       if validActions.put[action] then
  1524.         tAction = validActions.put[action]() --# Place
  1525.       else
  1526.         tAction = turtle.place(action) --# Engrave sign
  1527.       end
  1528.       if tAction then
  1529.         inventorySlots()
  1530.         if dirCheck then checkDirections() end
  1531.       end
  1532.     elseif command == "inv" then
  1533.       inventorySlots()
  1534.       tAction = true
  1535.     elseif command == "sel" and type(action) == "number" and action > 0 and action < 17 then
  1536.       tAction = turtle.select(action) --# select user chosen slot
  1537.       selectedSlot = tAction and action or selectedSlot
  1538.       if _CC_VERSION or _HOST then getSlotContents() end
  1539.     elseif command == "rds" then
  1540.       rs.setOutput("front", action)
  1541.       gtRedstone = action
  1542.       tAction = true
  1543.     elseif command == "gtrQRY" then
  1544.       if action == "Full" then
  1545.         gtRedstone = rs.getOutput("front")
  1546.         getFuelLevel()
  1547.         inventorySlots()
  1548.         if dirCheck then checkDirections() end
  1549.       end
  1550.       tAction = true
  1551.     elseif command == "name" or command == "note" then
  1552.       gtSettings[command] = action
  1553.       if command == "name" then os.setComputerLabel(action) redraw = true end
  1554.       saveData()
  1555.       tAction = true
  1556.     elseif command == "color" then
  1557.       if colorBurst[action] then
  1558.         gtSettings.color = action
  1559.         saveData()
  1560.       end
  1561.       tAction = gtSettings.color == action
  1562.     elseif command == "refuel" and gtInventory[selectedSlot].isFuel then
  1563.       tAction = turtle.refuel(action)
  1564.       getFuelLevel()
  1565.       gtInventory[selectedSlot].count = turtle.getItemCount(selectedSlot)
  1566.       if gtInventory[selectedSlot].count == 0 then gtInventory[selectedSlot].isFuel = false slotContents = "<emtpy>" end
  1567.     elseif command == "eqp" then
  1568.       if (action ~= "right" and action ~= "left") or (action == netSide) then return false end
  1569.       tAction = validActions.eqp[action]()
  1570.       gtInventory[selectedSlot].count = turtle.getItemCount(selectedSlot)
  1571.       if _CC_VERSION or _HOST then getSlotContents() end
  1572.     elseif command == "gpsLoc" then
  1573.       loc.x, loc.y, loc.z = gps.locate(2)
  1574.       if not loc.x then
  1575.         loc.x, loc.y, loc.z = "No GPS Fix", "No GPS Fix", "No GPS Fix"
  1576.       end
  1577.       tAction = loc.x ~= "No GPS Fix"
  1578.     elseif command == "lock" then
  1579.       if not gtSettings.password or not unlockedClients[client] then return false end
  1580.       lockState = true
  1581.       unlockedClients[client] = nil
  1582.       unlockedClients.count = math.max(0, unlockedClients.count - 1)
  1583.       tAction = true
  1584.     elseif command == "unlock" then
  1585.       if not lockState then return false end
  1586.       if gtSettings.password and gtSettings.password == action then
  1587.         lockState = false
  1588.         unlockedClients[client] = true
  1589.         unlockedClients.count = unlockedClients.count + 1
  1590.         tAction = true
  1591.       end
  1592.     end
  1593.     return tAction
  1594.   end
  1595.  
  1596.   local function netReceive()
  1597.     local success, complete, newCmdData, encryptedData, decodedData, decryptedData, encKey, id = false, false, { }
  1598.     while true do
  1599.       if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1600.       id, encryptedData = rednet.receive("gtRemote")
  1601.       complete, newCmdData = false, { }
  1602.       if type(encryptedData) == "string" then
  1603.         success, decodedData = pcall(decode, encryptedData)
  1604.         if success and type(decodedData) == "string" then
  1605.           encKey = thisCC .. "gt!Remote" .. tostring(id)
  1606.           success, decryptedData = pcall(decrypt, encKey, decodedData)
  1607.           if success and type(decryptedData) == "string" then
  1608.             success, newCmdData = pcall(textutils.unserialize, decryptedData)
  1609.             if success and type(newCmdData) == "table" and newCmdData.program and newCmdData.program == "gtRemote" and newCmdData.cc and newCmdData.cc == id then
  1610.               complete = true
  1611.             end
  1612.           else
  1613.             encKey = tostring(id) .. "gt!Remote_Broadcast" .. tostring(id)
  1614.             success, decryptedData = pcall(decrypt, encKey, decodedData)
  1615.             if success and type(decryptedData) == "string" then
  1616.               success, newCmdData = pcall(textutils.unserialize, decryptedData)
  1617.               if success and type(newCmdData) == "table" and newCmdData.program and newCmdData.program == "gtRemote" and newCmdData.cc and newCmdData.cc == id then
  1618.                 complete = true
  1619.               end
  1620.             end
  1621.           end
  1622.         end
  1623.       end
  1624.       if complete then
  1625.         client = id
  1626.         if validActions[newCmdData.cmd] then
  1627.           lockState = true
  1628.           if gtSettings.password then
  1629.             if unlockedClients[client] then lockState = false end
  1630.           else
  1631.             lockState = false
  1632.           end
  1633.           return doAction(newCmdData.cmd, newCmdData.action)
  1634.         end
  1635.       end
  1636.       return false
  1637.     end
  1638.   end
  1639.  
  1640.   local function reportStatus(successState)
  1641.     gtSuccess = successState
  1642.     local dataPack = textutils.serialize({
  1643.       program = "gtRemoteHost";
  1644.       cc = tonumber(thisCC);
  1645.       name = gtSettings.name;
  1646.       note = gtSettings.note;
  1647.       color = gtSettings.color;
  1648.       redstone = gtRedstone;
  1649.       lockState = lockState;
  1650.       fuelState = fuelState;
  1651.       fuelAmount = fuelAmount;
  1652.       fuelPercent = fuelPercent;
  1653.       coal = coal;
  1654.       slot = selectedSlot;
  1655.       contents = slotContents;
  1656.       quietCount = 0;
  1657.       loc = { x = loc.x, y = loc.y, z = loc.z };
  1658.       inv = gtInventory;
  1659.       up = up;
  1660.       down = down;
  1661.       forward = forward;
  1662.       dirCheck = dirCheck;
  1663.     })
  1664.     local encKey = tostring(client) .. "gt!Remote" .. thisCC
  1665.     local encryptedData = encode(encrypt(encKey, dataPack))
  1666.     if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1667.     rednet.send(client, encryptedData, "gtRemote")
  1668.   end
  1669.  
  1670.   local function staticTermScreen()
  1671.     local titleText = gtSettings.name .. " / # " .. thisCC .. " / " .. "gtHost " .. gtHver
  1672.     term.setBackgroundColor(black)
  1673.     term.clear()
  1674.     drawElement(1, 1, termX, 1, white, blue, titleText)
  1675.     drawElement(2, 3, 1, 1, gray, black, "Name:")
  1676.     drawElement(2, 4, 1, 1, nil, nil, "Description:")
  1677.     drawElement(2, 5, 1, 1, nil, nil, "Assigned Color:")
  1678.     drawElement(2, 7, 1, 1, nil, nil, "Fuel:")
  1679.     if fuelPercent < 101 then drawElement(2, 8, 1, 1, nil, nil, "Coal equiv:") end
  1680.     drawElement(2, 10, 1, 1, nil, nil, "Redstone output:")
  1681.     if gtSettings.password then drawElement(2, 11, 1, 1, nil, nil, "Unlocked clients:") end
  1682.     drawElement(2, termY - 1, 1, 1, nil, nil, "Last Action Success:")
  1683.   end
  1684.  
  1685.   gtHostKernel = function()
  1686.     local sFuelLimit, sFuelAmount, fuelColor = tostring(math.floor(turtleFuelLimit / 1000))
  1687.     while true do
  1688.       if not tArgs[1] and not shellCommand then
  1689.         if redraw then
  1690.           staticTermScreen()
  1691.           redraw = false
  1692.         end
  1693.         drawElement(18, 3, 1, 1, white, black, gtSettings.name)
  1694.         drawElement(18, 4, 1, 1, silver, nil, gtSettings.note .. string.rep(" ", 24 - #gtSettings.note))
  1695.         drawElement(18, 5, 1, 1, colorBurst[gtSettings.color][2] or red, nil, (colorBurst[gtSettings.color][1] or "Error") .. "     ")
  1696.         fuelColor = fuelPercent > 49 and green or orange
  1697.         drawElement(14, 7, 1, 1, fuelPercent < 10 and red or fuelColor, nil, fuelPercent < 101 and tostring(fuelPercent) or "Unlimited")
  1698.         if fuelPercent < 101 then
  1699.           term.setTextColor(silver)
  1700.           term.write("%   ")
  1701.           sFuelAmount = fuelAmount >= 1000 and tostring(math.floor(fuelAmount / 100) / 10) .. "K" or tostring(fuelAmount)
  1702.           drawElement(23, 7, 1, 1, silver, nil, "(" .. sFuelAmount .. " / " .. sFuelLimit .. "K)     ")
  1703.           drawElement(14, 8, 1, 1, nil, nil, tostring(coal) .. " coal   ")
  1704.         end
  1705.         if gtSettings.password then drawElement(23, 11, 1, 1, silver, nil, tostring(unlockedClients.count) .. "  ") end
  1706.         drawElement(23, 10, 1, 1, gtRedstone and green or red, nil, tostring(gtRedstone) .. "  ")
  1707.         drawElement(23, termY - 1, 1, 1, gtSuccess and green or red, nil, tostring(gtSuccess) .. "  ")
  1708.       end
  1709.       reportStatus(netReceive())
  1710.     end
  1711.   end
  1712. end
  1713.  
  1714. local function firstRun()
  1715.   if not fs.exists("/data") then fs.makeDir("/data") end
  1716.   drawElement(2, 2, 1, 1, nil, nil, "Please name this turtle")
  1717.   drawElement(3, 3, 1, 1, nil, nil, "(8 characters or less)")
  1718.   repeat --# Set host name
  1719.     term.setCursorPos(2, 5)
  1720.     local newName = read():sub(1, 8)
  1721.     gtSettings.name = newName
  1722.   until newName ~= ""
  1723.   os.setComputerLabel(gtSettings.name) --# Set turtle label
  1724.   term.clear()
  1725.   drawElement(2, 2, 1, 1, nil, nil, "Please type in a short")
  1726.   drawElement(2, 3, 1, 1, nil, nil, "description (21 chars.)")
  1727.   repeat --# Set host description
  1728.     term.setCursorPos(2, 5)
  1729.     local newDesc = read():sub(1, 21)
  1730.     gtSettings.note = newDesc
  1731.   until newDesc ~= ""
  1732.   term.clear()
  1733.   drawElement(2, 2, 1, 1, nil, nil, "Select a color")
  1734.   local y = 3
  1735.   for k, v in pairs(colorBurst) do
  1736.     y = y + 1
  1737.     drawElement(2, y, 1, 1, nil, nil, k .. " = " .. v[1])
  1738.   end
  1739.   repeat --# Select color
  1740.     term.setCursorPos(2, 13)
  1741.     local newColor = string.upper(read():sub(1, 1))
  1742.     gtSettings.color = newColor
  1743.   until colorBurst[newColor]
  1744.   term.clear()
  1745.   drawElement(2, 2, 1, 1, nil, nil, "Would you like to password")
  1746.   drawElement(2, 3, 1, 1, nil, nil, "protect this turtle? [Y/N]")
  1747.   term.setCursorPos(2, 5)
  1748.   local lockQ = string.lower(read():sub(1, 1))
  1749.   if lockQ == "y" then
  1750.     local pass
  1751.     drawElement(2, 7, 1, 1, nil, nil, "Please enter a password...")
  1752.     repeat --# Set password
  1753.       term.setCursorPos(2, 9)
  1754.       pass = read()
  1755.     until pass ~= ""
  1756.     gtSettings.password = table.concat(pbkdf2(pass, "gt!Remote", 15))
  1757.     gtSettings.hashedPWs = true
  1758.   end
  1759.   saveData()
  1760. end
  1761.  
  1762. clearTerm()
  1763. if not turtle then error("This is not a turtle.", 0) end
  1764. drawElement(2, 1, 1, 1, nil, nil, "Configuring hardware . . .")
  1765. for _, side in pairs({ "left", "right" }) do
  1766.   if peripheral.isPresent(side) and peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then
  1767.     netSide = side
  1768.     break
  1769.   end
  1770. end
  1771. if netSide == "none" then
  1772.   term.clear()
  1773.   drawElement(2, 2, 1, 1, red, black, "No wireless")
  1774.   drawElement(2, 3, 1, 1, nil, nil, "modem detected!")
  1775.   drawElement(2, 5, 1, 1, nil, nil, "gtHost REQUIRES")
  1776.   drawElement(2, 6, 1, 1, nil, nil, "a wireless modem.")
  1777.   term.setTextColor(colors.white)
  1778.   term.setCursorPos(1, 9)
  1779.   return
  1780. end
  1781. if not fs.exists(config) then
  1782.   firstRun()
  1783.   term.clear()
  1784.   drawElement(2, 3, 1, 1, nil, nil, "Configuration complete . . .")
  1785. else
  1786.   drawElement(2, 3, 1, 1, nil, nil, "Ingesting configuration data . . .")
  1787.   local gtHConfig = fs.open(config, "r") or error("init: Cannot open " .. config .. " for reading", 0)
  1788.   gtSettings = textutils.unserialize(gtHConfig.readAll())
  1789.   gtHConfig.close()
  1790.   if not gtSettings.newColors then
  1791.     local oldColors = {
  1792.       L = "S";
  1793.       Y = "I";
  1794.     }
  1795.     if oldColors[gtSettings.color] then gtSettings.color = oldColors[gtSettings.color] end
  1796.     gtSettings.newColors = true
  1797.     saveData()
  1798.   end
  1799.   if gtSettings.password and not gtSettings.hashedPWs then
  1800.     gtSettings.password = table.concat(pbkdf2(gtSettings.password, "gt!Remote", 15))
  1801.     gtSettings.hashedPWs = true
  1802.     saveData()
  1803.   end
  1804. end
  1805. if gtSettings.password then lockState = true end
  1806. drawElement(2, 5, 1, 1, nil, nil, "Getting fuel level . . .")
  1807. turtleFuelLimit = turtle.getFuelLimit()
  1808. getFuelLevel()
  1809. drawElement(2, 7, 1, 1, nil, nil, "Scanning inventory . . .")
  1810. inventorySlots()
  1811. selectedSlot = turtle.getSelectedSlot()
  1812. drawElement(2, 9, 1, 1, nil, nil, "Examining redstone . . .")
  1813. gtRedstone = rs.getOutput("front")
  1814. drawElement(2, 11, 1, 1, nil, nil, "Acquiring GPS fix . . .")
  1815. if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1816. loc.x, loc.y, loc.z = gps.locate(2)
  1817. if not loc.x then
  1818.   loc.x, loc.y, loc.z = "No GPS Fix", "No GPS Fix", "No GPS Fix"
  1819. end
  1820. drawElement(2, 13, 1, 1, nil, nil, "Hosting services . . .")
  1821. rednet.host("gtRemote", gtSettings.name .. thisCC)
  1822. gtSuccess = true
  1823. if tArgs[1] then
  1824.     parallel.waitForAny(foregroundShell, gtHostKernel)
  1825. else
  1826.   redraw = true
  1827.   parallel.waitForAny(gtHostKernel, charInput)
  1828. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement