Advertisement
LDDestroier

Whisk - File/Folder modem file sender (CC)

Feb 26th, 2016
1,402
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.65 KB | None | 0 0
  1. --[[
  2.     Whisk - File/Folder Transmitter for ComputerCraft
  3.      by EldidiStroyrr
  4.  
  5.     Use the GUI by running w/o arguments
  6.    
  7.     get with
  8.      pastebin get 4ZRHE4Ar whisk
  9.      std pb 4ZRHE4Ar whisk
  10.      std ld whisk whisk
  11.  
  12.     Whisk is now on SimSoft! Install w/ storecode jVELp2st
  13. --]]
  14.  
  15. local channel = 2846
  16. local modem = peripheral.find("modem")
  17.  
  18. local yield = function()
  19.     os.queueEvent("yield")
  20.     os.pullEvent("yield")
  21. end
  22.  
  23. local displayHelp = function()
  24.     local helptxt = [[
  25. Whisk - file/folder sender
  26.  
  27. Syntax:
  28.  whisk
  29.  whisk send <path> [idfilter] [password]
  30.  whisk receive [path] [idfilter] [password]
  31. ]]
  32.     write(helptxt)
  33. end
  34.  
  35. fixstr = function(str) --replaces those annoying tabs with spaces, which fixes encryption
  36.     if not type(str) == "string" then return str end
  37.     local fix = string.gsub(str,string.char(9),"  ")
  38.     return fix
  39. end
  40.  
  41. local defaultKey = "swordfish" --the most secure.
  42. local tArg = {...}
  43. local mode, itPath, idfilter, enckey = tArg[1], tArg[2], tonumber(tArg[3]), tArg[4], tArg[5]
  44. filetree = {}
  45. if not enckey then
  46.     enckey = defaultKey
  47. end
  48. if tArg[5] == "y" then
  49.     doReadOnly = true
  50. else
  51.     doReadOnly = false
  52. end
  53.  
  54. --API made by valithor.
  55. local encrypt = function(msg,key)
  56.     local num = ""
  57.     for i = 1, #key do
  58.         local let = key:sub(i,i):byte()
  59.         num = let <= 9  and num.."99"..let or let<=99 and num.."9"..let or num..let
  60.         num = #msg..num
  61.     end
  62.     math.randomseed(tonumber(num))
  63.     local encrypt = ""
  64.     for i = 1, #msg do
  65.         local rotation = math.random(0,94)
  66.         local byte = msg:sub(i,i):byte()
  67.         local rotate = rotation+byte <= 127 and rotation +byte or ((rotation+byte)%127)+32
  68.         encrypt = encrypt..string.char(rotate)
  69.     end
  70.     return encrypt
  71. end
  72.  
  73. local decrypt = function(msg,key)
  74.     local num = ""
  75.     for i = 1, #key do
  76.         local let = key:sub(i,i):byte()
  77.         num = let <= 9 and num.."99"..let or let<=99 and num.."9"..let or num..let
  78.         num = #msg..num
  79.     end
  80.     math.randomseed(tonumber(num))
  81.     local decrypt = ""
  82.     for i = 1, #msg do
  83.         local rotation = math.random(0,94)
  84.         local byte = msg:sub(i,i):byte()
  85.         local rotate = byte-rotation >= 32 and byte-rotation or byte-rotation
  86.         if rotate < 32 then
  87.             rotate = rotate+95
  88.         end
  89.         decrypt = decrypt..string.char(rotate)
  90.     end
  91.     return decrypt
  92. end
  93.  
  94. local tEnc = function(msg)
  95.     return encrypt(encrypt(tostring(msg),enckey),tostring(math.floor(os.time()/2)))
  96. end
  97. local tDec = function(msg)
  98.     return decrypt(decrypt(tostring(msg),enckey),tostring(math.floor(os.time()/2)))
  99. end
  100.  
  101. listAll = function(_path, _files, noredundant) --Thanks Lyqyd!
  102.     local path = _path or ""
  103.     local files = _files or {}
  104.     if #path > 1 then table.insert(files, path) end
  105.     for _, file in ipairs(fs.list(path)) do
  106.         local path = fs.combine(path, file)
  107.         if fs.isDir(path) then
  108.             listAll(path, files)
  109.         else
  110.             table.insert(files, path)
  111.         end
  112.     end
  113.     if noredundant then
  114.         for a = 1, #files do
  115.             if fs.isDir(tostring(files[a])) then
  116.                 if #fs.list(tostring(files[a])) ~= 0 then
  117.                     table.remove(files,a)
  118.                 end
  119.             end
  120.         end
  121.     end
  122.     return files
  123. end
  124.  
  125. local function choice(input)
  126.     local event, button
  127.     repeat
  128.         event, button = os.pullEvent("key")
  129.         if type(button) == "number" then button = keys.getName(button) end
  130.         if button == nil then button = " " end
  131.     until string.find(input, button)
  132.     return button
  133. end
  134.  
  135. local drawThing = function(text,y,t,b)
  136.     local scr_x, scr_y = term.getSize()
  137.     local _pt,_pb = term.getTextColor(), term.getBackgroundColor()
  138.     if t then term.setTextColor(t) else term.setTextColor(colors.black) end
  139.     if b then term.setBackgroundColor(b) else term.setBackgroundColor(colors.white) end
  140.     term.setCursorPos(1,y-1)
  141.     term.clearLine()
  142.     term.setCursorPos((scr_x/2)-(#text/2),y)
  143.     term.clearLine()
  144.     print(text)
  145.     term.clearLine()
  146.     term.setTextColor(_pt)
  147.     term.setBackgroundColor(_pb)
  148. end
  149.  
  150. output = {}
  151.  
  152. local send = function()
  153.     if not fs.exists(itPath) then
  154.         error("No such file.")
  155.     end
  156.     contents = {}
  157.     rawContents = {}
  158.     if not fs.isDir(itPath) then
  159.         local file = fs.open(itPath,"r")
  160.         line = ""
  161.         local s = 0
  162.         while line do
  163.             line = file.readLine()
  164.             if line then
  165.                 table.insert(rawContents,fixstr(line))
  166.                 table.insert(contents,tEnc(fixstr(line)))
  167.                 if s >= 64 then
  168.                     yield()
  169.                     s = 0
  170.                 else
  171.                     s = s + 1
  172.                 end
  173.             end
  174.         end
  175.         filetree = {[fs.getName(itPath)] = {fyle = contents, dir = false}}
  176.         file.close()
  177.         output = {id = os.getComputerID(), files = filetree}
  178.     else
  179.         filelist = {}
  180.         _filelist = listAll(itPath,nil,true)
  181.         if not doReadOnly then
  182.             for a = 1, #_filelist do
  183.                 if not fs.isReadOnly(_filelist[a]) then
  184.                     table.insert(filelist,_filelist[a])
  185.                 end
  186.             end
  187.         else
  188.             filelist = _filelist
  189.         end
  190.         for a = 1, #filelist do
  191.             local isDir
  192.             contents = {}
  193.             rawContents = {}
  194.             if not fs.isDir(filelist[a]) then
  195.                 local file = fs.open(filelist[a],"r")
  196.                 local line = ""
  197.                 local s = 0
  198.                 while line do
  199.                     line = file.readLine()
  200.                     if line then
  201.                         table.insert(contents,tEnc(fixstr(line)))
  202.                         table.insert(rawContents,fixstr(line))
  203.                         if s >= 64 then
  204.                             yield()
  205.                             s = 0
  206.                         else
  207.                             s = s + 1
  208.                         end
  209.                     end
  210.                 end
  211.                 file.close()
  212.                 isDir = false
  213.             else
  214.                 contents = {""}
  215.                 isDir = true
  216.             end
  217.             if fs.combine("",shell.resolve(itPath)) == "" then --This oughta fix things
  218.                 filelist[a] = fs.combine("root"..os.getComputerID(),filelist[a])
  219.             end
  220.             filetree[filelist[a]] = {fyle = contents, dir = isDir}
  221.         end
  222.         output = {id = os.getComputerID(), files = filetree}
  223.     end
  224.     modem.transmit(channel,channel,output)
  225. end
  226. local receive = function(GUImode)
  227.     local combinedSize = 0
  228.     local filecount = 0
  229.     --local event, side, sendID, repChannel, msg
  230.     while true do
  231.         input = {}
  232.         event, side, sendChannel, repChannel, msg = os.pullEvent()
  233.         if event == "char" and string.lower(side) == "x" then
  234.             if not GUImode then
  235.                 print("Cancelled.")
  236.             end
  237.             return 0,0,false
  238.         end
  239.         if type(msg) == "table" then
  240.             if type(msg.files) == "table" and (idfilter or msg.id) == msg.id then
  241.                 if GUImode then
  242.                     term.setBackgroundColor(colors.gray)
  243.                     term.clear()
  244.                     drawThing("Decrypting...",3)
  245.                 else
  246.                     print("Decrypting...")
  247.                 end
  248.                 break
  249.             end
  250.         end
  251.     end
  252.     for k,v in pairs(msg.files) do
  253.         local fee
  254.         if not itPath then
  255.             fee = k
  256.         else
  257.             local slashpos = string.find(k,"/") or 1
  258.             fee = fs.combine(itPath,k:sub(slashpos))
  259.         end
  260.         local doOverwrite = true
  261.         if fs.exists(fee) and fee == k then
  262.             if GUImode then
  263.                 drawThing("Overwrite '"..fee.."'? [Y/N]",6)
  264.             else
  265.                 print("Overwrite '"..fee.."'? [Y/N]")
  266.             end
  267.             if choice("yn") == "n" then
  268.                 doOverwrite = false
  269.             else
  270.                 doOverwrite = true
  271.             end
  272.         end
  273.         if doOverwrite then
  274.             filecount = filecount + 1
  275.             if not fs.exists(fs.getDir(fee)) then fs.makeDir(fs.getDir(fee)) end
  276.             if type(v) == "table" then
  277.                 if v.dir then
  278.                     fs.makeDir(fee)
  279.                 else
  280.                     local file = fs.open(fee,"w")
  281.                     if file then
  282.                         for a = 1, #v.fyle do
  283.                             file.writeLine(fixstr(tDec(v.fyle[a])))
  284.                             if a % 32 == 0 then
  285.                                 yield()
  286.                             end
  287.                         end
  288.                         file.close()
  289.                         combinedSize = combinedSize + fs.getSize(fee)
  290.                     end
  291.                 end
  292.             end
  293.         end
  294.     end
  295.     return filecount, combinedSize, true
  296. end
  297.  
  298. local sendGUI = function()
  299.     term.setBackgroundColor(colors.gray)
  300.     term.clear()
  301.     drawThing("Which file/folder?",3)
  302.     itPath = ""
  303.     repeat
  304.         term.setCursorPos(1,6)
  305.         term.setTextColor(colors.black)
  306.         term.setBackgroundColor(colors.lightGray)
  307.         term.clearLine()
  308.         write(">")
  309.         sleep(0)
  310.         itPath = read()
  311.     until string.gsub(itPath," ","") ~= ""
  312.     term.setTextColor(colors.white)
  313.     term.setBackgroundColor(colors.gray)
  314.     if not fs.exists(itPath) then
  315.         drawThing("Doesn't exist!",3)
  316.         sleep(0.6)
  317.         return false
  318.     end
  319.     drawThing("Encryption key? (optional)",3)
  320.     enckey = nil
  321.     term.setCursorPos(1,6)
  322.     term.setTextColor(colors.black)
  323.     term.setBackgroundColor(colors.lightGray)
  324.     term.clearLine()
  325.     write(">")
  326.     sleep(0)
  327.     enckey = read("*")
  328.     if enckey == "" then enckey = defaultKey end
  329.     drawThing("ID filter? (optional)",3)
  330.     idfilter = nil
  331.     term.setCursorPos(1,6)
  332.     term.setTextColor(colors.black)
  333.     term.setBackgroundColor(colors.lightGray)
  334.     term.clearLine()
  335.     write(">")
  336.     sleep(0)
  337.     idfilter = tonumber(read())
  338.     drawThing("Do read-only files/folders? (Y/N)",3)
  339.     doReadOnly = false
  340.     term.setCursorPos(1,6)
  341.     term.setTextColor(colors.black)
  342.     term.setBackgroundColor(colors.lightGray)
  343.     term.clearLine()
  344.     sleep(0)
  345.     local thing = choice("yn")
  346.     if thing == "y" then doReadOnly = true else doReadOnly = false end
  347.     local thang = "Encrypting"
  348.     if idfilter then
  349.         thang = thang.." for ID "..tostring(idfilter).."..."
  350.     else
  351.         thang = thang.."..."
  352.     end
  353.     term.setBackgroundColor(colors.gray)
  354.     term.clear()
  355.     drawThing(thang,3)
  356.     send()
  357.     drawThing("Sent '"..itPath.."'!",3)
  358.     sleep(0)
  359.     return true
  360. end
  361.  
  362. local receiveGUI = function()
  363.     term.setBackgroundColor(colors.gray)
  364.     term.clear()
  365.     drawThing("Save as what? (optional)",3)
  366.     itPath = nil
  367.     term.setCursorPos(1,6)
  368.     term.setTextColor(colors.black)
  369.     term.setBackgroundColor(colors.lightGray)
  370.     term.clearLine()
  371.     write(">")
  372.     sleep(0)
  373.     itPath = read()
  374.     if string.gsub(itPath," ","") == "" then
  375.         itPath = nil
  376.     end
  377.     drawThing("Decryption key? (optional)",3)
  378.     enckey = nil
  379.     term.setCursorPos(1,6)
  380.     term.setTextColor(colors.black)
  381.     term.setBackgroundColor(colors.lightGray)
  382.     term.clearLine()
  383.     write(">")
  384.     sleep(0)
  385.     enckey = read("*")
  386.     if enckey == "" then enckey = defaultKey end
  387.     drawThing("Filter ID? (optional)",3)
  388.     idfilter = nil
  389.     term.setCursorPos(1,6)
  390.     term.setTextColor(colors.black)
  391.     term.setBackgroundColor(colors.lightGray)
  392.     term.clearLine()
  393.     write(">")
  394.     sleep(0)
  395.     idfilter = tonumber(read())
  396.     local thang = "Receiving"
  397.     if idfilter then
  398.         thang = thang.." from ID "..tostring(idfilter).."..."
  399.     else
  400.         thang = thang.."..."
  401.     end
  402.     term.setBackgroundColor(colors.gray)
  403.     term.clear()
  404.     drawThing(thang,3)
  405.     local count,size,success = receive(true)
  406.     if success then
  407.         drawThing("Received!",3)
  408.         if count ~= 1 then
  409.             drawThing("(Got "..count.." files)",5)
  410.         else
  411.             drawThing("(Got "..count.." file)",5)
  412.         end
  413.         if size ~= 1 then
  414.             drawThing("(Totals "..size.." bytes)",7)
  415.         else
  416.             drawThing("(Totals "..size.." byte)",7)
  417.         end
  418.     else
  419.         drawThing("Cancelled.",3)
  420.     end
  421.     sleep(0)
  422.     return true
  423. end
  424.  
  425. local gui = function()
  426.     local scr_x, scr_y = term.getSize()
  427.     local prevColor = term.getBackgroundColor()
  428.     local evt = {}
  429.     term.setBackgroundColor(colors.gray)
  430.     term.clear()
  431.     while true do
  432.         term.setBackgroundColor(colors.gray)
  433.         if res then term.clear() end
  434.         drawThing("Whisk BETA",3)
  435.         drawThing("(1) Send",7,colors.white,colors.black)
  436.         drawThing("(2) Receive",11,colors.white,colors.black)
  437.         drawThing("(X,Q) Exit",15,colors.white,colors.black)
  438.         evt = {os.pullEvent()}
  439.         local res = false
  440.         sleep(0)
  441.         if evt[1] == "mouse_click" then
  442.             if evt[2] == 1 then
  443.                 if math.abs(evt[4] - 7) <= 1 then
  444.                     res = sendGUI()
  445.                 elseif math.abs(evt[4] - 11) <= 1 then
  446.                     res = receiveGUI()
  447.                 elseif math.abs(evt[4] - 15) <= 1 then
  448.                     res = true
  449.                 end
  450.             end
  451.         elseif evt[1] == "key" then
  452.             if evt[2] == keys.one then
  453.                 res = sendGUI()
  454.             elseif evt[2] == keys.two then
  455.                 res = receiveGUI()
  456.             elseif evt[2] == keys.three or evt[2] == keys.q or evt[2] == keys.x then
  457.                 res = true
  458.             end
  459.         end
  460.         if res then
  461.             term.setCursorPos(1,scr_y)
  462.             term.setBackgroundColor(prevColor)
  463.             term.clearLine()
  464.             break
  465.         end
  466.     end
  467. end
  468.  
  469. if modem then modem.open(channel) end
  470.  
  471. waitForModem = function()
  472.     while true do
  473.         sleep(0)
  474.         modem = peripheral.find("modem")
  475.         if modem then
  476.             return
  477.         end
  478.     end
  479. end
  480.  
  481. if not tArg[1] then
  482.     local prevBG, prevTXT = term.getBackgroundColor(), term.getTextColor()
  483.     if modem then
  484.         gui()
  485.     else
  486.         term.setBackgroundColor(colors.gray)
  487.         term.clear()
  488.         drawThing("You don't have a modem!",3)
  489.         drawThing("Attach one or press a key.",5)
  490.         sleep(0.1)
  491.         local outcome = parallel.waitForAny(function() os.pullEvent("key") end, waitForModem)
  492.         if modem then
  493.             modem.open(channel)
  494.             gui()
  495.         else
  496.             local scr_x,scr_y = term.getSize()
  497.             term.setCursorPos(1,scr_y)
  498.             term.setBackgroundColor(prevBG)
  499.             term.setTextColor(prevTXT)
  500.             term.clearLine()
  501.             sleep(0)
  502.             return false
  503.         end
  504.     end
  505. else
  506.     if not modem then
  507.         error("No modem detected.")
  508.     end
  509.     if mode == "send" then
  510.         send()
  511.     elseif mode == "receive" then
  512.         write("Receiving")
  513.         if idfilter then
  514.             print(" from "..idfilter.."...")
  515.         else
  516.             print("...")
  517.         end
  518.         local fc, size = receive(false)
  519.         write("Done. (got "..fc.." file")
  520.         if fc ~= 1 then write("s") end
  521.         write(", totalling "..size.." byte")
  522.         if size ~= 1 then print("s)") else print(")") end
  523.     else
  524.         displayHelp()
  525.     end
  526. end
  527.  
  528. sleep(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement