Guest User

Untitled

a guest
Apr 8th, 2013
853
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.22 KB | None | 0 0
  1. -- File usage:
  2. --
  3. --  Just copy and paste this code on to some random file on a disk and create another startup file named "startup" on that disk.
  4. --    In "startup" put (replace [NAME] with the filename you put this code into)
  5. --      os.loadAPI("disk/[NAME]")"
  6. --
  7. --  Note if using Encryption: If you plan to use this code on different machines, BUT you want to use the an RFID card between them
  8. --    (you have one machine for reading and one for writing), you MUST MUST MUST use the same disk, OR copy the
  9. --    "key-Blowfish" file to every other disk you want to use with that RFID card with
  10. --
  11. --  Free software license: I am posting this under the GNU GPL (GNU General Public License), that is to say, you can
  12. --    take this code and do whatever you want with it, but if you distrubte it, you must also do so under the GNU GPL.
  13. --    
  14. --    I also ask you give credit to me as the original writer
  15. --
  16. --      --Angellus_Mortis
  17. --
  18.  
  19. -- Returns a handle to a peripheral connect of a specificed type
  20. -- Returns nil if peripheral of type is not found
  21. -- Input:
  22. --  type (string) : type of peripheral to return a handle for
  23. local function getPeripheral(type)
  24.   local sides = {"top", "bottom", "left", "right", "back"}
  25.   local i = 1
  26.   repeat
  27.     if  peripheral.getType(sides[i]) == type then
  28.       return peripheral.wrap(sides[i])
  29.     end
  30.     i = i + 1
  31.   until i == 6
  32.     return nil
  33. end
  34.  
  35. -- Changes the color to write a quick message and then changes it back
  36. -- Only changes color if term is in color
  37. -- Input:
  38. --  text (string)     : text to output in color
  39. --  someColor (color) : color to output the text in
  40. local function writeColorMessage(text, someColor)
  41.   if term.isColor() then
  42.     term.setTextColor(someColor)
  43.   end
  44.   term.write(text)
  45.   if term.isColor() then
  46.     term.setTextColor(colors.white)
  47.   end
  48. end
  49.  
  50. -- Callback for when scanning starts from reader
  51. -- By default,
  52. --  this looks for an attached montior (should be 2x1)
  53. --  And just displays "ID Required"
  54. --  Changes background to Cyan and text to black
  55. --  Turns off signal to door (see onValidCard for more)
  56. local function onScanStart()
  57.   local screen = getPeripheral("monitor")
  58.  
  59.   -- turn off door signal
  60.   redstone.setBundledOutput("top", 0)
  61.   if not screen then
  62.     -- Throw error to console if monitor was not found
  63.     writeColorMessage("Error: ", colors.red)
  64.     term.write("No Monitor Detected!")
  65.     print()
  66.   else
  67.     -- Write message
  68.     screen.setTextScale(1.8)
  69.     screen.clear()
  70.     screen.setCursorPos(1, 2)
  71.     if screen.isColor() then
  72.       screen.setTextColor(colors.black)
  73.       screen.setBackgroundColor(colors.cyan)
  74.     end
  75.     screen.write("ID Required")
  76.   end
  77. end
  78.  
  79. -- Callback when an invalid card is thown from Reader
  80. -- By default,
  81. --  this looks for an attached montior (should be 2x1)
  82. --  And just displays "ID Required" in black
  83. --  displays "Not Authorized!" in red
  84. --  Cyan background
  85. local function onInvalidCard()
  86.   local screen = getPeripheral("monitor")
  87.  
  88.   -- Throw error to console if monitor was not found
  89.   if not screen then
  90.     writeColorMessage("Error: ", colors.red)
  91.     term.write("No Monitor Detected!")
  92.     print()
  93.   else
  94.     -- Write message
  95.     screen.setTextScale(1.4)
  96.     screen.clear()
  97.     screen.setCursorPos(4, 2)
  98.     if screen.isColor() then
  99.       screen.setTextColor(colors.black)
  100.       screen.setBackgroundColor(colors.cyan)
  101.     end
  102.     screen.write("ID Required")
  103.     screen.setCursorPos(3, 4)
  104.     if screen.isColor() then
  105.       screen.setTextColor(colors.red)
  106.     end
  107.     screen.write("Not Authorized!")
  108.   end
  109. end
  110.  
  111. -- Callback for when valid card is thrown from reader
  112. -- By default,
  113. --  this looks for an attached montior (should be 2x1)
  114. --  And just displays "ID Required" in black
  115. --  displays "Access Granted" in green
  116. --  Cyan background
  117. --  
  118. --  Sends white wire signal on top of the monitor
  119. --  To set up a door lock, just connect a white wire to the top
  120. --  then connect the wire to a door.
  121. --  Also set up monitor so the user knows what is going on
  122. local function onValidCard()
  123.   local screen = getPeripheral("monitor")
  124.  
  125.   -- Throw error to console if monitor was not found
  126.   if not screen then
  127.     writeColorMessage("Error: ", colors.red)
  128.     term.write("No Monitor Detected!")
  129.     print()
  130.   else
  131.     -- Write message
  132.     screen.setTextScale(1.4)
  133.     screen.clear()
  134.     screen.setCursorPos(4, 2)
  135.     if screen.isColor() then
  136.       screen.setTextColor(colors.black)
  137.       screen.setBackgroundColor(colors.cyan)
  138.     end
  139.     screen.write("ID Required")
  140.     screen.setCursorPos(3, 4)
  141.     if screen.isColor() then
  142.       screen.setTextColor(colors.green)
  143.     end
  144.     screen.write("Access Granted")
  145.  
  146.     --Open door
  147.     redstone.setBundledOutput("top", 1)
  148.   end
  149. end
  150.  
  151. -- Global varibles
  152. local data = {["useEncryption"] = true, ["encryptionType"] = "Blowfish", ["keySize"] = nil}
  153.  
  154. -- test if the frist character of a given string is the one supplied
  155. -- Input:
  156. --  testString (string)   : character to test for (only ONE character)
  157. --  inputString (string)  : string to test against
  158. local function checkFirstChar(testString, inputString)
  159.   if string.lower(testString) == string.lower(string.sub(inputString, 1, 1)) then
  160.     return true
  161.   else
  162.     return false
  163.   end
  164. end
  165.  
  166. -- Prints program header
  167. -- Input:
  168. --  isAdmin (bool)  : whether or not program is in admin mode
  169. local function header(isAdmin, type)
  170.   local title
  171.   if not type then
  172.     title = "RFID Writer/Reader"
  173.   elseif type == "writer" then
  174.     title = "RFID Writer"
  175.   elseif type == "reader" then
  176.     title = "RFID Reader"
  177.   end
  178.   term.clear()
  179.   term.setCursorPos(1, 1)
  180.   if isAdmin then
  181.     writeColorMessage(title .. " - Admin Mode", colors.green)
  182.     print()
  183.   else
  184.     writeColorMessage(title, colors.cyan)
  185.     print()
  186.   end
  187.   print()
  188. end
  189.  
  190. -- Returns a string of the encryption key to use to encrypt the RFID text with
  191. -- Input:
  192. --  encryptor (handle)  : handle to cryptographic accelerator
  193. local function getKey(encryptor)
  194.   local file = fs.open("disk/key-"..data["encryptionType"], "r")
  195.  
  196.   -- If the key has not been generated yet, generate it
  197.   if not file then
  198.     file = fs.open("disk/key-"..data["encryptionType"], "w")
  199.     local key = encryptor.generateSymmetricKey(data["encryptionType"], data["keySize"])
  200.     local keyEnc = key.encode()
  201.     file.write(keyEnc)
  202.     file.close()
  203.     return keyEnc
  204.   end
  205.  
  206.   local key = file.readLine()
  207.   file.close()
  208.   return key
  209. end
  210.  
  211. -- Determines if text needs decrypted and then returns it
  212. -- Input:
  213. --  message (string)    : text possibly decrypted
  214. --  encryptor (handle)  : handle to cryptographic accelerator
  215. local function testForEncryption(message, encryptor)
  216.   -- If using encryption..
  217.   if data["useEncryption"] and encryptor then
  218.     local key = encryptor.decodeKey(data["encryptionType"], getKey(encryptor))
  219.     -- Attempt to decrypt the message
  220.     local status, err = pcall(function() message = key.decrypt(data["encryptionType"], message) end)
  221.     -- If failes, set message to empty string to force password check to fail
  222.     if not status then
  223.       message = ""
  224.     end
  225.   end
  226.  
  227.   return message
  228. end
  229.  
  230. -- Determines if text needs to be encrypted or not and then returns it
  231. -- Input:
  232. --  text (string)       : text to be written
  233. --  encryptor (handle)  : handle to cryptographic accelerator
  234. local function testEncode(text, encryptor)
  235.   if data["useEncryption"] and encryptor then
  236.     -- Convert the string into an object
  237.     local key = encryptor.decodeKey(data["encryptionType"], getKey(encryptor))
  238.     text = key.encrypt(data["encryptionType"], text)
  239.   end
  240.  
  241.   return text
  242. end
  243.  
  244. local function resetScreen()
  245.   term.setCursorPos(1,1)
  246.   term.clear()
  247. end
  248.  
  249.  
  250. -- Main program for the writer
  251. -- Input:
  252. --  param (string)  : optional parameter for admin mode
  253. function Writer(param)
  254.   -- Writing Variables
  255.   local label
  256.   local text
  257.   local writer = getPeripheral("rfid writer")  
  258.  
  259.   -- Encryption vars
  260.   local encryptor = getPeripheral("cryptographic accelerator")
  261.  
  262.   -- Admin related vars
  263.   local admin = false
  264.   local secretParam = '146790'
  265.   -- Simply delete the password if you want to prompt the user for it
  266.   local adminPassword = ''
  267.  
  268.   -- Test if admin is to run
  269.   if param == secretParam then
  270.       admin = true
  271.       -- If auto mode is off, ask for admin password
  272.       if (adminPassword == '') then
  273.         header(true, "writer")
  274.         term.write("Enter the admin password: ")
  275.         if term.isColor() then
  276.           term.setTextColor(colors.cyan)
  277.         end
  278.         adminPassword = read("*")
  279.         if term.isColor() then
  280.           term.setTextColor(colors.white)
  281.         end
  282.       end
  283.     end
  284.  
  285.     -- If RFID writer is not connected
  286.     while not writer do
  287.       header(admin, "writer")
  288.       term.write("No RFID Writer Connected! ")
  289.       writeColorMessage(":(", colors.red)
  290.       print()
  291.       term.write("Please connect one and press ")
  292.       writeColorMessage("ENTER", colors.green)
  293.       print()
  294.       local event, param1
  295.       repeat
  296.         event, param1 = os.pullEvent ("key")
  297.       until param1 == 28
  298.       writer = getPeripheral("rfid writer")
  299.     end
  300.  
  301.     -- If no valid card is present
  302.     while (not writer.isPresent()) or writer.isCoded() do
  303.       header(admin, "writer")
  304.       term.write("RFID Card is either missing or already coded ")
  305.       writeColorMessage(":(", colors.red)
  306.       print()
  307.       term.write("Please insert a blank RFID card and press ")
  308.       writeColorMessage("ENTER", colors.green)
  309.       print()
  310.       local event, param1
  311.       repeat
  312.         event, param1 = os.pullEvent ("key")
  313.       until param1 == 28
  314.     end
  315.    
  316.     header(admin, "writer")
  317.  
  318.     -- Set Disk Label
  319.     term.write("Enter the label for the disk: ")
  320.     if term.isColor() then
  321.       term.setTextColor(colors.cyan)
  322.     end
  323.     label = read()
  324.     if term.isColor() then
  325.       term.setTextColor(colors.white)
  326.     end
  327.    
  328.  
  329.     if label == secretParam then
  330.       return Writer(label)
  331.     end
  332.        
  333.     -- Gets text to encode
  334.     term.write("Enter text to write to RFID Card: ")
  335.     if term.isColor() then
  336.       term.setTextColor(colors.cyan)
  337.     end
  338.     text = read()
  339.     if term.isColor() then
  340.       term.setTextColor(colors.white)
  341.     end
  342.  
  343.     -- Y-offset for any admin mode related messages
  344.     local offset = 0
  345.  
  346.     print()
  347.     print("Starting RFID Encoding...")
  348.  
  349.     if not admin then
  350.       -- Encodes card
  351.       writer.encode(testEncode(text, encryptor), label)
  352.     else
  353.       -- Passes in admin password
  354.       writer.encode(testEncode(text, encryptor), label, adminPassword)
  355.       -- Does not really test. Uses progress to determine if the password was successful
  356.       term.write("Testing admin password...")
  357.       offset = offset + 1
  358.     end
  359.  
  360.     os.sleep(1)
  361.  
  362.     local progress = writer.getProgress()
  363.    
  364.     -- if Admin mode, display if password was successful
  365.     if progress >= 0 and admin then
  366.       offset = offset + 1
  367.       term.write("..Invalid!")
  368.       print()
  369.       -- turn off admin mode so progress bar will show
  370.       admin = false
  371.     elseif admin then
  372.       term.write("..Success")
  373.       print()
  374.       print()
  375.     end
  376.  
  377.     -- if not admin mode (or password failed) show progress bar
  378.     if not admin then
  379.       term.setCursorPos(1, 8 + offset)
  380.       local toDraw = 1
  381.       -- adjust for varible screen width
  382.       local w = term.getSize() - 10
  383.       local frac = 1 / w
  384.       -- Draw empty progress bar
  385.       term.write("0% [")
  386.       term.setCursorPos(5 + w, 8 + offset)
  387.       term.write("] 100%")
  388.       -- Draw progress line
  389.       while progress >= 0 do    
  390.         term.setCursorPos(4 + toDraw, 8 + offset)
  391.         while progress >= (toDraw * frac) do
  392.           term.write("-")
  393.           toDraw = toDraw + 1
  394.         end
  395.         os.sleep(1)
  396.         progress = writer.getProgress()
  397.       end
  398.       -- make sure progress bar gets filled ;)
  399.       while (toDraw * frac) <= 1 do
  400.         term.write("-")
  401.         toDraw = toDraw + 1
  402.       end
  403.       print()
  404.     end
  405.    
  406.     print("Text successfully written to card.")
  407.     print()
  408.     term.write("Press ")
  409.     writeColorMessage("ENTER", colors.green)
  410.     term.write(" to exit...")
  411.     local event, param1
  412.     repeat
  413.       event, param1 = os.pullEvent ("key")
  414.     until param1 == 28
  415.     resetScreen()
  416.  
  417.     Writer()
  418. end
  419.  
  420. -- Main program for the reader
  421. function Reader()
  422.   -- Reading Varibles
  423.   local reader = getPeripheral("rfid reader")
  424.   local allowOtherCards = false
  425.   local detected = 0
  426.   local valid = false
  427.   local password = ""
  428.  
  429.  
  430.   -- Encryption vars
  431.   local encryptor = getPeripheral("cryptographic accelerator")
  432.  
  433.   -- If RFID reader is not connected
  434.   while not reader do
  435.     header(false, "reader")
  436.     print("No RFID Reader Connected! :(")
  437.     term.write("Please connect one and press ")
  438.     writeColorMessage("ENTER", colors.green)
  439.     print()
  440.     local event, param1
  441.     repeat
  442.       event, param1 = os.pullEvent ("key")
  443.     until param1 == 28
  444.     reader = getPeripheral("rfid reader")
  445.   end
  446.  
  447.   -- If password is not set, prompt user to provide a card with one on it
  448.   -- IMPORTANT! Only one RFID card can be present when setting password or else
  449.   --       the wrong password may be set
  450.   while password == "" do
  451.     header(false, "reader")
  452.     print("Password not set. Verify the card with the valid ")
  453.     print("password on it is in range and is the ONLY card ")
  454.     term.write("within range and press ")
  455.     writeColorMessage("ENTER", colors.green)
  456.     print()
  457.     local event, param1
  458.     repeat
  459.       event, param1 = os.pullEvent ("key")
  460.     until param1 == 28
  461.     print()
  462.     print("Scanning for card...")
  463.     reader.scan()
  464.     -- Repeat pull event until done scanning
  465.     repeat
  466.       event, param1 = os.pullEvent()
  467.       if (event == "rfid_detected") then
  468.         print("Card found. Trying to set password...")
  469.         password = testForEncryption(param1, encryptor)
  470.  
  471.         if not (password == "") then
  472.           -- Some stuff for the user
  473.           print("Password set")
  474.           print("Starting reader...")
  475.           sleep(1)
  476.         end
  477.       -- Could not set password
  478.       elseif event == "rfid_scan_done" and password == "" then
  479.         if data["useEncryption"] then
  480.           print("No card found or unable to decrypt password!")
  481.           print()
  482.           print("Make sure you are using the same encryption key for the reader and writer.")
  483.           sleep(5)
  484.         else
  485.           print("No card found!")
  486.           sleep(2)
  487.         end
  488.       end
  489.     until event == "rfid_scan_done" or not (password == "")
  490.   end
  491.  
  492.   -- ASk the user if they want to still throw a valid card event when there
  493.   -- are other invalid cards around
  494.   local doRepeat = true
  495.   repeat
  496.     header(false, "reader")
  497.     print("Do you want to throw valid card with other invalid cards around?")
  498.     term.write("Enter yes/[no]: ")
  499.     if term.isColor() then
  500.       term.setTextColor(colors.cyan)
  501.     end
  502.     local usrInp = read()
  503.     if term.isColor() then
  504.       term.setTextColor(colors.white)
  505.     end
  506.     if checkFirstChar('n', usrInp) or usrInp == '' then
  507.       allowOtherCards = false
  508.       doRepeat = false
  509.     elseif checkFirstChar('y', usrInp) then
  510.       allowOtherCards = true
  511.       doRepeat = false
  512.     end
  513.   until not doRepeat
  514.  
  515.   -- Start reading loop
  516.   while true do
  517.     header(false, "reader")
  518.     valid = false
  519.     detected = 0
  520.  
  521.     print("Scanning for cards...")
  522.     print()
  523.     reader.scan()
  524.     onScanStart()
  525.  
  526.     local event, message
  527.     repeat
  528.       event, message = os.pullEvent()
  529.  
  530.       if event == "rfid_detected" then
  531.         print("An RFID Card was detected.")
  532.         term.write("Testing password...")
  533.  
  534.         if testForEncryption(message, encryptor) == password then
  535.           term.write("..Success")
  536.           if ((not allowOtherCards) and detected == 0) or allowOtherCards then
  537.             valid = true
  538.           end  
  539.         else
  540.           term.write("..Invalid")
  541.           if not allowOtherCards then
  542.             valid = false
  543.           end
  544.         end
  545.         print()
  546.         print()
  547.         detected = detected + 1
  548.       end
  549.     until event == "rfid_scan_done"
  550.  
  551.     if detected == 0 then
  552.       print("No cards found.")
  553.     elseif valid then
  554.       print("Valid password!")
  555.       onValidCard()
  556.     elseif not allowOtherCards then
  557.       print("Invalid password or other cards nearby!")
  558.       onInvalidCard()
  559.     else
  560.       print("Invalid password!")
  561.  
  562.       onInvalidCard()
  563.     end
  564.     os.sleep(5)
  565.   end
  566.  
  567.   Reader()
  568. end
  569.  
  570. function runRFID()
  571.   local reader = getPeripheral("rfid reader")
  572.   local writer = getPeripheral("rfid writer")
  573.  
  574.   -- If RFID writer/reader is not connected
  575.   while not reader and not writer do
  576.     header(false)
  577.     print("No RFID Writer/Reader Connected! :(")
  578.     term.write("Please connect one and press ")
  579.     writeColorMessage("ENTER", colors.green)
  580.     print()
  581.     local event, param1
  582.     repeat
  583.       event, param1 = os.pullEvent ("key")
  584.     until param1 == 28
  585.     reader = getPeripheral("rfid reader")
  586.     writer = getPeripheral("rfid writer")
  587.   end
  588.  
  589.   if reader and writer then
  590.     local doRepeat = true
  591.     repeat
  592.       header(false)
  593.       print("Both a reader and writer connected.")
  594.       term.write("Enter [reader]/writer: ")
  595.       if term.isColor() then
  596.         term.setTextColor(colors.cyan)
  597.       end
  598.       local usrInp = read()
  599.       if term.isColor() then
  600.         term.setTextColor(colors.white)
  601.       end
  602.       if checkFirstChar('r', usrInp) or usrInp == '' then
  603.         Reader()
  604.         doRepeat = false
  605.       elseif checkFirstChar('w', usrInp) then
  606.         Writer()
  607.         doRepeat = false
  608.       end
  609.     until not doRepeat
  610.   elseif reader then
  611.     Reader()
  612.   elseif writer then
  613.     Writer()
  614.   end
  615. end
  616.  
  617. function startup()
  618.   local reader = getPeripheral("rfid reader")
  619.   local writer = getPeripheral("rfid writer")
  620.   local encryptor = getPeripheral("cryptographic accelerator")
  621.   header(false)
  622.   writeColorMessage("Booting.", colors.magenta)
  623.   sleep(1)
  624.   writeColorMessage(".", colors.magenta)
  625.   sleep(1)
  626.   writeColorMessage(".", colors.magenta)
  627.   print()
  628.  
  629.   if encryptor then
  630.     writeColorMessage("Encryptor found", colors.cyan)
  631.     print()
  632.     print("Using encryption...")
  633.     data["useEncryption"] = true
  634.   else
  635.     writeColorMessage("No encryptor found", colors.red)
  636.     print()
  637.     print("Turning off encryption...")
  638.     data["useEncryption"] = false
  639.   end
  640.   sleep(1)
  641.  
  642.   if not reader and not writer then
  643.     writeColorMessage("Reader and writer missing", colors.red)
  644.     print()
  645.     print("Prompting to place one...")
  646.   elseif reader and writer then
  647.     writeColorMessage("Reader ", colors.green)
  648.     term.write("and ")
  649.     writeColorMessage("Writer ", colors.yellow)
  650.     term.write("both found")
  651.     print()
  652.     print("Prompting which to use...")
  653.   elseif reader then
  654.     writeColorMessage("Reader found", colors.green)
  655.     print()
  656.     print("Starting reader...")
  657.   elseif writer then
  658.     writeColorMessage("Writer found", colors.yellow)
  659.     print()
  660.     print("Starting writer...")
  661.   end
  662.   sleep(1)
  663.  
  664.   runRFID()
  665. end
  666.  
  667. function os.pullEvent(_sFilter)
  668.    local event = { os.pullEventRaw(_sFilter) }
  669.    if event[1] == "terminate" then
  670.      runRFID()
  671.    end
  672.    return unpack(event)
  673.  end
  674.  
  675. startup()
Advertisement
Add Comment
Please, Sign In to add comment