update-10.05

This commit is contained in:
github-actions[bot] 2021-10-05 23:44:29 +08:00
parent 06c809aa1a
commit 9ae163902b
13 changed files with 599 additions and 0 deletions

52
app-store-ui/Makefile Normal file
View File

@ -0,0 +1,52 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=app-store-ui
PKG_VERSION:=1.0
PKG_RELEASE:=3
PKG_HOST_ONLY=1
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME}
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/package.mk
define Package/app-store-ui
SECTION:=libs
CATEGORY:=Libraries
TITLE:=App Store UI
BUILDONLY:=1
endef
define Package/app-store-ui/description
UI for luci-app-store
endef
define Host/Prepare
mkdir -p $(HOST_BUILD_DIR)
$(CP) ./src/. $(HOST_BUILD_DIR)
find $(HOST_BUILD_DIR) -name .svn | $(XARGS) rm -rf
endef
define Host/Configure
endef
define Host/Compile
endef
define Host/Install
endef
define Host/Clean
rm -f $(HOST_BUILD_DIR)/src/dist
endef
$(eval $(call HostBuild))
$(eval $(call BuildPackage,app-store-ui))

16
app-store-ui/src/dist/index.html vendored Normal file
View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" crossorigin src="/luci-static/istore/index.js"></script>
<link rel="modulepreload" href="/luci-static/istore/vendor.js">
<link rel="stylesheet" href="/luci-static/istore/style.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

121
luci-app-store/API.md Normal file
View File

@ -0,0 +1,121 @@
### 路由器端API
0. 获取csrfToken用于POST请求
```
GET /cgi-bin/luci/admin/store/token
{"token":"xxx"}
```
1. 已安装软件列表
```
GET /cgi-bin/luci/admin/store/installed
[
{
"description": "DDNS.TO内网穿透",
"tags": [
"net",
"tool"
],
"entry": "/cgi-bin/luci/admin/services/ddnsto",
"author": "xiaobao",
"depends": [
"ddnsto",
"luci-app-ddnsto",
"luci-i18n-ddnsto-zh-cn"
],
"title": "DDNS.TO",
"time": 1629356347,
"release": 1,
"website": "https://www.ddnsto.com/",
"name": "ddnsto",
"version": "1.0.0"
}
]
```
2. 安装软件
```
POST /cgi-bin/luci/admin/store/install
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
3. 更新软件
```
POST /cgi-bin/luci/admin/store/upgrade
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
4. 卸载软件
```
POST /cgi-bin/luci/admin/store/remove
token=xxx&package=upnp
{"code":0, "stdout":"", "stderr":""}
```
5. 刷新可用软件列表
```
POST /cgi-bin/luci/admin/store/update
token=xxx
{"code":0, "stdout":"", "stderr":""}
```
6. 查询特定软件状态
```
GET /cgi-bin/luci/admin/store/status?package=ddnsto
{
"description": "DDNS.TO内网穿透",
"tags": [
"net",
"tool"
],
"entry": "/cgi-bin/luci/admin/services/ddnsto",
"author": "xiaobao",
"depends": [
"ddnsto",
"luci-app-ddnsto",
"luci-i18n-ddnsto-zh-cn"
],
"installed": true,
"title": "DDNS.TO",
"time": "1629356347",
"release": 1,
"website": "https://www.ddnsto.com/",
"name": "ddnsto",
"version": "1.0.0"
}
{"installed":false}
```
7. 任务状态(日志)
```
GET /cgi-bin/luci/admin/store/log
{
"stdout": "Installing app-meta-ddnsto (1.0.0) to root...\nDownloading http://192.168.9.168:9999/packages/aarch64_cortex-a53/meta/app-meta-ddnsto_1.0.0_all.ipk\nConfiguring app-meta-ddnsto.\n",
"stderr": "",
"code": 206
}
{"stdout":"","stderr":"","code":0}
```
8. 上传安装
```
POST /cgi-bin/luci/admin/store/upload
(文件上传表单,支持文件扩展名".ipk,.run")
{"code":0, "stdout":"", "stderr":""}
```

27
luci-app-store/Makefile Normal file
View File

