Advertisement
LDDestroier

PROGDOR BETA

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