{%
/*
* Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks
* Copyright (C) 2024 Tim Wilkinson
* See Contributors file for additional contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
");
}
function getPackageOptions()
{
let i = ``;
let r = ``;
const perm_pkgs = {};
const installed_pkgs = {};
map(split(fs.readfile("/etc/permpkg"), "\n"), p => perm_pkgs[p] = true);
let f = fs.popen("/bin/opkg list-installed");
if (f) {
const re = /^([^ \t]+)[ \t]-[ \t](.+)/;
for (let l = f.read("line"); length(l); l = f.read("line")) {
const m = match(l, re);
if (m) {
installed_pkgs[m[1]] = true;
if (!perm_pkgs[m[1]]) {
r += ``;
}
}
}
f.close();
}
f = fs.popen("/bin/opkg list");
if (f) {
const re = /^([^ ]+) - ([-0-9a-fr\.]+)(.*)$/;
for (let l = f.read("line"); length(l); l = f.read("line")) {
let m = match(trim(l), re);
if (m && !installed_pkgs[m[1]]) {
i += ``;
}
}
f.close();
}
return { i: i, r: r };
}
function recordPackage(op, pkgname, pkgfile)
{
const store = "/etc/package_store";
const catfile = `${store}/catalog.json`;
fs.mkdir(store);
const catalog = json(fs.readfile(catfile) || '{ "installed": {} }');
switch (op) {
case "upload":
const package = split(pkgname, "_")[0];
if (package) {
fs.writefile(`${store}/${package}.ipk`, fs.readfile(pkgfile));
catalog.installed[package] = "local";
}
break;
case "download":
const f = fs.popen(`/bin/opkg status ${pkgname} 2>&1`);
if (f) {
const status = replace(f.read("all"), "\n", " ");
f.close();
const m = match(status, /Package: ([^ \t]+)/);
if (m) {
catalog.installed[m[1]] = "global";
}
}
break;
case "remove":
fs.unlink(`${store}/${pkgname}.ipk`);
delete catalog.installed[pkgname];
break;
default:
break;
}
fs.unlink(catfile);
for (let k in catalog.installed) {
fs.writefile(catfile, sprintf("%J", catalog));
break;
}
}
if (request.env.REQUEST_METHOD === "POST" && request.args["packagefile.ipk"] && request.args.packagename) {
const ipk = request.args["packagefile.ipk"];
const packagename = fs.readfile(request.args.packagename);
if (system(`/bin/opkg -force-overwrite install ${ipk} > /dev/null 2>&1`) === 0) {
recordPackage("upload", packagename, ipk);
print(`