@ -0,0 +1,27 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI based ipk store
LUCI_DESCRIPTION:=luci-app-store is a ipk store developed by LinkEase team
LUCI_DEPENDS:=+curl
LUCI_PKGARCH:=all
PKG_VERSION:=0.1.0
PKG_RELEASE:=6
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
LUCI_BUILD_DEPENDS:=app-store-ui/host
TARGET_CONFIGURE_OPTS = FRONTEND_DIST="$(BUILD_DIR_HOST)/app-store-ui/dist" APP_STORE_VERSION="$(PKG_VERSION)"
define Package/luci-app-store/conffiles
/etc/.app_store.id
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

3
luci-app-store/README.md Normal file
View File

@ -0,0 +1,3 @@
# luci-app-store
OpenWRT应用商店

View File

@ -0,0 +1,218 @@
module("luci.controller.store", package.seeall)
local myopkg = "is-opkg"
local page_index = {"admin", "store", "pages"}
function index()
local function store_api(action, onlypost)
local e = entry({"admin", "store", action}, onlypost and post("store_action", {action = action}) or call("store_action", {action = action}))
e.dependent = false -- 父节点不是必须的
e.leaf = true -- 没有子节点
end
local action
entry({"admin", "store"}, call("redirect_index"), _("iStore"), 31)
entry({"admin", "store", "pages"}, call("store_index")).leaf = true
entry({"admin", "store", "token"}, call("store_token"))
entry({"admin", "store", "log"}, call("store_log"))
entry({"admin", "store", "uid"}, call("action_user_id"))
entry({"admin", "store", "upload"}, post("store_upload"))
for _, action in ipairs({"update", "install", "upgrade", "remove"}) do
store_api(action, true)
end
for _, action in ipairs({"status", "installed"}) do
store_api(action, false)
end
end
local function user_id()
local jsonc = require "luci.jsonc"
local json_parse = jsonc.parse
local fs = require "nixio.fs"
local data = fs.readfile("/etc/.app_store.id")
local id
if data ~= nil then
id = json_parse(data)
else
id = {arch="",uid=""}
end
id.version = (fs.readfile("/etc/.app_store.version") or "?"):gsub("[\r\n]", "")
return id
end
function redirect_index()
luci.http.redirect(luci.dispatcher.build_url(unpack(page_index)))
end
function store_index()
luci.template.render("store/main", {prefix=luci.dispatcher.build_url(unpack(page_index)),id=user_id()})
end
function store_log()
local fs = require "nixio.fs"
local code = 0
local e = fs.readfile("/tmp/log/istore.stderr")
local o = fs.readfile("/tmp/log/istore.stdout")
if o ~= nil then
code = 206
end
luci.http.prepare_content("application/json")
luci.http.write_json({code=code,stdout=o or "",stderr=e or ""})
end
function action_user_id()
luci.http.prepare_content("application/json")
luci.http.write_json(user_id())
end
-- Internal action function
local function _action(exe, cmd, ...)
local os = require "os"
local fs = require "nixio.fs"
local pkg = ""
for k, v in pairs({...}) do
pkg = pkg .. " '" .. v:gsub("'", "") .. "'"
end
local c = "%s %s %s >/tmp/log/istore.stdout 2>/tmp/log/istore.stderr" %{ exe, cmd, pkg }
local r = os.execute(c)
local e = fs.readfile("/tmp/log/istore.stderr")
local o = fs.readfile("/tmp/log/istore.stdout")
fs.unlink("/tmp/log/istore.stderr")
fs.unlink("/tmp/log/istore.stdout")
return r, o or "", e or ""
end
function store_action(param)
local metadir = "/usr/lib/opkg/meta"
local metapkgpre = "app-meta-"
local code, out, err, ret, out0, err0
local fs = require "nixio.fs"
local ipkg = require "luci.model.ipkg"
local jsonc = require "luci.jsonc"
local json_parse = jsonc.parse
local action = param.action or ""
if action == "status" then
local pkg = luci.http.formvalue("package")
local metapkg = metapkgpre .. pkg
local meta = {}
local metadata = fs.readfile(metadir .. "/" .. pkg .. ".json")
if metadata ~= nil then
meta = json_parse(metadata)
end
meta.installed = false
local status = ipkg.status(metapkg)
if next(status) ~= nil then
meta.installed=true
meta.time=tonumber(status[metapkg]["Installed-Time"])
end
ret = meta
elseif action == "installed" then
local itr = fs.dir(metadir)
local data = {}
if itr then
local pkg
for pkg in itr do
if pkg:match("^.*%.json$") then
local meta = json_parse(fs.readfile(metadir .. "/" .. pkg))
local metapkg = metapkgpre .. meta.name
local status = ipkg.status(metapkg)
meta.time = tonumber(status[metapkg]["Installed-Time"])
data[#data+1] = meta
end
end
end
ret = data
else
local pkg = luci.http.formvalue("package")
local metapkg = metapkgpre .. pkg
if action == "update" or pkg then
if action == "update" or action == "install" then
code, out, err = _action(myopkg, action, metapkg)
else
local meta = json_parse(fs.readfile(metadir .. "/" .. pkg .. ".json"))
if action == "upgrade" then
code, out, err = _action(myopkg, action, unpack(meta.depends), metapkg)
else -- remove
code, out, err = _action(myopkg, action, unpack(meta.depends), metapkg)
if code ~= 0 then
code, out0, err0 = _action(myopkg, action, unpack(meta.depends), metapkg)
out = out .. out0
err = err .. err0
end
fs.unlink("/tmp/luci-indexcache")
end
end
else
code = 400
err = "package is null"
end
ret = {
code = code,
stdout = out,
stderr = err
}
end
luci.http.prepare_content("application/json")
luci.http.write_json(ret)
end
function store_token()
luci.http.prepare_content("application/json")
require "luci.template".render_string("{\"token\":\"<%=token%>\"}")
end
function store_upload()
local fd
local path
local finished = false
local tmpdir = "/tmp/is-root/tmp"
luci.http.setfilehandler(
function(meta, chunk, eof)
if not fd then
path = tmpdir .. "/" .. meta.file
nixio.fs.mkdirr(tmpdir)
fd = io.open(path, "w")
end
if chunk then
fd:write(chunk)
end
if eof then
fd:close()
finished = true
end
end
)
local code, out, err
out = ""
if finished then
if string.lower(string.sub(path, -4, -1)) == ".run" then
code, out, err = _action("sh", "-c", "chmod 755 \"%s\" && \"%s\"" %{ path, path })
else
code, out, err = _action(myopkg, "install", path)
end
else
code = 500
err = "upload failed!"
end
nixio.fs.unlink(path)
local ret = {
code = code,
stdout = out,
stderr = err
}
luci.http.prepare_content("application/json")
luci.http.write_json(ret)
end

View File

@ -0,0 +1,24 @@
<%+header%>
<link rel="stylesheet" href="/luci-static/istore/style.css">
<script>
(function(){
var vue_prefix="<%=prefix%>";
var myurl = window.location.pathname;
window.addEventListener('popstate', () => {
if (myurl != window.location.pathname
&& window.location.pathname != vue_prefix
&& ! window.location.pathname.startsWith(vue_prefix+'/')) {
window.location.href = window.location.pathname;
}
});
window.vue_base = vue_prefix + '/';
window.token = "<%=token%>";
window.device_id = {arch:"<%=id.arch%>",uid:"<%=id.uid%>",version:"<%=id.version%>"};
})();
</script>
<h2 name="content">应用商店 v<%=id.version%></h2>
<div id="app">
</div>
<script type="module" crossorigin src="/luci-static/istore/index.js"></script>
<link rel="modulepreload" href="/luci-static/istore/vendor.js">
<%+footer%>

87
luci-app-store/root/bin/is-opkg Executable file
View File

@ -0,0 +1,87 @@
#!/bin/sh
IS_ROOT=/tmp/is-root
DL_DIR=${IS_ROOT}/tmp/dl
LISTS_DIR_O=/tmp/opkg-lists
LISTS_DIR=${IS_ROOT}${LISTS_DIR_O}
OPKG_CONF_DIR=${IS_ROOT}/etc/opkg
FEEDS_SERVER=https://istore.linkease.com/repo
ARCH=`opkg -f /dev/null print-architecture | grep -v 'arch all' | grep -v 'arch noarch' | cut -d ' ' -f2`
action=${1}
shift
is_init() {
mkdir -p ${DL_DIR} ${LISTS_DIR} ${IS_ROOT}/etc ${IS_ROOT}/var
cat /etc/opkg.conf | grep -v lists_dir | grep -v check_signature > ${IS_ROOT}/etc/opkg.conf
cp ${IS_ROOT}/etc/opkg.conf ${IS_ROOT}/etc/opkg_o.conf
echo >> ${IS_ROOT}/etc/opkg.conf
echo "lists_dir ext ${LISTS_DIR}" >> ${IS_ROOT}/etc/opkg.conf
echo >> ${IS_ROOT}/etc/opkg_o.conf
echo "lists_dir ext ${LISTS_DIR_O}" >> ${IS_ROOT}/etc/opkg_o.conf
[ -e ${IS_ROOT}/var/lock ] || {
cp -a /etc/opkg ${IS_ROOT}/etc/
ln -s /var/lock ${IS_ROOT}/var/lock
}
}
opkg_wrap() {
OPKG_CONF_DIR=${OPKG_CONF_DIR} opkg -f ${IS_ROOT}/etc/opkg.conf "$@"
}
update() {
curl -o ${OPKG_CONF_DIR}/meta.conf "${FEEDS_SERVER}/all/meta.conf" && \
curl -o ${OPKG_CONF_DIR}/all.conf "${FEEDS_SERVER}/all/isfeeds.conf" && \
curl -o ${OPKG_CONF_DIR}/arch.conf "${FEEDS_SERVER}/${ARCH}/isfeeds.conf" && \
opkg -f ${IS_ROOT}/etc/opkg_o.conf --offline-root ${IS_ROOT} update
return 0
}
check_mtime() {
find ${OPKG_CONF_DIR}/arch.conf -mtime -1 2>/dev/null | grep -q . || update
}
wrapped_in_update() {
check_mtime || return 1
opkg_wrap "$@" && return 0
local idle_t=$((`date '+%s'` - `date -r ${IS_ROOT}/.last_force_ts '+%s' 2>/dev/null || echo '0'`))
[ $idle_t -gt 120 ] || return 1
update || return 1
touch ${IS_ROOT}/.last_force_ts
opkg_wrap "$@"
}
usage() {
echo "usage: is-opkg sub-command [arguments...]"
echo "where sub-command is one of:"
echo " update Update list of available packages"
echo " upgrade <pkgs> Upgrade packages"
echo " install <pkgs> Install package(s)"
echo " remove <pkgs> Remove package(s)"
}
is_init >/dev/null 2>&1
case $action in
"update")
update
;;
"install")
wrapped_in_update install "$@"
;;
"upgrade")
wrapped_in_update upgrade "$@"
;;
"remove")
opkg_wrap --autoremove --force-removal-of-dependent-packages remove "$@"
;;
*)
usage
;;
esac

