Last active
January 5, 2024 22:19
-
-
Save Jan200101/b3c3fbece8c63a4f6bc545bb120b6fa2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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