LDDestroier

PROGDOR - CC file bundler

Jul 29th, 2016
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.63 KB | None | 0 0
  1. --[[
  2.  PROGDOR file bundling program
  3.  
  4. Download with:
  5.  pastebin get YXx5jjMV progdor
  6.  std ld progdor progdor
  7.  
  8. This is a stable release. You fool!
  9. --]]
  10.  
  11. local doCompress = false --even if this is false, it will decompress compressed files. nifty, huh?
  12.  
  13. local doPastebin = false
  14. local tArg = {...}
  15. local input, outpath
  16. if tArg[1] == "-p" then --the p is for pastebin
  17.     doPastebin = true
  18.     input = tArg[2]
  19.     outpath = tArg[3]
  20. else
  21.     input = tArg[1]
  22.     outpath = tArg[2]
  23. end
  24.  
  25. local progdor = fs.getName(shell.getRunningProgram())
  26. local dir = shell.dir()
  27. local displayHelp = function()
  28.     local txt = progdor.." <input> [output]\nCompression is "..tostring(doCompress):upper().."."
  29.     return print(txt)
  30. end
  31.  
  32. local yield = function()
  33.     os.queueEvent("yield")
  34.     os.pullEvent("yield")
  35. end
  36.  
  37. -- CCA API START --
  38.  
  39. local bit = bit32
  40. local function pack(bn1, bn2)
  41.     return bit.band(bn1, 0xFF), bit.rshift(bn1, 8) + bit.lshift(bit.band(bn2, 0xF), 4), bit.rshift(bn2, 4)
  42. end
  43. local function upack(b1, b2, b3)
  44.     return (b1 + bit.lshift(bit.band(b2, 0xF), 8)), (bit.lshift(b3,4) + bit.band(bit.rshift(b2, 4), 0xF))
  45. end
  46. local function createDict(bool)
  47.     local ret = {}
  48.     for i = 1, 255 do
  49.         if bool then
  50.             ret[string.char(i)] = i
  51.         else
  52.             ret[i] = string.char(i)
  53.         end
  54.     end
  55.     if not bool then ret[256] = 256 end
  56.     return ret
  57. end
  58. local function cp(sInput)
  59.     local dic = createDict(true)
  60.     local s = ""
  61.     local ch
  62.     local dlen = 256
  63.     local result = {}
  64.     local temp
  65.     for i = 1, #sInput do
  66.         if dlen == 4095 then
  67.             result[#result + 1] = dic[s]
  68.             result[#result + 1] = 256
  69.             dic = createDict(true)
  70.             dlen = 256
  71.             s = ""
  72.         end
  73.         ch = sInput:sub(i, i)
  74.         temp = s..ch
  75.         if dic[temp] then
  76.             s = temp
  77.         else
  78.             result[#result + 1] = dic[s]
  79.             dlen = dlen +1
  80.             dic[temp] = dlen       
  81.             s = ch
  82.         end
  83.     end
  84.     result[#result + 1] = dic[s]
  85.    
  86.     return result
  87. end
  88. local function dc(data)
  89.     local dic = createDict(false)  
  90.     local entry
  91.     local ch
  92.     local currCode
  93.     local result = {}
  94.     result[#result + 1] = dic[data[1]]
  95.     prefix = dic[data[1]]
  96.     for i = 2, #data do
  97.         currCode = data[i]
  98.         if currCode == 256 then
  99.             dic = createDict(false)
  100.             prefix = ""
  101.         else
  102.             entry = dic[currCode]
  103.             if entry then--exists in dictionary
  104.                 ch = entry:sub(1, 1)       
  105.                 result[#result + 1] = entry
  106.                 if prefix ~= "" then
  107.                     dic[#dic+1] = prefix .. ch
  108.                 end
  109.             else   
  110.                 ch = prefix:sub(1, 1)
  111.                 result[#result + 1] = prefix..ch
  112.                 dic[#dic + 1] = prefix..ch
  113.             end
  114.        
  115.             prefix = dic[currCode]
  116.         end
  117.     end
  118.    
  119.     return table.concat(result)
  120. end
  121. local function trim(inp)
  122.     for i = 0,2 do
  123.         if inp[#inp] == 0 then
  124.             inp[#inp] = nil
  125.         end
  126.     end
  127. end
  128. local function decompress(input)
  129.     local rec = {}
  130.     for i = 1, #input, 3 do
  131.         if i % 66 == 0 then
  132.             yield()
  133.         end
  134.         rec[#rec+1], rec[#rec+2] = upack(input[i], input[i+1] or 0, input[i+2] or 0)
  135.     end
  136.     trim(rec)
  137.     return dc(rec)
  138. end
  139. local function compress(input)
  140.     local rec = {}
  141.     local data = cp(input)
  142.     for i=1, #data, 2 do
  143.         yield()
  144.         rec[#rec+1], rec[#rec+2], rec[#rec+3] = pack(data[i], data[i+1] or 0)
  145.     end
  146.     trim(rec)
  147.     return rec
  148. end
  149.  
  150. -- CCA API END --
  151.  
  152. local fixstr = function(str)
  153.     return str:gsub("\\(%d%d%d)",string.char)
  154. end
  155.  
  156. local explode = function(div,str)
  157.     if (div=='') then return false end
  158.     local pos,arr = 0,{}
  159.     for st,sp in function() return string.find(str,div,pos,true) end do
  160.         table.insert(arr,str:sub(pos,st-1))
  161.         pos = sp + 1
  162.     end
  163.     table.insert(arr,str:sub(pos))
  164.     return arr
  165. end
  166. local sanitize = function(sani,tize)
  167.     local _,x = string.find(sani,tize)
  168.     if x then
  169.         return sani:sub(x+1)
  170.     else
  171.         return sani
  172.     end
  173. end
  174. local tablize = function(input)
  175.     if type(input) == "string" then
  176.         return explode("\n",input)
  177.     elseif type(input) == "table" then
  178.         return table.concat(input,"\n")
  179.     end
  180. end
  181. local compyress = function(input)
  182.     return string.char(unpack(compress(input)))
  183. end
  184. local decompyress = function(input)
  185.     local out = {}
  186.     for a = 1, #input do
  187.         table.insert(out,string.byte(input:sub(a,a)))
  188.     end
  189.     return decompress(out)
  190. end
  191. local listAll
  192. listAll = function(_path, _files, noredundant)
  193.     local path = _path or ""
  194.     local files = _files or {}
  195.     if #path > 1 then table.insert(files, path) end
  196.     for _, file in ipairs(fs.list(path)) do
  197.         local path = fs.combine(path, file)
  198.         if (file ~= thisProgram) then
  199.             local guud = true
  200.             if guud then
  201.                 if fs.isDir(path) then
  202.                     listAll(path, files, noredundant)
  203.                 else
  204.                     table.insert(files, path)
  205.                 end
  206.             end
  207.         end
  208.     end
  209.     if noredundant then
  210.         for a = 1, #files do
  211.             if fs.isDir(tostring(files[a])) then
  212.                 if #fs.list(tostring(files[a])) ~= 0 then
  213.                     table.remove(files,a)
  214.                 end
  215.             end
  216.         end
  217.     end
  218.     return files
  219. end
  220. if not (input) then
  221.     return displayHelp()
  222. end
  223. if not outpath then
  224.     outpath = input
  225. end
  226.  
  227. local choice = function(input,verbose)
  228.     if not input then
  229.         input = "yn"
  230.     end
  231.     if verbose then
  232.         write("[")
  233.         for a = 1, #input do
  234.             write(input:sub(a,a):upper())
  235.             if a < #input then
  236.                 write(",")
  237.             end
  238.         end
  239.         write("]?")
  240.     end
  241.     local evt,char
  242.     repeat
  243.         evt,char = os.pullEvent("char")
  244.     until string.find(input:lower(),char:lower())
  245.     if verbose then
  246.         print(char:upper())
  247.     end
  248.     local pos = string.find(input:lower(),char:lower())
  249.     return pos, char:lower()
  250. end
  251.  
  252. local postToPastebin = function(name, contents)
  253.     local key = "0ec2eb25b6166c0c27a394ae118ad829"
  254.     local response = http.post(
  255.         "http://pastebin.com/api/api_post.php",
  256.         "api_option=paste&"..
  257.         "api_dev_key="..key.."&"..
  258.         "api_paste_format=lua&"..
  259.         "api_paste_name="..textutils.urlEncode(name).."&"..
  260.         "api_paste_code="..textutils.urlEncode(contents)
  261.     )
  262.     if response then
  263.         local sResponse = response.readAll()
  264.         response.close()
  265.         local sCode = string.match( sResponse, "[^/]+$" )
  266.         return sCode
  267.     else
  268.         return false
  269.     end
  270.     return
  271. end
  272.  
  273. function doPack(input,output,doCompress,verbose) --make sure that shell exists before using verbose mode
  274.     local tx = term.getTextColor()
  275.     if not doPastebin then
  276.         if not fs.exists(input) then return 3 end
  277.         if fs.isReadOnly(output) then return 5 end
  278.     end
  279.     local packageSelf = true
  280.     local packageReadOnly = true
  281.     local ro_asked = false
  282.     local ps_asked = false
  283.     if fs.isDir(input) then --if not a package
  284.         local out = {}
  285.         local list = listAll(input,nil,true)
  286.         if verbose then
  287.             for a = 1, #list do --this checks for self and read-only files
  288.                 if fs.isReadOnly(list[a]) and (not ro_asked) then
  289.                     write("Include read-only files? ")
  290.                     if choice("yn",true) == 2 then
  291.                         packageReadOnly = false
  292.                     end
  293.                     ro_asked = true
  294.                 end
  295.                 if fs.combine("",list[a]) == shell.getRunningProgram() and (not ps_asked) then
  296.                     write("Include self? ")
  297.                     if choice("yn",true) == 2 then
  298.                         packageSelf = false
  299.                     end
  300.                     ps_asked = true
  301.                 end
  302.             end
  303.         end
  304.         for a = 1, #list do --this loop kills fascists
  305.             local is_self = fs.combine("",list[a]) == fs.combine("",shell.getRunningProgram())
  306.             if not ((is_self and not packageSelf) or (fs.isReadOnly(list[a]) and not packageReadOnly)) then
  307.                 if verbose then
  308.                     write("[")
  309.                     if term.isColor() then term.setTextColor(colors.lightGray) end
  310.                     write(sanitize(list[a],fs.combine(dir,input)))
  311.                     term.setTextColor(tx)
  312.                     write("]")
  313.                 end
  314.                 if fs.isDir(list[a]) then
  315.                     out[sanitize(list[a],fs.combine(dir,input))] = true
  316.                 else
  317.                     local file = fs.open(list[a],"r")
  318.                     local cont = file.readAll()
  319.                     file.close()
  320.                     if doCompress then
  321.                         out[sanitize(list[a],fs.combine(dir,input))] = tablize(compyress(cont))
  322.                     else
  323.                         out[sanitize(list[a],fs.combine(dir,input))] = tablize(cont)
  324.                     end
  325.                 end
  326.                 local tx = term.getTextColor()
  327.                 if fs.getName(list[a]):lower() == "peasant" then
  328.                     if term.isColor() then
  329.                         term.setTextColor(colors.orange)
  330.                     end
  331.                     print(" BURNINATED")
  332.                 else
  333.                     if term.isColor() then
  334.                         term.setTextColor(colors.green)
  335.                     end
  336.                     print(" GOOD")
  337.                 end
  338.                 term.setTextColor(tx)
  339.             else
  340.                 if fs.getName(list[a]):lower() == "peasant" then
  341.                     print("Spared "..list[a])
  342.                 else
  343.                     print("Skipped "..list[a])
  344.                 end
  345.             end
  346.         end
  347.         local fullOutput = tostring(doCompress).."\n"..fixstr(textutils.serialize(out))
  348.         local sCode
  349.         if doPastebin then
  350.             print("Uploading...")
  351.             sCode = postToPastebin(input,fullOutput)
  352.             return 7, "Code = '"..sCode.."'"
  353.         else
  354.             if fs.isDir(output) then fs.delete(output) end
  355.             local file = fs.open(output,"w")
  356.             file.write(fullOutput)
  357.             file.close()
  358.             return 1
  359.         end
  360.     else --if a package
  361.         local list, isCompy
  362.         if not doPastebin then
  363.             local file = fs.open(input,"r")
  364.             isCompy = file.readLine()
  365.             list = file.readAll()
  366.             file.close()
  367.         else
  368.             local file = http.get("http://pastebin.com/raw/"..tostring(input))
  369.             if file then
  370.                 isCompy = file.readLine()
  371.                 list = file.readAll()
  372.             else
  373.                 return 6
  374.             end
  375.         end
  376.         local list = textutils.unserialize(list)
  377.         if type(list) ~= "table" then
  378.             return 4
  379.         end
  380.         if fs.exists(output) then
  381.             fs.delete(output)
  382.         end
  383.         local amnt = 0
  384.         for k,v in pairs(list) do
  385.             amnt = amnt + 1
  386.         end
  387.         local num = 0
  388.         for k,v in pairs(list) do
  389.             num = num + 1
  390.             if v == true then
  391.                 fs.makeDir(fs.combine(output,fs.combine(k,dir)))
  392.             else
  393.                 local file = fs.open(fs.combine(output,fs.combine(k,dir)),"w")
  394.                 if verbose then
  395.                     write("[")
  396.                     if term.isColor() then term.setTextColor(colors.lightGray) end
  397.                     write(k)
  398.                     term.setTextColor(tx)
  399.                     write("]")
  400.                 end
  401.                 if isCompy:gsub(" ","") == "true" then
  402.                     file.write(decompyress(tablize(v)))
  403.                 else
  404.                     file.write(tablize(v))
  405.                 end
  406.                 file.close()
  407.                 local tx = term.getTextColor()
  408.                 if fs.getName(k):lower() == "peasant" then
  409.                     if term.isColor() then
  410.                         term.setTextColor(colors.orange)
  411.                     end
  412.                     print(" UNBURNINATED")
  413.                 else
  414.                     if term.isColor() then
  415.                         term.setTextColor(colors.green)
  416.                     end
  417.                     print(" GOOD")
  418.                 end
  419.                 term.setTextColor(tx)
  420.             end
  421.         end
  422.         return 2
  423.     end
  424. end
  425.  
  426. local success, res, otherRes = pcall( function() return doPack(input,outpath,doCompress,true) end ) --functionized it!
  427.  
  428. if not success then
  429.     term.setTextColor(colors.white)
  430.     print("\n***Something went wrong!***")
  431.     return printError(res)
  432. end
  433.  
  434. if res then
  435.     local msgs = {
  436.         [1] = "Successfully packed '"..input.."/' as '"..outpath.."'",
  437.         [2] = "Successfully unpacked '"..input.."' to '"..outpath.."/'",
  438.         [3] = "That file/folder does not exist.",
  439.         [4] = "That file isn't a packed folder.",
  440.         [5] = "You don't have permission.",
  441.         [6] = "Failed to connect.",
  442.         [7] = "Uploaded successfully.",
  443.     }
  444.     print(msgs[res])
  445.     if otherRes then
  446.         print(otherRes)
  447.     end
  448. end
Add Comment
Please, Sign In to add comment