View File

@ -0,0 +1,22 @@
#!/bin/sh
[ -e /etc/.app_store.id ] && exit 0
mkdir -p /tmp/is-inst/var/lock
ARCH=`opkg -f /dev/null --offline-root /tmp/is-inst print-architecture | grep -v 'arch all' | grep -v 'arch noarch' | cut -d ' ' -f2`
rm -rf /tmp/is-inst
for iface in eth0 br-lan; do
if [ -e /sys/class/net/$iface/address ]; then
HASH=`md5sum /sys/class/net/$iface/address | cut -d ' ' -f1`
break
fi
done
if [ -z "$HASH" ]; then
HASH=`dd if=/dev/urandom bs=512 count=1 2>/dev/null | md5sum | cut -d ' ' -f1`
fi
echo "{\"arch\":\"${ARCH}\", \"uid\":\"${HASH}\"}" > /etc/.app_store.id
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache

View File

@ -0,0 +1,7 @@
clean:
compile:
install:
mkdir -p "$(DESTDIR)/www/luci-static"
cp -a "$(FRONTEND_DIST)/luci-static/istore" "$(DESTDIR)/www/luci-static/"
mkdir -p "$(DESTDIR)/etc"
echo "$(APP_STORE_VERSION)" > "$(DESTDIR)/etc/.app_store.version"