Skip to content

Instantly share code, notes, and snippets.

@Jan200101
Last active January 5, 2024 22:19
Show Gist options
  • Save Jan200101/b3c3fbece8c63a4f6bc545bb120b6fa2 to your computer and use it in GitHub Desktop.
Save Jan200101/b3c3fbece8c63a4f6bc545bb120b6fa2 to your computer and use it in GitHub Desktop.
// pack.src
// NAME!BASE64
shell = get_shell
computer = shell.host_computer
// start ../lib-src/libbase64.src
// libbase64.src
// based on https://github.com/iskolbin/lbase64
// MIT License
// Copyright (c) 2018 Ilya Kolbin
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// start assert.src
// assert.src
assert = function(cond, msg)
if cond == false then
exit("assert: " + msg)
end if
end function
// end assert.src
base64 = {}
base64._table = [
"A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m",
"n","o","p","q","r","s","t","u","v","w","x","y","z",
"0","1","2","3","4","5","6","7","8","9","+","/","=",
]
base64._extract = function( v, from, width )
w = 0
flag = 2^from
i = 0
while i < width
flag2 = flag + flag
if v % flag2 >= flag then
w = w + 2^i
end if
flag = flag2
i = i + 1
end while
return w
end function
base64.encode = function(str)
t = []
k = 0
n = str.len
lastn = n % 3
i = 0
while i < n-lastn
a = str[i+0].code
b = str[i+1].code
c = str[i+2].code
v = a*65536 + b*256 + c
t.push(self._table[self._extract(v,18,6)] + self._table[self._extract(v,12,6)] + self._table[self._extract(v,6,6)] + self._table[self._extract(v,0,6)])
i = i + 3
end while
if lastn == 2 then
a = str[n-2].code
b = str[n-1].code
v = a*65536 + b*256
s = self._table[self._extract(v,18,6)] + self._table[self._extract(v,12,6)] + self._table[self._extract(v,6,6)] + self._table[64]
t.push(s)
else if lastn == 1 then
a = str[n-1].code
v = a*65536
s = self._table[self._extract(v,18,6)] + self._table[self._extract(v,12,6)] + self._table[64] + self._table[64]
t.push(s)
end if
return t.join("")
end function
base64.decode = function(data)
t = []
k = 0
n = data.len
if data[-2:data.len] == "==" then
padding = 2
else if data[-1:data.len] == "=" then
padding = 1
else
padding = 0
end if
l = n
if padding > 0 then l = n - 4
i = 0
while i < l
a = data[i+0]
b = data[i+1]
c = data[i+2]
d = data[i+3]
v = self._table.indexOf(a)*262144 + self._table.indexOf(b)*4096 + self._table.indexOf(c)*64 + self._table.indexOf(d)
s = char(self._extract(v,16,8)) + char(self._extract(v,8,8)) + char(self._extract(v,0,8))
t.push(s)
i = i + 4
end while
if padding == 1 then
a = data[n-4]
b = data[n-3]
c = data[n-2]
v = self._table.indexOf(a)*262144 + self._table.indexOf(b)*4096 + self._table.indexOf(c)*64
s = char(self._extract(v,16,8)) + char(self._extract(v,8,8))
t.push(s)
else if padding == 2 then
a = data[n-4]
b = data[n-3]
v = self._table.indexOf(a)*262144 + self._table.indexOf(b)*4096
s = char(self._extract(v,16,8))
t.push(s)
end if
return t.join("")
end function
assert(base64.encode("test") == "dGVzdA==", "base64 encoder broke")
assert(base64.decode("dGVzdA==") == "test", "base64 decoder broke")
assert(base64.decode(base64.encode("test")) == "test", "base64 round trip broke 1")
assert(base64.decode(base64.encode("reallylongstring")) == "reallylongstring", "base64 round trip broke 2")
// end ../lib-src/libbase64.src
// start ../lib-src/argparse.src
// argparse.src
ArgumentParser = {
"classID": "ArgumentParser",
"arguments": {},
}
// aname
// description:
// contains the argument name
// type: string
//
// long
// description:
// if the argument should be the full name or a single letter
// also defines if one or two dashes will be used
// type: number
// default: false
//
// action
// description:
// defines how the arguments will be handled.
// type: string
// values:
// store
// stores the next argument
// flag
// stores True if the flag was found, False otherwise
// default: "store"
//
ArgumentParser.add_argument = function(aname, long=false, action="store")
if typeof(aname) != "string" then exit("add_argument: invalid aname type")
if typeof(long) != "number" then exit("add_argument: invalid long type")
if typeof(action) != "string" then exit("add_argument: invalid action type")
if ["store", "flag"].indexOf(action) == null then exit("add_argument: invalid action value")
if long then
flag = "--"+aname
else
flag = "-"+aname[0]
end if
// check for duplicate flags
if self.arguments.hasIndex(flag) then
exit("add_argument: duplicate flag '" + aname + "'")
end if
self.arguments[flag] = {
"aname": aname,
"long": long,
"action": action,
}
end function
ArgumentParser.parse_args = function(args)
parsedargs = {}
for a in self.arguments.indexes
k = self.arguments[a]
n = k["aname"]
v = {
"store": "",
"flag": false,
}[k["action"]]
parsedargs[n] = v
end for
i = 0
while i < args.len
a = args[i]
if a == "--help" then exit(self.print_help)
// Ain't a flag, we are done here
if a[0] != "-" then break
if self.arguments.hasIndex(a) == false then
exit("<b>error</b>: unknown flag: '" + a + "'")
end if
k = self.arguments[a]
n = k["aname"]
if k["action"] == "store" then
i = i + 1
if args.len <= i then exit("no parameter for flag '" + a + "' found")
v = args[i]
else if k["action"] == "flag" then
v = true
else
exit("found invalid action: "+ k["action"])
end if
parsedargs[n] = v
i = i + 1
end while
parsedargs.rest = args[i:args.len]
return parsedargs
end function
ArgumentParser.print_help = function()
program_name = program_path.split("/")[-1]
usage_start = "Usage: " + program_name
short_flags = []
long_flags = []
stores = []
for k in self.arguments.indexes
a = self.arguments[k]
if a["action"] == "flag" then
if a["long"] == true then
long_flags.push(k)
else
short_flags.push(a["aname"][0])
end if
else if a["action"] == "store" then
stores.push([a["aname"], k])
else
exit("print_help: invalid action found")
end if
end for
flag_usage = ""
if short_flags.len != 0 then
flag_usage = flag_usage + " [-" + short_flags.join("") + "]"
end if
for f in long_flags
flag_usage = flag_usage + " [" + f + "]"
end for
store_usage = ""
for s in stores
store_usage = store_usage + " [" + s[1] + " " + s[0] + "]"
end for
usage = "<b>" + usage_start + flag_usage + store_usage + "</b>"
print(usage)
end function
// end ../lib-src/argparse.src
// start ../lib-src/basename.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
basename = function(path)
l = path.len
while path[l-1] == PATHSEP
l = l - 1
end while
for i in range(l-1, 0)
if path[i] == PATHSEP and path[i+1:l].len != 0 then
return path[i+1:l]
end if
end for
return path[0:l]
end function
// end ../lib-src/basename.src
// start ../lib-src/dirname.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
dirname = function(path)
l = path.len
if path[l-1] == PATHSEP then
return path
end if
for i in range(l-2, 0)
if path[i] == PATHSEP then
return path[0:i]
end if
end for
return path
end function
// end ../lib-src/dirname.src
// start ../lib-src/abspath.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
abspath = function(path, cwd = null)
if cwd == null then cwd = current_path
if path[0] != PATHSEP then path = cwd + PATHSEP + path
pathseg = path.split(PATHSEP)
i = 0
while i < pathseg.len
if pathseg[i] == "." then
pathseg.remove(i)
continue
else if pathseg[i] == ".." then
pathseg.remove(i)
pathseg.remove(i-1)
i = i - 1
continue
end if
i = i + 1
end while
return pathseg.join(PATHSEP)
end function
// end ../lib-src/abspath.src
// start ../lib-src/pathsep.src
PATHSEP = "/"
// end ../lib-src/pathsep.src
// start ../lib-src/mkdir.src
// mkdir.src
// start ../lib-src/pathsep.src
PATHSEP = "/"
// end ../lib-src/pathsep.src
// start ../lib-src/abspath.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
abspath = function(path, cwd = null)
if cwd == null then cwd = current_path
if path[0] != PATHSEP then path = cwd + PATHSEP + path
pathseg = path.split(PATHSEP)
i = 0
while i < pathseg.len
if pathseg[i] == "." then
pathseg.remove(i)
continue
else if pathseg[i] == ".." then
pathseg.remove(i)
pathseg.remove(i-1)
i = i - 1
continue
end if
i = i + 1
end while
return pathseg.join(PATHSEP)
end function
// end ../lib-src/abspath.src
// start ../lib-src/basename.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
basename = function(path)
l = path.len
while path[l-1] == PATHSEP
l = l - 1
end while
for i in range(l-1, 0)
if path[i] == PATHSEP and path[i+1:l].len != 0 then
return path[i+1:l]
end if
end for
return path[0:l]
end function
// end ../lib-src/basename.src
// start ../lib-src/dirname.src
// start pathsep.src
PATHSEP = "/"
// end pathsep.src
dirname = function(path)
l = path.len
if path[l-1] == PATHSEP then
return path
end if
for i in range(l-2, 0)
if path[i] == PATHSEP then
return path[0:i]
end if
end for
return path
end function
// end ../lib-src/dirname.src
mkdir = function(computer, path)
if computer == null or path == null then exit("mkdir: invalid arguments")
path = abspath(path)
segs = path.split(PATHSEP)
for i in segs.indexes
if i == 0 then continue
p = segs[0:i+1].join(PATHSEP)
f = computer.File(p)
if f == null then
computer.create_folder(dirname(p), basename(p))
else if f.is_folder then
continue
else
exit("mkdir: failed to create folder, '" + p + "' is a file")
end if
end for
end function
// end ../lib-src/mkdir.src
parser = new ArgumentParser
parser.add_argument("pack", false, "flag")
parser.add_argument("unpack", false, "flag")
parser.add_argument("force", false, "flag")
args = parser.parse_args(params)
if args["pack"] == args["unpack"] then
parser.print_help
exit("[!] Either -p(ack) or -u(npack) needs to be specified")
end if
filepath = args["rest"].join(" ")
fd = computer.File(abspath(filepath))
if fd == null then
exit("pack: " + filepath + " is not a file or directory")
end if
pack = function(file)
if file.is_folder then
d = ""
for f in file.get_folders
d = d + pack(f)
end for
for f in file.get_files
d = d + pack(f)
end for
return d
else if file.is_binary then
print("[!] Skipping binary file " + basename(file.path))
return ""
end if
c = current_path
p = file.path
if p[0:c.len] == c then
p = p[c.len+1:p.len]
end if
print("[*] Processing " + p)
d = base64.encode(file.get_content)
return p + "!" + d + char(10)
end function
unpack = function(file)
if file.is_folder or file.is_binary then
exit("Cannot unpack folders or binary files")
end if
content = file.get_content
lines = content.split(char(10))
for i in lines.indexes
line = lines[i]
if line.len == 0 then continue
segments = line.split("!")
if segments.len != 2 then exit("[!] found corrupt segment " + i)
path = segments[0]
data = base64.decode(segments[1])
f = computer.File(path)
if f != null then
if f.is_folder or f.is_binary then
exit("[!] " + path + " already exists and is not a file")
end if
r = null
a = {
"y": true,
"yes": true,
"n": false,
"no": false,
}
while a.indexOf(r) == null
a = user_input("[?] " + path + " already exists. replace? [y/n]")
end while
if a[r] == true then
print("[*] Skipping " + path)
continue
end if
else
d = abspath(dirname(path))
b = basename(path)
mkdir(computer, d)
res = computer.touch(d, b)
if typeof(res) == "string" then
error("[!] failed to create file '" + path + "': " + res)
end if
f = computer.File(path)
end if
print("[*] Unpacking " + path)
f.set_content(data)
end for
end function
if args["pack"] then
outname = basename(filepath) + ".pack"
outpath = current_path + PATHSEP + basename(outname)
if computer.File(outpath) != null then
exit("pack: output file already exists (" + outpath + ")")
end if
print("[*] Packing...")
d = pack(fd)
res = computer.touch(dirname(outpath), basename(outpath))
if typeof(res) == "string" then
exit("pack: touch error: " + res)
end if
outfile = computer.File(outpath)
outfile.set_content(d)
print("[*] Created pack file " + outpath)
else if args["unpack"] then
unpack(fd)
end if
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment