🛸 Sync 2024-01-10 01:02
@ -1,67 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015-2016 OpenWrt.org
|
||||
# Copyright (C) 2020 jjm2473@gmail.com
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_ARCH_DDNSTO:=$(ARCH)
|
||||
|
||||
PKG_NAME:=ddnsto
|
||||
PKG_VERSION:=3.0.4
|
||||
PKG_RELEASE:=$(PKG_ARCH_DDNSTO)-7
|
||||
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=http://fw.koolcenter.com/binary/ddnsto/
|
||||
PKG_HASH:=486aa15a5e026b5a3aca72f1850746e127a7e86ef11db8a7c498dad29545eaf6
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=DDNS.to - the reverse proxy
|
||||
DEPENDS:=
|
||||
PKGARCH:=all
|
||||
URL:=https://www.ddnsto.com/
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
DDNS.to is a reverse proxy
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/ddnsto
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
[ -f /etc/uci-defaults/ddnsto ] && /etc/uci-defaults/ddnsto && rm -f /etc/uci-defaults/ddnsto
|
||||
fi
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ddnsto.$(PKG_ARCH_DDNSTO) $(1)/usr/sbin/ddnstod
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ddwebdav.$(PKG_ARCH_DDNSTO) $(1)/usr/sbin/ddwebdav
|
||||
$(INSTALL_CONF) ./files/ddnsto.config $(1)/etc/config/ddnsto
|
||||
$(INSTALL_BIN) ./files/ddnsto.init $(1)/etc/init.d/ddnsto
|
||||
$(INSTALL_BIN) ./files/ddnsto.uci-default $(1)/etc/uci-defaults/ddnsto
|
||||
$(LN) /usr/sbin/ddnstod $(1)/usr/sbin/ddnsto
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
@ -1,49 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
DEVICE_IDX=0
|
||||
LOG_LEVEL=2
|
||||
while getopts u:x:l: flag
|
||||
do
|
||||
case "${flag}" in
|
||||
u) TOKEN=${OPTARG};;
|
||||
x) DEVICE_IDX=${OPTARG};;
|
||||
l) LOG_LEVEL=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
logger "ddnsto: the token is empty, get token from https://www.ddnsto.com/ "
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "ddnsto version device_id is is:"
|
||||
/usr/sbin/ddnsto -u ${TOKEN} -w
|
||||
|
||||
_term() {
|
||||
logger "ddnsto: SIGTERM"
|
||||
killall ddnsto 2>/dev/null
|
||||
killall ddwebdav 2>/dev/null
|
||||
|
||||
rm -f /tmp/.ddnsto.pid
|
||||
rm -f /tmp/.ddnsto.status
|
||||
rm -f /tmp/.ddnsto.up
|
||||
exit
|
||||
}
|
||||
|
||||
trap "_term;" SIGTERM
|
||||
|
||||
while true ; do
|
||||
if ! pidof "ddnsto" > /dev/null ; then
|
||||
logger "ddnsto try running"
|
||||
/usr/sbin/ddnsto -u ${TOKEN} -x ${DEVICE_IDX} &
|
||||
PID=$!
|
||||
wait $PID
|
||||
RET=$?
|
||||
logger "ddnsto EXIT CODE: ${RET}"
|
||||
if [ "${RET}" == "100" ]; then
|
||||
logger "ddnsto token error, please set a correct token from https://www.ddnsto.com/ "
|
||||
exit 100
|
||||
fi
|
||||
fi
|
||||
sleep 20
|
||||
done
|
@ -1,5 +0,0 @@
|
||||
config ddnsto
|
||||
option enabled '0'
|
||||
option feat_port '3033'
|
||||
option feat_enabled '0'
|
||||
option index '0'
|
@ -1,45 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 1
|
||||
config_get_bool logger $1 logger 0
|
||||
config_get token $1 token
|
||||
config_get index $1 index 0
|
||||
config_get_bool feat_enabled $1 feat_enabled 1
|
||||
}
|
||||
|
||||
ddnsto_prepare() {
|
||||
killall ddnstod 2>/dev/null
|
||||
killall ddwebdav 2>/dev/null
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
ddnsto_prepare
|
||||
}
|
||||
|
||||
start_service() {
|
||||
ddnsto_prepare
|
||||
config_load ddnsto
|
||||
config_foreach get_config ddnsto
|
||||
if [ $enabled != 1 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$token" ]; then
|
||||
logger -t ddnsto -p warn "token not set"
|
||||
return 1
|
||||
fi
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /usr/sbin/ddnstod -u "$token" -x $index -F
|
||||
[ "$logger" == 1 ] && procd_set_param stderr 1
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "ddnsto"
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@ddnsto[-1]
|
||||
add ucitrack ddnsto
|
||||
set ucitrack.@ddnsto[-1].init=ddnsto
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
/etc/init.d/ddnsto enable
|
||||
|
||||
exit 0
|
@ -1,223 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2017-2020 Ian Leonard <antonlacon@gmail.com>
|
||||
# Copyright (C) 2018 Ted Hess <thess@kitschensync.net>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ffmpeg-remux
|
||||
PKG_VERSION:=4.3.3
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=ffmpeg-$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=https://ffmpeg.org/releases/
|
||||
PKG_HASH:=9f0a68fbd74feb4e50dc220bddd59d84626774a53687fb737806ae00e5c6e9e6
|
||||
PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>, \
|
||||
Ian Leonard <antonlacon@gmail.com>
|
||||
|
||||
PKG_LICENSE:=LGPL-2.1-or-later GPL-2.0-or-later LGPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=COPYING.GPLv2 COPYING.GPLv3 COPYING.LGPLv2.1 COPYING.LGPLv3
|
||||
PKG_CPE_ID:=cpe:/a:ffmpeg:ffmpeg
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-x/ffmpeg-$(PKG_VERSION)
|
||||
|
||||
FFMPEG_REMUX_DECODERS:= \
|
||||
mpeg1video \
|
||||
mpeg2video \
|
||||
mpeg4 \
|
||||
mpegvideo \
|
||||
h264 \
|
||||
hevc \
|
||||
vc1 \
|
||||
|
||||
FFMPEG_REMUX_MUXERS:= \
|
||||
matroska \
|
||||
h264 \
|
||||
hevc \
|
||||
mp4 \
|
||||
mpeg1video \
|
||||
mpeg2video \
|
||||
mpegts \
|
||||
ogg \
|
||||
|
||||
FFMPEG_REMUX_DEMUXERS:= \
|
||||
avi \
|
||||
h264 \
|
||||
hevc \
|
||||
matroska \
|
||||
mov \
|
||||
mpegps \
|
||||
mpegts \
|
||||
mpegvideo \
|
||||
ogg \
|
||||
rm \
|
||||
vc1 \
|
||||
wv \
|
||||
|
||||
FFMPEG_REMUX_PARSERS:= \
|
||||
aac \
|
||||
flac \
|
||||
ac3 \
|
||||
h264 \
|
||||
hevc \
|
||||
mpegaudio \
|
||||
mpeg4video \
|
||||
mpegvideo \
|
||||
vc1 \
|
||||
|
||||
FFMPEG_REMUX_PROTOCOLS:= \
|
||||
file pipe
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ffmpeg-remux
|
||||
TITLE:=FFmpeg remux
|
||||
SECTION:=multimedia
|
||||
CATEGORY:=Multimedia
|
||||
URL:=https://ffmpeg.org/
|
||||
DEPENDS+= +libpthread +zlib +libbz2
|
||||
endef
|
||||
|
||||
define Package/ffmpeg-remux/description
|
||||
FFmpeg remux only program
|
||||
endef
|
||||
|
||||
# Strip off FPU notation
|
||||
REAL_CPU_TYPE:=$(firstword $(subst +, ,$(CONFIG_CPU_TYPE)))
|
||||
# Fixup cpu types recogized by ffmpeg configure
|
||||
REAL_CPU_TYPE:=$(subst octeonplus,octeon+,$(REAL_CPU_TYPE))
|
||||
|
||||
FFMPEG_CONFIGURE:= \
|
||||
CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(FPIC)" \
|
||||
LDFLAGS="$(TARGET_LDFLAGS)" \
|
||||
./configure \
|
||||
--enable-cross-compile \
|
||||
--cross-prefix="$(TARGET_CROSS)" \
|
||||
--arch="$(ARCH)" \
|
||||
$(if $(REAL_CPU_TYPE),--cpu=$(call qstrip,$(REAL_CPU_TYPE)),) \
|
||||
--target-os=linux \
|
||||
--prefix="/usr" \
|
||||
--pkg-config="pkg-config" \
|
||||
--enable-shared \
|
||||
--enable-pthreads \
|
||||
--enable-zlib \
|
||||
--disable-doc \
|
||||
--disable-debug \
|
||||
\
|
||||
--disable-lzma \
|
||||
--disable-vaapi \
|
||||
--disable-vdpau \
|
||||
--disable-outdevs
|
||||
|
||||
ifeq ($(CONFIG_SOFT_FLOAT),y)
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--disable-altivec \
|
||||
--disable-vsx \
|
||||
--disable-power8 \
|
||||
--disable-armv5te \
|
||||
--disable-armv6 \
|
||||
--disable-armv6t2 \
|
||||
--disable-fast-unaligned \
|
||||
--disable-runtime-cpudetect
|
||||
|
||||
else ifneq ($(findstring arm,$(CONFIG_ARCH))$(findstring aarch64,$(CONFIG_ARCH)),)
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--disable-runtime-cpudetect
|
||||
# XXX: GitHub issue 3320 ppc cpu with fpu but no altivec (WNDR4700)
|
||||
else ifneq ($(findstring powerpc,$(CONFIG_ARCH)),)
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--disable-altivec
|
||||
endif
|
||||
|
||||
# selectively disable optimizations according to arch/cpu type
|
||||
ifneq ($(findstring arm,$(CONFIG_ARCH)),)
|
||||
FFMPEG_CONFIGURE+= --enable-lto
|
||||
|
||||
ifneq ($(findstring vfp,$(CONFIG_CPU_TYPE)),)
|
||||
FFMPEG_CONFIGURE+= --enable-vfp
|
||||
else
|
||||
FFMPEG_CONFIGURE+= --disable-vfp
|
||||
endif
|
||||
ifneq ($(findstring neon,$(CONFIG_CPU_TYPE)),)
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--enable-neon \
|
||||
--enable-vfp
|
||||
else
|
||||
FFMPEG_CONFIGURE+= --disable-neon
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(findstring aarch64,$(CONFIG_ARCH)),)
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--enable-lto \
|
||||
--enable-neon \
|
||||
--enable-vfp
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
FFMPEG_CONFIGURE+= --enable-lto
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FFMPEG_X86ASM),y)
|
||||
FFMPEG_CONFIGURE += --enable-x86asm
|
||||
else
|
||||
FFMPEG_CONFIGURE += --disable-x86asm
|
||||
endif
|
||||
|
||||
|
||||
FFMPEG_ENABLE= \
|
||||
$(foreach c, $(2), \
|
||||
--enable-$(1)="$(c)" \
|
||||
)
|
||||
|
||||
FFMPEG_CONFIGURE+= \
|
||||
--enable-hardcoded-tables \
|
||||
--disable-static \
|
||||
--libdir="/usr/lib/remux" \
|
||||
--enable-rpath \
|
||||
\
|
||||
--disable-ffplay \
|
||||
--disable-alsa \
|
||||
--disable-iconv \
|
||||
--disable-sndio \
|
||||
--disable-schannel \
|
||||
--disable-sdl2 \
|
||||
--disable-securetransport \
|
||||
--disable-xlib \
|
||||
--disable-v4l2-m2m \
|
||||
--disable-avdevice \
|
||||
--disable-postproc \
|
||||
--disable-swresample \
|
||||
--disable-swscale \
|
||||
--disable-everything \
|
||||
$(call FFMPEG_ENABLE,decoder,$(FFMPEG_REMUX_DECODERS)) \
|
||||
$(call FFMPEG_ENABLE,parser,$(FFMPEG_REMUX_PARSERS)) \
|
||||
$(call FFMPEG_ENABLE,demuxer,$(FFMPEG_REMUX_DEMUXERS)) \
|
||||
$(call FFMPEG_ENABLE,muxer,$(FFMPEG_REMUX_MUXERS)) \
|
||||
$(call FFMPEG_ENABLE,protocol,$(FFMPEG_REMUX_PROTOCOLS))
|
||||
|
||||
ifneq ($(CONFIG_TARGET_x86),)
|
||||
TARGET_CFLAGS+= -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
define Build/Configure
|
||||
( cd $(PKG_BUILD_DIR); $(FFMPEG_CONFIGURE) )
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
DESTDIR="$(PKG_INSTALL_DIR)" \
|
||||
all install
|
||||
endef
|
||||
|
||||
define Package/ffmpeg-remux/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/remux
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/remux/lib{avcodec,avfilter,avformat,avutil}.so.* $(1)/usr/lib/remux/
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/bin/ffmpeg $(1)/usr/bin/remux
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ffmpeg-remux))
|
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 易有云团队
|
||||
|
||||
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.
|
@ -1,4 +0,0 @@
|
||||
# iStore
|
||||
|
||||
## Introduce
|
||||
The iStore is a app store for OpenWRT, it is implemented using Shell scripts, only depends on OpenWRT standard components, and does not contain binary files itself
|
@ -1,51 +0,0 @@
|
||||
# iStore
|
||||
|
||||
## 介绍
|
||||
|
||||
iStore 是一个[开源](https://github.com/linkease/istore)且标准的 OpenWRT 软件中心实现。
|
||||
|
||||
是属于易有云团队的固件 [iStoreOS](https://github.com/istoreos) 的一部分。
|
||||
|
||||
iStore 的设计目标:
|
||||
|
||||
1. 方便用户安装插件
|
||||
2. 每个插件都有教程,方便初学者入门使用插件
|
||||
3. 适配所有的 OpenWRT 皮肤,以及移动端
|
||||
4. 全部基于 OpenWRT 的标准接口开发,不用以前 KoolShare LEDE 的特有的插件风格的软件中心
|
||||
|
||||
iStore 的无法弥补的缺陷:
|
||||
|
||||
1. 因为 OpenWRT 版本特别多,导致不同平台的插件依赖不一样。所以即使你的系统能安装 iStore,iStore 里面的插件不一定能安装
|
||||
2. 我们需要固件开发者自主集成 iStore,并解决 iStore 里面的各种插件的依赖
|
||||
|
||||
我们建议固件开发者集成 iStore,这样固件开发者只需要发布一个精简固件,用户可以按需安装自己喜欢的插件。还能共享插件的教程,独立更新某个插件版本。
|
||||
|
||||
> 21版本的固件安装 iStore 需要依赖 `luci-compat`
|
||||
|
||||
## 安装 iStore 到 OpenWRT 官方固件
|
||||
只支持 x86_64 和 arm64 设备。
|
||||
|
||||
```
|
||||
opkg update || exit 1
|
||||
cd /tmp
|
||||
wget https://github.com/linkease/openwrt-app-actions/raw/main/applications/luci-app-systools/root/usr/share/systools/istore-reinstall.run
|
||||
chmod 755 istore-reinstall.run
|
||||
./istore-reinstall.run
|
||||
```
|
||||
|
||||
## 集成到自己编译的固件中
|
||||
iStore 官方的软件仓库支持 `x86_64`,`arm64` 两个架构,这两个架构的基于 **OpenWRT** 固件都可以直接集成 iStore
|
||||
|
||||
只需在固件编译目录下执行:
|
||||
```shell
|
||||
echo >> feeds.conf.default
|
||||
echo 'src-git istore https://github.com/linkease/istore;main' >> feeds.conf.default
|
||||
./scripts/feeds update istore
|
||||
./scripts/feeds install -d y -p istore luci-app-store
|
||||
```
|
||||
|
||||
然后正常编译固件即可
|
||||
|
||||
## 功能预览
|
||||
|
||||
![istore-preview.png](./preview/istore-preview.png)
|
@ -1,150 +0,0 @@
|
||||
### 路由器端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":""}
|
||||
```
|
||||
|
||||
9. 检查iStore自身更新
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/check_self_upgrade
|
||||
|
||||
|
||||
{"code":500, "msg":"Internal Error"}
|
||||
{"code":200, "msg":"1.1.2"}
|
||||
{"code":304, "msg":""}
|
||||
```
|
||||
|
||||
1. 更新iStore自身
|
||||
> 检查iStore自身更新接口返回code为200时才调用这个接口
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/do_self_upgrade
|
||||
token=xxx
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
|
||||
2. 枚举块设备
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/get_block_devices
|
||||
|
||||
|
||||
{"code":500, "msg":"Unable to execute block utility"}
|
||||
{"code":200, "data":{"sda1":{"dev":"\/dev\/sda1","uuid":"f54566dd-ec58-4e24-9451-bbf75834add3","version":"1.0","type":"ext4","size":"238.46 GB"},"mmcblk0p2":{"dev":"\/dev\/mmcblk0p2","uuid":"dba3d0dc-f072-4e81-a0ac-ac35197fb286","version":"1.0","label":"etc","mount":"\/overlay","type":"ext4","size":"6.87 GB"},"mmcblk0p1":{"dev":"\/dev\/mmcblk0p1","uuid":"8f9564a1-68006e25-c4c26df6-de88ef16","version":"4.0","mount":"\/rom","type":"squashfs","size":"127.99 MB"}}}
|
||||
```
|
@ -1,39 +0,0 @@
|
||||
# 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 +opkg +luci-lib-ipkg +tar +coreutils +coreutils-stat +libuci-lua +mount-utils +luci-lib-taskd
|
||||
LUCI_EXTRA_DEPENDS:=luci-lib-taskd (>=1.0.17)
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_VERSION:=0.1.14-2
|
||||
# PKG_RELEASE MUST be empty for luci.mk
|
||||
PKG_RELEASE:=
|
||||
|
||||
ISTORE_UI_VERSION:=0.1.14
|
||||
ISTORE_UI_RELEASE:=2
|
||||
PKG_HASH:=4d20ffeabfe6572b01e0bedd860043ec0dbd6f2f63aaf0ee58caeb851df18e73
|
||||
|
||||
PKG_SOURCE_URL_FILE:=v$(ISTORE_UI_VERSION)-$(ISTORE_UI_RELEASE).tar.gz
|
||||
PKG_SOURCE:=istore-ui-$(PKG_SOURCE_URL_FILE)
|
||||
PKG_SOURCE_URL:=https://github.com/linkease/istore-ui/archive/refs/tags
|
||||
|
||||
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
|
||||
|
||||
TARGET_CONFIGURE_OPTS= FRONTEND_DIST="$(BUILD_DIR)/istore-ui-$(ISTORE_UI_VERSION)-$(ISTORE_UI_RELEASE)/app-store-ui/src/dist" APP_STORE_VERSION="$(PKG_VERSION)"
|
||||
TARGET_CONFIGURE_OPTS+= SED="$(SED)"
|
||||
|
||||
define Package/luci-app-store/conffiles
|
||||
/etc/.app_store.id
|
||||
/etc/config/istore
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
@ -1,3 +0,0 @@
|
||||
# luci-app-store
|
||||
OpenWRT应用商店
|
||||
|
@ -1,759 +0,0 @@
|
||||
module("luci.controller.store", package.seeall)
|
||||
|
||||
local myopkg = "is-opkg"
|
||||
local is_backup = "/usr/libexec/istore/backup"
|
||||
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
|
||||
if nixio.fs.access("/usr/lib/lua/luci/view/store/main_dev.htm") then
|
||||
entry({"admin", "store", "dev"}, call("store_dev")).leaf = true
|
||||
end
|
||||
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"))
|
||||
entry({"admin", "store", "check_self_upgrade"}, call("check_self_upgrade"))
|
||||
entry({"admin", "store", "do_self_upgrade"}, post("do_self_upgrade"))
|
||||
entry({"admin", "store", "toggle_docker"}, post("toggle_docker"))
|
||||
|
||||
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
|
||||
if nixio.fs.access("/usr/libexec/istore/backup") then
|
||||
entry({"admin", "store", "get_support_backup_features"}, call("get_support_backup_features"))
|
||||
entry({"admin", "store", "light_backup"}, post("light_backup"))
|
||||
entry({"admin", "store", "get_light_backup_file"}, call("get_light_backup_file"))
|
||||
entry({"admin", "store", "local_backup"}, post("local_backup"))
|
||||
entry({"admin", "store", "light_restore"}, post("light_restore"))
|
||||
entry({"admin", "store", "local_restore"}, post("local_restore"))
|
||||
entry({"admin", "store", "get_backup_app_list_file_path"}, call("get_backup_app_list_file_path"))
|
||||
entry({"admin", "store", "get_backup_app_list"}, call("get_backup_app_list"))
|
||||
entry({"admin", "store", "get_available_backup_file_list"}, call("get_available_backup_file_list"))
|
||||
entry({"admin", "store", "set_local_backup_dir_path"}, post("set_local_backup_dir_path"))
|
||||
entry({"admin", "store", "get_local_backup_dir_path"}, call("get_local_backup_dir_path"))
|
||||
entry({"admin", "store", "get_block_devices"}, call("get_block_devices"))
|
||||
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)
|
||||
end
|
||||
if id == nil then
|
||||
fs.unlink("/etc/.app_store.id")
|
||||
id = {arch="",uid=""}
|
||||
end
|
||||
|
||||
id.version = (fs.readfile("/etc/.app_store.version") or "?"):gsub("[\r\n]", "")
|
||||
|
||||
return id
|
||||
end
|
||||
|
||||
local function user_config()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
local data = {
|
||||
hide_docker = uci:get("istore", "istore", "hide_docker") == "1",
|
||||
channel = uci:get("istore", "istore", "channel")
|
||||
}
|
||||
return data
|
||||
end
|
||||
|
||||
local function vue_lang()
|
||||
local i18n = require("luci.i18n")
|
||||
local lang = i18n.translate("istore_vue_lang")
|
||||
if lang == "istore_vue_lang" or lang == "" then
|
||||
lang = "en"
|
||||
end
|
||||
return lang
|
||||
end
|
||||
|
||||
local function is_exec(cmd, async)
|
||||
local nixio = require "nixio"
|
||||
local os = require "os"
|
||||
local fs = require "nixio.fs"
|
||||
local rshift = nixio.bit.rshift
|
||||
|
||||
local oflags = nixio.open_flags("wronly", "creat")
|
||||
local lock, code, msg = nixio.open("/var/lock/istore.lock", oflags)
|
||||
if not lock then
|
||||
return 255, "", "Open lock failed: " .. msg
|
||||
end
|
||||
|
||||
-- Acquire lock
|
||||
local stat, code, msg = lock:lock("tlock")
|
||||
if not stat then
|
||||
lock:close()
|
||||
return 255, "", "Lock failed: " .. msg
|
||||
end
|
||||
|
||||
if async then
|
||||
cmd = "/etc/init.d/tasks task_add istore " .. luci.util.shellquote(cmd)
|
||||
end
|
||||
local r = os.execute(cmd .. " >/var/log/istore.stdout 2>/var/log/istore.stderr")
|
||||
local e = fs.readfile("/var/log/istore.stderr")
|
||||
local o = fs.readfile("/var/log/istore.stdout")
|
||||
|
||||
fs.unlink("/var/log/istore.stderr")
|
||||
fs.unlink("/var/log/istore.stdout")
|
||||
|
||||
lock:lock("ulock")
|
||||
lock:close()
|
||||
|
||||
e = e or ""
|
||||
if r == 256 and e == "" then
|
||||
e = "os.execute exit code 1"
|
||||
end
|
||||
return rshift(r,8), o or "", e or ""
|
||||
end
|
||||
|
||||
function redirect_index()
|
||||
luci.http.redirect(luci.dispatcher.build_url(unpack(page_index)))
|
||||
end
|
||||
|
||||
function store_index()
|
||||
local fs = require "nixio.fs"
|
||||
local features = { "_lua_force_array_" }
|
||||
if fs.access("/usr/libexec/istore/backup") then
|
||||
features[#features+1] = "backup"
|
||||
end
|
||||
if luci.sys.call("which docker >/dev/null 2>&1") == 0 then
|
||||
features[#features+1] = "docker"
|
||||
end
|
||||
if luci.sys.call("[ -d /ext_overlay ] >/dev/null 2>&1") == 0 then
|
||||
features[#features+1] = "sandbox"
|
||||
end
|
||||
if luci.sys.call("[ -f /www/luci-static/resources/luci.js ] >/dev/null 2>&1") == 0 then
|
||||
features[#features+1] = "luci-js"
|
||||
end
|
||||
luci.template.render("store/main", {prefix=luci.dispatcher.build_url(unpack(page_index)),id=user_id(),lang=vue_lang(),user_config=user_config(),features=features})
|
||||
end
|
||||
|
||||
function store_dev()
|
||||
luci.template.render("store/main_dev", {prefix=luci.dispatcher.build_url(unpack({"admin", "store", "dev"})),id=user_id(),lang=vue_lang(),user_config=user_config()})
|
||||
end
|
||||
|
||||
function store_log()
|
||||
local fs = require "nixio.fs"
|
||||
local code = 0
|
||||
local e = fs.readfile("/var/log/istore.stderr")
|
||||
local o = fs.readfile("/var/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
|
||||
|
||||
function check_self_upgrade()
|
||||
local ret = {
|
||||
code = 500,
|
||||
msg = "Unknown"
|
||||
}
|
||||
local r,o,e = is_exec(myopkg .. " check_self_upgrade")
|
||||
if r ~= 0 then
|
||||
ret.msg = e
|
||||
else
|
||||
ret.code = o == "" and 304 or 200
|
||||
ret.msg = o:gsub("[\r\n]", "")
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
end
|
||||
|
||||
function do_self_upgrade()
|
||||
local code, out, err, ret
|
||||
code,out,err = is_exec(myopkg .. " do_self_upgrade")
|
||||
ret = {
|
||||
code = code,
|
||||
stdout = out,
|
||||
stderr = err
|
||||
}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
end
|
||||
|
||||
-- Internal action function
|
||||
local function _action(exe, cmd, ...)
|
||||
|
||||
local pkg = ""
|
||||
for k, v in pairs({...}) do
|
||||
pkg = pkg .. " " .. luci.util.shellquote(v)
|
||||
end
|
||||
|
||||
local c = "%s %s %s" %{ exe, cmd, pkg }
|
||||
|
||||
return is_exec(c, true)
|
||||
end
|
||||
|
||||
function store_action(param)
|
||||
local metadir = "/usr/lib/opkg/meta"
|
||||
local metapkgpre = "app-meta-"
|
||||
local code, out, err, ret
|
||||
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) or {}
|
||||
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 metadata = fs.readfile(metadir .. "/" .. pkg)
|
||||
if metadata ~= nil then
|
||||
local meta = json_parse(metadata)
|
||||
if meta == nil then
|
||||
local i18n = require("luci.i18n")
|
||||
local name = pkg:gsub("^(.-)%.json$", "%1")
|
||||
meta = {
|
||||
name = name,
|
||||
title = "{ " .. name .. " }",
|
||||
author = "<UNKNOWN>",
|
||||
version = "0.0.0",
|
||||
description = i18n.translate("This package is broken! Please reinstall or uninstall it."),
|
||||
depends = {},
|
||||
tags = {"broken"},
|
||||
broken = true,
|
||||
}
|
||||
end
|
||||
local metapkg = metapkgpre .. meta.name
|
||||
local status = ipkg.status(metapkg)
|
||||
if next(status) ~= nil then
|
||||
meta.time = tonumber(status[metapkg]["Installed-Time"])
|
||||
data[#data+1] = meta
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
ret = data
|
||||
else
|
||||
local pkg = luci.http.formvalue("package")
|
||||
local metapkg = pkg and (metapkgpre .. pkg) or ""
|
||||
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"))
|
||||
local pkgs = {}
|
||||
if meta == nil then
|
||||
meta = {
|
||||
depends = {},
|
||||
}
|
||||
end
|
||||
if action == "upgrade" then
|
||||
pkgs = meta.depends
|
||||
table.insert(pkgs, metapkg)
|
||||
code, out, err = _action(myopkg, action, unpack(pkgs))
|
||||
else -- remove
|
||||
for _, dep in ipairs(meta.depends) do
|
||||
if dep ~= "docker-deps" and dep ~= "luci-js-deps" then
|
||||
pkgs[#pkgs+1] = dep
|
||||
end
|
||||
end
|
||||
table.insert(pkgs, metapkg)
|
||||
code, out, err = _action(myopkg, action, unpack(pkgs))
|
||||
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", "ls -l \"%s\"; md5sum \"%s\" 2>/dev/null; chmod 755 \"%s\" && \"%s\"; RET=$?; rm -f \"%s\"; exit $RET" %{ path, path, path, path, path })
|
||||
else
|
||||
code, out, err = _action("sh", "-c", "opkg install \"%s\"; RET=$?; rm -f \"%s\"; exit $RET" %{ path, 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
|
||||
|
||||
local function split(str,reps)
|
||||
local resultStrList = {}
|
||||
string.gsub(str,'[^'..reps..']+',function (w)
|
||||
table.insert(resultStrList,w)
|
||||
end)
|
||||
return resultStrList
|
||||
end
|
||||
|
||||
local function ltn12_popen(command)
|
||||
|
||||
local fdi, fdo = nixio.pipe()
|
||||
local pid = nixio.fork()
|
||||
|
||||
if pid > 0 then
|
||||
fdo:close()
|
||||
local close
|
||||
return function()
|
||||
local buffer = fdi:read(2048)
|
||||
local wpid, stat = nixio.waitpid(pid, "nohang")
|
||||
if not close and wpid and stat == "exited" then
|
||||
close = true
|
||||
end
|
||||
|
||||
if buffer and #buffer > 0 then
|
||||
return buffer
|
||||
elseif close then
|
||||
fdi:close()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
elseif pid == 0 then
|
||||
nixio.dup(fdo, nixio.stdout)
|
||||
fdi:close()
|
||||
fdo:close()
|
||||
nixio.exec("/bin/sh", "-c", command)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_support_backup_features
|
||||
function get_support_backup_features()
|
||||
local jsonc = require "luci.jsonc"
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
local success_ret = {code = 200, msg = "Unknown"}
|
||||
local r,o,e = is_exec(is_backup .. " get_support_backup_features")
|
||||
if r ~= 0 then
|
||||
error_ret.msg = e
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.code = 200
|
||||
success_ret.msg = jsonc.stringify(split(o,'\n'))
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- post light_backup
|
||||
function light_backup()
|
||||
local jsonc = require "luci.jsonc"
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
local success_ret = {code = 200,msg = "Unknown"}
|
||||
local r,o,e = is_exec(is_backup .. " backup")
|
||||
|
||||
if r ~= 0 then
|
||||
error_ret.msg = e
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.code = 200
|
||||
success_ret.msg = o:gsub("[\r\n]", "")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_light_backup_file
|
||||
function get_light_backup_file()
|
||||
local light_backup_cmd = "tar -c %s | gzip 2>/dev/null"
|
||||
local loght_backup_filelist = "/etc/istore/app.list"
|
||||
local reader = ltn12_popen(light_backup_cmd:format(loght_backup_filelist))
|
||||
luci.http.header('Content-Disposition', 'attachment; filename="light-backup-%s-%s.tar.gz"' % {
|
||||
luci.sys.hostname(), os.date("%Y-%m-%d")})
|
||||
luci.http.prepare_content("application/x-targz")
|
||||
luci.ltn12.pump.all(reader, luci.http.write)
|
||||
end
|
||||
|
||||
local function update_local_backup_path(path)
|
||||
local uci = require "uci"
|
||||
local fs = require "nixio.fs"
|
||||
local x = uci.cursor()
|
||||
local local_backup_path
|
||||
|
||||
if fs.access("/etc/config/istore") then
|
||||
local_backup_path = x:get("istore","istore","local_backup_path")
|
||||
else
|
||||
--create config file
|
||||
local f=io.open("/etc/config/istore","a+")
|
||||
f:write("config istore \'istore\'\n\toption local_backup_path \'\'")
|
||||
f:flush()
|
||||
f:close()
|
||||
end
|
||||
|
||||
if path ~= local_backup_path then
|
||||
-- set uci config
|
||||
x:set("istore","istore","local_backup_path",path)
|
||||
x:commit("istore")
|
||||
end
|
||||
end
|
||||
|
||||
-- post local_backup
|
||||
function local_backup()
|
||||
local code, out, err, ret
|
||||
local error_ret
|
||||
local path = luci.http.formvalue("path")
|
||||
if path ~= "" then
|
||||
-- judge path
|
||||
code,out,err = is_exec("findmnt -T " .. path .. " -o TARGET|sed -n 2p")
|
||||
if out:gsub("[\r\n]", "") == "/" or out:gsub("[\r\n]", "") == "/tmp" then
|
||||
-- error
|
||||
error_ret = {code = 500, stderr = "Path Error,Can not be / or tmp."}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
-- update local backup path
|
||||
update_local_backup_path(path)
|
||||
code,out,err = _action(is_backup, "backup", path)
|
||||
ret = {
|
||||
code = code,
|
||||
stdout = out,
|
||||
stderr = err
|
||||
}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
end
|
||||
else
|
||||
-- error
|
||||
error_ret = {code = 500, stderr = "Path Unknown"}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- post light_restore
|
||||
function light_restore()
|
||||
local fd
|
||||
local path
|
||||
local finished = false
|
||||
local tmpdir = "/tmp/"
|
||||
luci.http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not fd then
|
||||
path = tmpdir .. "/" .. meta.file
|
||||
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, ret
|
||||
|
||||
if finished then
|
||||
is_exec("rm /etc/istore/app.list;tar -xzf " .. path .. " -C /")
|
||||
nixio.fs.unlink(path)
|
||||
if nixio.fs.access("/etc/istore/app.list") then
|
||||
code,out,err = _action(is_backup, "restore")
|
||||
ret = {
|
||||
code = code,
|
||||
stdout = out,
|
||||
stderr = err
|
||||
}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
else
|
||||
local error_ret = {code = 500, stderr = "File is error!"}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
else
|
||||
ret = {code = 500, stderr = "upload failed!"}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- post local_restore
|
||||
function local_restore()
|
||||
local path = luci.http.formvalue("path")
|
||||
local code, out, err, ret
|
||||
if path ~= "" then
|
||||
code,out,err = _action(is_backup, "restore", path)
|
||||
ret = {
|
||||
code = code,
|
||||
stdout = out,
|
||||
stderr = err
|
||||
}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
else
|
||||
-- error
|
||||
error_ret = {code = 500, stderr = "Path Unknown"}
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_backup_app_list_file_path
|
||||
function get_backup_app_list_file_path()
|
||||
local jsonc = require "luci.jsonc"
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
local success_ret = {code = 200,msg = "Unknown"}
|
||||
local r,o,e = is_exec(is_backup .. " get_backup_app_list_file_path")
|
||||
if r ~= 0 then
|
||||
error_ret.msg = e
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.code = 200
|
||||
success_ret.msg = o:gsub("[\r\n]", "")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_backup_app_list
|
||||
function get_backup_app_list()
|
||||
local jsonc = require "luci.jsonc"
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
local success_ret = {code = 200,msg = "Unknown"}
|
||||
local r,o,e = is_exec(is_backup .. " get_backup_app_list")
|
||||
if r ~= 0 then
|
||||
error_ret.msg = e
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.code = 200
|
||||
success_ret.msg = jsonc.stringify(split(o,'\n'))
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_available_backup_file_list
|
||||
function get_available_backup_file_list()
|
||||
local jsonc = require "luci.jsonc"
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
local success_ret = {code = 200,msg = "Unknown"}
|
||||
local path = luci.http.formvalue("path")
|
||||
local r,o,e
|
||||
|
||||
if path ~= "" then
|
||||
-- update local backup path
|
||||
update_local_backup_path(path)
|
||||
r,o,e = is_exec(is_backup .. " get_available_backup_file_list " .. path)
|
||||
if r ~= 0 then
|
||||
error_ret.msg = e
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.code = 200
|
||||
success_ret.msg = jsonc.stringify(split(o,'\n'))
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
else
|
||||
-- set error code
|
||||
error_ret.msg = "Path Unknown"
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- post set_local_backup_dir_path
|
||||
function set_local_backup_dir_path()
|
||||
local path = luci.http.formvalue("path")
|
||||
local success_ret = {code = 200, msg = "Success"}
|
||||
local error_ret = {code = 500, msg = "Unknown"}
|
||||
|
||||
if path ~= "" then
|
||||
-- update local backup path
|
||||
update_local_backup_path(path)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
else
|
||||
-- set error code
|
||||
error_ret.msg = "Path Unknown"
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- call get_local_backup_dir_path
|
||||
function get_local_backup_dir_path()
|
||||
local uci = require "uci"
|
||||
local fs = require "nixio.fs"
|
||||
local x = uci.cursor()
|
||||
local local_backup_path = nil
|
||||
local success_ret = {code = 200,msg = "Unknown"}
|
||||
local error_ret = {code = 500, msg = "Path Unknown"}
|
||||
|
||||
if fs.access("/etc/config/istore") then
|
||||
local_backup_path = x:get("istore","istore","local_backup_path")
|
||||
if local_backup_path == nil then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
else
|
||||
success_ret.msg = local_backup_path:gsub("[\r\n]", "")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(success_ret)
|
||||
end
|
||||
else
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
-- copy from /usr/lib/lua/luci/model/diskman.lua
|
||||
local function byte_format(byte)
|
||||
local suff = {"B", "KB", "MB", "GB", "TB"}
|
||||
for i=1, 5 do
|
||||
if byte > 1024 and i < 5 then
|
||||
byte = byte / 1024
|
||||
else
|
||||
return string.format("%.2f %s", byte, suff[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- copy from /usr/libexec/rpcd/luci
|
||||
local function getBlockDevices()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local block = io.popen("/sbin/block info", "r")
|
||||
if block then
|
||||
local rv = {}
|
||||
|
||||
while true do
|
||||
local ln = block:read("*l")
|
||||
if not ln then
|
||||
break
|
||||
end
|
||||
|
||||
local dev = ln:match("^/dev/(.-):")
|
||||
if dev then
|
||||
local s = tonumber((fs.readfile("/sys/class/block/" .. dev .."/size")))
|
||||
local e = {
|
||||
dev = "/dev/" .. dev,
|
||||
size = s and byte_format(s * 512)
|
||||
}
|
||||
|
||||
local key, val = { }
|
||||
for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
|
||||
e[key:lower()] = val
|
||||
end
|
||||
|
||||
rv[dev] = e
|
||||
end
|
||||
end
|
||||
|
||||
block:close()
|
||||
|
||||
return rv
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function get_block_devices()
|
||||
local error_ret = {code = 500, msg = "Unable to execute block utility"}
|
||||
local devices = getBlockDevices()
|
||||
if devices ~= nil then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({code = 200, data = devices})
|
||||
else
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(error_ret)
|
||||
end
|
||||
end
|
||||
|
||||
function toggle_docker()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local hide = luci.http.formvalue("hide")
|
||||
uci:set("istore", "istore", "hide_docker", hide == "true" and "1" or "0")
|
||||
uci:commit("istore")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({code = 200, msg = "Success"})
|
||||
end
|
@ -1,62 +0,0 @@
|
||||
<%+header%>
|
||||
<%
|
||||
local jsonc = require "luci.jsonc"
|
||||
%>
|
||||
<script>
|
||||
(function(){
|
||||
var vue_prefix="<%=prefix%>";
|
||||
var myurl = window.location.pathname;
|
||||
window.addEventListener('popstate', function(){
|
||||
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.istore_api_base = "https://istore.linkease.com";
|
||||
window.vue_lang_data = '/luci-static/istore/i18n/<%=lang%>.json?v=<%=id.version%>';
|
||||
window.vue_lang = '<%=lang%>';
|
||||
window.token = "<%=token%>";
|
||||
window.device_id = {arch:"<%=id.arch%>",uid:"<%=id.uid%>",version:"<%=id.version%>"};
|
||||
window.istore_features = <%=jsonc.stringify(features)%>.filter(f => f !== '_lua_force_array_');
|
||||
window.istore_config = <%=jsonc.stringify(user_config or {})%>;
|
||||
})();
|
||||
</script>
|
||||
<h2 name="content"><%:iStore%>
|
||||
<a onclick="void(0)" href="https://github.com/linkease/istore/issues/22" target="_blank" style="text-decoration: none;">
|
||||
v<%=id.version%>
|
||||
</a>
|
||||
</h2>
|
||||
<link rel="stylesheet" href="/luci-static/istore/style.css?v=<%=id.version%>">
|
||||
<div id="app">
|
||||
</div>
|
||||
<%+tasks/embed%>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
let beforeunloadRegistered = false;
|
||||
window.istore_log = function(flush_menu_onclose) {
|
||||
if (flush_menu_onclose && !beforeunloadRegistered) {
|
||||
beforeunloadRegistered = true;
|
||||
window.addEventListener("beforeunload", function(event) {
|
||||
try { window.L.ui.menu.flushCache() } catch (e) { }
|
||||
return true;
|
||||
});
|
||||
}
|
||||
taskd.show_log("istore", true);
|
||||
};
|
||||
})();
|
||||
<%
|
||||
local taskd = require "luci.model.tasks"
|
||||
local status = taskd.status("istore")
|
||||
if status.running or status.exit_code ~= 404 then
|
||||
-%>
|
||||
window.istore_log(true);
|
||||
<%
|
||||
end
|
||||
%>
|
||||
</script>
|
||||
|
||||
<script type="module" crossorigin src="/luci-static/istore/index.js?v=<%=id.version%>"></script>
|
||||
<%+footer%>
|
@ -1,218 +0,0 @@
|
||||
#!/bin/sh
|
||||
# this script MUST supports executting without luci-app-store installed,
|
||||
# so we can use this script to install luci-app-store itself
|
||||
|
||||
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=`sed -n -e 's/^Architecture: *\([^ ]\+\) *$/\1/p' /rom/usr/lib/opkg/info/libc.control /usr/lib/opkg/info/libc.control 2>/dev/null | head -1`
|
||||
|
||||
# for istore self upgrade
|
||||
ISTORE_PKG=luci-app-store
|
||||
ISTORE_DEP_PKGS="luci-lib-taskd luci-lib-xterm taskd"
|
||||
ISTORE_INDEX=https://istore.linkease.com/repo/all/store/Packages.gz
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
|
||||
is_init() {
|
||||
mkdir -p ${DL_DIR} ${LISTS_DIR} ${IS_ROOT}/etc ${IS_ROOT}/var
|
||||
|
||||
cat /etc/opkg.conf | grep -Fv lists_dir | grep -Fv 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
|
||||
# create opkg_o.conf for executting 'opkg update' with offline-root, so we don't overwrite system opkg list
|
||||
echo >> ${IS_ROOT}/etc/opkg_o.conf
|
||||
echo "lists_dir ext ${LISTS_DIR_O}" >> ${IS_ROOT}/etc/opkg_o.conf
|
||||
|
||||
cp -au /etc/opkg ${IS_ROOT}/etc/
|
||||
[ -e ${IS_ROOT}/var/lock ] || ln -s /var/lock ${IS_ROOT}/var/lock
|
||||
}
|
||||
|
||||
opkg_wrap() {
|
||||
OPKG_CONF_DIR=${OPKG_CONF_DIR} opkg -f ${IS_ROOT}/etc/opkg.conf "$@"
|
||||
}
|
||||
|
||||
fcurl() {
|
||||
curl --fail --show-error "$@"
|
||||
}
|
||||
|
||||
check_space() {
|
||||
local free="$((`stat -c '%a * %S' -f /` >> 20 ))"
|
||||
if [ "$free" -lt 1 ]; then
|
||||
echo "Root disk full!" >&2
|
||||
exit 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
update() {
|
||||
if [ -z "${ARCH}" ]; then
|
||||
echo "Get architecture failed" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
fcurl -o ${OPKG_CONF_DIR}/meta.conf "${FEEDS_SERVER}/all/meta.conf" && \
|
||||
fcurl -o ${OPKG_CONF_DIR}/all.conf "${FEEDS_SERVER}/all/isfeeds.conf" && \
|
||||
fcurl -o ${OPKG_CONF_DIR}/arch.conf "${FEEDS_SERVER}/${ARCH}/isfeeds.conf" || \
|
||||
return 1
|
||||
|
||||
opkg -f ${IS_ROOT}/etc/opkg_o.conf --offline-root ${IS_ROOT} update
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
update_if_outdate() {
|
||||
local idle_t=$((`date '+%s'` - `date -r ${IS_ROOT}/.last_force_ts '+%s' 2>/dev/null || echo '0'`))
|
||||
[ $idle_t -gt ${1:-120} ] || return 2
|
||||
update || return 1
|
||||
touch ${IS_ROOT}/.last_force_ts
|
||||
return 0
|
||||
}
|
||||
|
||||
check_self_upgrade() {
|
||||
local newest=`curl --connect-timeout 2 --max-time 5 -s ${ISTORE_INDEX} | gunzip | grep -FA10 "Package: ${ISTORE_PKG}" | grep -Fm1 'Version: ' | sed 's/^Version: //'`
|
||||
local current=`grep -Fm1 'Version: ' /usr/lib/opkg/info/${ISTORE_PKG}.control | sed 's/^Version: //'`
|
||||
if [ "v$newest" = "v" -o "v$current" = "v" ]; then
|
||||
echo "Check version failed!" >&2
|
||||
exit 255
|
||||
fi
|
||||
if [ "$newest" != "$current" ]; then
|
||||
echo "$newest"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
do_self_upgrade_0() {
|
||||
opkg_wrap upgrade ${ISTORE_DEP_PKGS} && opkg_wrap upgrade ${ISTORE_PKG}
|
||||
}
|
||||
|
||||
do_self_upgrade() {
|
||||
check_mtime || return 1
|
||||
local newest=`curl --connect-timeout 2 --max-time 5 -s ${ISTORE_INDEX} | gunzip | grep -FA10 "Package: ${ISTORE_PKG}" | grep -Fm1 'Version: ' | sed 's/^Version: //'`
|
||||
local current=`grep -Fm1 'Version: ' /usr/lib/opkg/info/${ISTORE_PKG}.control | sed 's/^Version: //'`
|
||||
if [ "v$newest" = "v" -o "v$current" = "v" ]; then
|
||||
echo "Check version failed!" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$newest" = "$current" ]; then
|
||||
echo "Already the latest version!" >&2
|
||||
return 1
|
||||
fi
|
||||
if opkg_wrap info ${ISTORE_PKG} | grep -qFm1 "Version: $newest"; then
|
||||
do_self_upgrade_0 && return 0
|
||||
update_if_outdate || return 1
|
||||
do_self_upgrade_0
|
||||
else
|
||||
update_if_outdate || return 1
|
||||
do_self_upgrade_0
|
||||
fi
|
||||
}
|
||||
|
||||
check_mtime() {
|
||||
find ${OPKG_CONF_DIR}/arch.conf -mtime -1 2>/dev/null | grep -q . || update
|
||||
}
|
||||
|
||||
wrapped_in_update() {
|
||||
check_mtime || return 1
|
||||
eval "$@" && return 0
|
||||
update_if_outdate || return 1
|
||||
eval "$@"
|
||||
}
|
||||
|
||||
step_upgrade() {
|
||||
local pkg
|
||||
local pkgs=""
|
||||
local metapkg=""
|
||||
for pkg in $@; do
|
||||
if [[ $pkg == app-meta-* ]]; then
|
||||
metapkg="$metapkg $pkg"
|
||||
else
|
||||
pkgs="$pkgs $pkg"
|
||||
fi
|
||||
done
|
||||
if [ -n "$pkgs" ]; then
|
||||
opkg_wrap upgrade $pkgs || return 1
|
||||
fi
|
||||
if [ -n "$metapkg" ]; then
|
||||
opkg_wrap upgrade $metapkg || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
new_upgrade() {
|
||||
check_mtime || return 1
|
||||
local metapkg=`echo "$@" | sed 's/ /\n/g' | grep -F app-meta-`
|
||||
if [ -z "$metapkg" ] || opkg_wrap info $metapkg | grep -qF not-installed ; then
|
||||
true
|
||||
else
|
||||
update_if_outdate
|
||||
fi
|
||||
wrapped_in_update step_upgrade "$@"
|
||||
}
|
||||
|
||||
remove() {
|
||||
opkg_wrap --autoremove --force-removal-of-dependent-packages remove "$@"
|
||||
}
|
||||
|
||||
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 package(s)"
|
||||
echo " install <pkgs> Install package(s)"
|
||||
echo " remove <pkgs|regexp> Remove package(s)"
|
||||
echo " info [pkg|regexp] Display all info for <pkg>"
|
||||
echo " list-upgradable List installed and upgradable packages"
|
||||
echo " check_self_upgrade Check iStore upgrade"
|
||||
echo " do_self_upgrade Upgrade iStore"
|
||||
echo " arch Show libc architecture"
|
||||
echo " opkg sys opkg wrap"
|
||||
}
|
||||
|
||||
is_init >/dev/null 2>&1
|
||||
|
||||
case $action in
|
||||
"update")
|
||||
update
|
||||
;;
|
||||
"install")
|
||||
check_space
|
||||
wrapped_in_update opkg_wrap install "$@"
|
||||
;;
|
||||
"upgrade")
|
||||
new_upgrade "$@"
|
||||
;;
|
||||
"remove")
|
||||
remove "$@" || remove "$@"
|
||||
;;
|
||||
"info")
|
||||
opkg_wrap info "$@"
|
||||
;;
|
||||
"list-upgradable")
|
||||
opkg_wrap list-upgradable
|
||||
;;
|
||||
"check_self_upgrade")
|
||||
check_self_upgrade
|
||||
;;
|
||||
"do_self_upgrade")
|
||||
check_space
|
||||
do_self_upgrade
|
||||
;;
|
||||
"arch")
|
||||
echo "$ARCH"
|
||||
;;
|
||||
"opkg")
|
||||
opkg_wrap "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
@ -1,3 +0,0 @@
|
||||
config istore 'istore'
|
||||
option hide_docker '0'
|
||||
# option channel 'istore'
|
@ -1,23 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2016 OpenWrt.org
|
||||
|
||||
START=45
|
||||
|
||||
boot() {
|
||||
[ -s /etc/.app_store.id ] && return 0
|
||||
|
||||
ARCH=`/bin/is-opkg arch`
|
||||
|
||||
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
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/etc/init.d/istore boot
|
||||
|
||||
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
|
@ -1,295 +0,0 @@
|
||||
#!/bin/sh
|
||||
#set -x
|
||||
#IS_DEBUG=1
|
||||
|
||||
IS_ROOT=/tmp/is-backup
|
||||
APP_LIST_FILE=/etc/istore/app.list
|
||||
BACKUP_CONFIG_FILE=/etc/config/istore
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
|
||||
|
||||
is_init() {
|
||||
mkdir -p ${IS_ROOT}
|
||||
}
|
||||
|
||||
opkg_list_installed_packages() {
|
||||
target=$1
|
||||
case $target in
|
||||
"preinstalled")
|
||||
OPKG_INFO_DIR="/rom/usr/lib/opkg/info"
|
||||
;;
|
||||
"userinstalled")
|
||||
OPKG_INFO_DIR="/overlay/upper/usr/lib/opkg/info"
|
||||
;;
|
||||
"allinstalled")
|
||||
OPKG_INFO_DIR="/usr/lib/opkg/info"
|
||||
;;
|
||||
*)
|
||||
echo "invalid target"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
(cd $OPKG_INFO_DIR && find . -depth -maxdepth 1 -name "*.list" -type f | sed 's#^\./\(.*\)\.list$#\1#g')
|
||||
}
|
||||
|
||||
ipk_build() {
|
||||
PKG_NAME_TEMP=$1
|
||||
IPK_OUTPUT_DIR=$2
|
||||
|
||||
UCI_BAK_DIR="/etc/istore/uci-defaults_bak/"
|
||||
UCI_DEF_DIR="etc/uci-defaults"
|
||||
OPKG_INFO_DIR="/usr/lib/opkg/info/"
|
||||
|
||||
[ -n "${PKG_NAME_TEMP}" ] || exit 1
|
||||
#get real pkg name in opkg
|
||||
PKG_NAME_TEMP=`cat ${IS_ROOT}/all_installed_package.list | sort -u | grep "^${PKG_NAME_TEMP}" | head -n 1`
|
||||
[ -n "${PKG_NAME_TEMP}" ] || exit 1
|
||||
|
||||
PKG_NAME=`cat ${OPKG_INFO_DIR}${PKG_NAME_TEMP}.control | grep "^Package: " | cut -d ' ' -f2`
|
||||
PKG_VER=`cat ${OPKG_INFO_DIR}${PKG_NAME}.control | grep "^Version: " | cut -d ' ' -f2`
|
||||
PKG_ARCH=`cat ${OPKG_INFO_DIR}${PKG_NAME}.control | grep "^Architecture: " | cut -d ' ' -f2`
|
||||
IPK_FILE_NAME="${PKG_NAME}_${PKG_VER}_${PKG_ARCH}"
|
||||
|
||||
rm -rf ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
mkdir -p ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
|
||||
#(1)make CONTROL dir; (2)copy control file to dir
|
||||
cd ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
mkdir -p CONTROL
|
||||
for control_file in `ls ${OPKG_INFO_DIR}${PKG_NAME}.* | grep -v ".list$"`; do
|
||||
file=${control_file##*/}
|
||||
suffix=${file##*.}
|
||||
cp ${control_file} CONTROL/${suffix}
|
||||
done
|
||||
|
||||
#(1)make DATA depend dir; (2)copy uci-defaults_bak file to dir; (3)copy other file to dir
|
||||
for pkgfile in `cat ${OPKG_INFO_DIR}${PKG_NAME}.list | cut -b 2-`; do
|
||||
file=${pkgfile##*/}
|
||||
path=${pkgfile%/*}
|
||||
mkdir -p ${path}
|
||||
if [ `echo "${path}" | grep "^${UCI_DEF_DIR}"` ]; then
|
||||
cp "${UCI_BAK_DIR}${file}" "${pkgfile}"
|
||||
else
|
||||
cp "/${pkgfile}" "${pkgfile}"
|
||||
fi
|
||||
done
|
||||
|
||||
#call ipkg-build script to build ipk
|
||||
/usr/libexec/istore/ipkg-build ${IS_ROOT}/${IPK_FILE_NAME} ${IPK_OUTPUT_DIR}
|
||||
echo "${IPK_FILE_NAME}.ipk" >> ${IPK_OUTPUT_DIR}/appdepipk.list
|
||||
|
||||
[ -n "${IS_DEBUG}" ] || rm -rf ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
}
|
||||
|
||||
# if arg is NULL, use light backup, otherwise use local backup
|
||||
backup() {
|
||||
[ -n "$1" ] && BACKUP_PATH=$1
|
||||
|
||||
#1.add all istore self data to sysupgrade config file,
|
||||
#sysupgrade will backup/restore it auto when flash new firmware
|
||||
echo "/etc/.app_store.id" > /lib/upgrade/keep.d/luci-app-store
|
||||
cat /usr/lib/opkg/info/luci-app-store.list >> /lib/upgrade/keep.d/luci-app-store
|
||||
echo "/etc/rc.d/S45istore" >> /lib/upgrade/keep.d/luci-app-store
|
||||
echo "/etc/istore/uci-defaults_bak" >> /lib/upgrade/keep.d/luci-app-store
|
||||
echo "${APP_LIST_FILE}" >> /lib/upgrade/keep.d/luci-app-store
|
||||
echo "${BACKUP_CONFIG_FILE}" >> /lib/upgrade/keep.d/luci-app-store
|
||||
|
||||
#write user installed package list to file
|
||||
opkg_list_installed_packages "userinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/user_installed_package.list
|
||||
|
||||
#write installed package list by istore feed to file
|
||||
cat ${IS_ROOT}/user_installed_package.list | \
|
||||
grep '^app-meta-' > ${IS_ROOT}/istore_installed_package.list
|
||||
|
||||
#if no input backup path, only back app.list
|
||||
mkdir -p /etc/istore
|
||||
cp ${IS_ROOT}/istore_installed_package.list ${APP_LIST_FILE}
|
||||
echo "backup installed package list to ${APP_LIST_FILE}"
|
||||
|
||||
if [ ! -n "${BACKUP_PATH}" ]; then
|
||||
echo "backup success"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d "${BACKUP_PATH}" ] && ! mkdir -p "${BACKUP_PATH}" ; then
|
||||
echo "invalid backup path, can not backup ipk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#write all installed package list to file
|
||||
opkg_list_installed_packages "allinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/all_installed_package.list
|
||||
|
||||
#write system pre installed package list to file
|
||||
opkg_list_installed_packages "preinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/pre_installed_package.list
|
||||
|
||||
#write installed packages and depends list by istore feed to file by depend sequence
|
||||
appdep_list=""
|
||||
temp_list=`cat ${IS_ROOT}/istore_installed_package.list | sed 's/^/\t/'`
|
||||
while [ -n "${temp_list}" ]
|
||||
do
|
||||
#get real pkg name
|
||||
for PKG_NAME_TEMP in ${temp_list}; do
|
||||
REAL_PKG_NAME=`cat ${IS_ROOT}/all_installed_package.list | sort -u | grep "^${PKG_NAME_TEMP}" | head -n 1`
|
||||
if [ "${REAL_PKG_NAME}" != "${PKG_NAME_TEMP}" ]; then
|
||||
temp_list=`echo "${temp_list}" | sed 's/^\t'"${PKG_NAME_TEMP}"'$/\t'"${REAL_PKG_NAME}"'/'`
|
||||
fi
|
||||
done
|
||||
|
||||
appdep_list=`echo -e "${temp_list}\n${appdep_list}"`
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "temp_list:\n""${temp_list}"
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "appdep_list:\n""${appdep_list}"
|
||||
|
||||
temp_list=`echo "${temp_list}" | xargs opkg depends | grep -v "depends on:" | grep -v " (>= " | grep -v " (= " | sort -u`
|
||||
done
|
||||
|
||||
appdep_list_all=`echo "${appdep_list}" | cut -f2 | grep -v "^$" | awk '!seen[$0]++'`
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "appdep_list_all:\n""${appdep_list_all}"
|
||||
echo "${appdep_list_all}" > ${IS_ROOT}/appdep.list
|
||||
|
||||
#3.rebuild all istore installed package to ipk and backup to userdata partation
|
||||
|
||||
# 4. create dir
|
||||
date=$(date +%Y-%m%d-%H%M)
|
||||
if [ ! -d "$BACKUP_PATH/backup_istore_$date" ];then
|
||||
mkdir $BACKUP_PATH/backup_istore_$date
|
||||
fi
|
||||
cp ${IS_ROOT}/istore_installed_package.list $BACKUP_PATH/backup_istore_$date/app.list
|
||||
cp ${IS_ROOT}/appdep.list $BACKUP_PATH/backup_istore_$date/appdep.list
|
||||
|
||||
#only backup non pre installed ipk
|
||||
cp ${IS_ROOT}/appdep.list ${IS_ROOT}/appdep_strip.list
|
||||
for pre_installed_pkg in `cat ${IS_ROOT}/appdep.list ${IS_ROOT}/pre_installed_package.list | sort -n | uniq -d`; do
|
||||
sed -i '/^'"$pre_installed_pkg"'$/d' ${IS_ROOT}/appdep_strip.list
|
||||
done
|
||||
|
||||
rm -f $BACKUP_PATH/backup_istore_$date/appdepipk.list
|
||||
echo "build ipk"
|
||||
for pkg_name in `cat ${IS_ROOT}/appdep_strip.list`; do
|
||||
ipk_build ${pkg_name} $BACKUP_PATH/backup_istore_$date
|
||||
done
|
||||
|
||||
# 5. create tar.gz file,and remove fir
|
||||
cd $BACKUP_PATH
|
||||
echo "write backup file to $BACKUP_PATH/backup_istore_$date.backup.tar.gz"
|
||||
tar -czf $BACKUP_PATH/backup_istore_$date.backup.tar.gz backup_istore_$date
|
||||
rm -rf $BACKUP_PATH/backup_istore_$date
|
||||
echo "backup success"
|
||||
}
|
||||
|
||||
# if arg is NULL, use light backup, otherwise use local backup
|
||||
restore() {
|
||||
if [ -n "$1" ]; then
|
||||
BACKUP_PATH_FILE=$1
|
||||
else
|
||||
echo "install package by ${APP_LIST_FILE}"
|
||||
is-opkg update
|
||||
for app in `cat ${APP_LIST_FILE}`; do
|
||||
#skip resotre istore self
|
||||
[ "A${app}" == "A""luci-app-store" ] && continue
|
||||
is-opkg install ${app}
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "${BACKUP_PATH_FILE}" ];then
|
||||
echo "invalid backup file, can not restore ipk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#1. Unzip file to dir
|
||||
BACKUP_PATH_FILE_NAME=${BACKUP_PATH_FILE##*/}
|
||||
BACKUP_PATH=/tmp/${BACKUP_PATH_FILE_NAME%.backup.tar.gz*}
|
||||
if [ -d "$BACKUP_PATH" ];then
|
||||
rm -rf $BACKUP_PATH
|
||||
fi
|
||||
mkdir -p $BACKUP_PATH
|
||||
echo "unpack input file..."
|
||||
# fix tar path error
|
||||
tar -zxf ${BACKUP_PATH_FILE} -C /tmp/
|
||||
|
||||
echo "check file"
|
||||
if [ ! -f "${BACKUP_PATH}/appdep.list" ];then
|
||||
echo "no available appdep.list, can not restore ipk"
|
||||
exit 1
|
||||
fi
|
||||
echo "check success"
|
||||
|
||||
#2. install ipk by backup path
|
||||
echo "restore begin"
|
||||
( cd ${BACKUP_PATH}; opkg install `cat ${BACKUP_PATH}/appdepipk.list` )
|
||||
|
||||
#3. rm dir
|
||||
rm -rf ${BACKUP_PATH}
|
||||
echo "restore success"
|
||||
}
|
||||
|
||||
get_support_backup_features() {
|
||||
echo "light_backup"
|
||||
#istore custom img mean support local_backup
|
||||
if [ -f /etc/istore_img_flag ];then
|
||||
echo "local_backup"
|
||||
fi
|
||||
}
|
||||
|
||||
get_backup_app_list_file_path() {
|
||||
echo "${APP_LIST_FILE}"
|
||||
}
|
||||
|
||||
get_backup_app_list() {
|
||||
if [ ! -f "${APP_LIST_FILE}" ];then
|
||||
echo "no app.list, can not get backup app list"
|
||||
exit 1
|
||||
fi
|
||||
cat ${APP_LIST_FILE}
|
||||
}
|
||||
|
||||
get_available_backup_file_list() {
|
||||
if [ -n "$1" ]; then
|
||||
for backup_file in `ls $1/*.backup.tar.gz`; do
|
||||
filename=${backup_file##*/}
|
||||
echo "${filename}"
|
||||
done
|
||||
else
|
||||
echo "input backup path is null"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "usage: backup sub-command [arguments...]"
|
||||
echo "where sub-command is one of:"
|
||||
echo " backup [dir] Backup all installed package(s) to [directory]"
|
||||
echo " restore [dir] Restore package(s) by [directory]"
|
||||
echo " get_support_backup_features get device support backup features"
|
||||
echo " get_backup_app_list_file_path get light backup app list file path"
|
||||
echo " get_backup_app_list get light backup app list"
|
||||
echo " get_available_backup_file_list get local available backup file list"
|
||||
}
|
||||
|
||||
is_init >/dev/null 2>&1
|
||||
|
||||
case $action in
|
||||
"get_support_backup_features")
|
||||
get_support_backup_features
|
||||
;;
|
||||
"backup")
|
||||
backup "$@"
|
||||
;;
|
||||
"restore")
|
||||
restore "$@"
|
||||
;;
|
||||
"get_backup_app_list_file_path")
|
||||
get_backup_app_list_file_path
|
||||
;;
|
||||
"get_backup_app_list")
|
||||
get_backup_app_list
|
||||
;;
|
||||
"get_available_backup_file_list")
|
||||
get_available_backup_file_list "$@"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
@ -1,200 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# ipkg-build -- construct a .ipk from a directory
|
||||
# Carl Worth <cworth@east.isi.edu>
|
||||
# based on a script by Steve Redler IV, steve@sr-tech.com 5-21-2001
|
||||
# 2003-04-25 rea@sr.unh.edu
|
||||
# Updated to work on Familiar Pre0.7rc1, with busybox tar.
|
||||
# Note it Requires: binutils-ar (since the busybox ar can't create)
|
||||
# For UID debugging it needs a better "find".
|
||||
set -e
|
||||
|
||||
version=1.0
|
||||
FIND="$(command -v find)"
|
||||
FIND="${FIND:-$(command -v gfind)}"
|
||||
TAR="${TAR:-$(command -v tar)}"
|
||||
GZIP="$(command -v gzip)"
|
||||
|
||||
# try to use fixed source epoch
|
||||
if [ -n "$PKG_SOURCE_DATE_EPOCH" ]; then
|
||||
TIMESTAMP=$(date --date="@$PKG_SOURCE_DATE_EPOCH")
|
||||
elif [ -n "$SOURCE_DATE_EPOCH" ]; then
|
||||
TIMESTAMP=$(date --date="@$SOURCE_DATE_EPOCH")
|
||||
else
|
||||
TIMESTAMP=$(date)
|
||||
fi
|
||||
|
||||
ipkg_extract_value() {
|
||||
sed -e "s/^[^:]*:[[:space:]]*//"
|
||||
}
|
||||
|
||||
required_field() {
|
||||
field=$1
|
||||
|
||||
grep "^$field:" < $CONTROL/control | ipkg_extract_value
|
||||
}
|
||||
|
||||
pkg_appears_sane() {
|
||||
local pkg_dir=$1
|
||||
|
||||
local owd=$PWD
|
||||
cd $pkg_dir
|
||||
|
||||
PKG_ERROR=0
|
||||
pkg=`required_field Package`
|
||||
version=`required_field Version | sed 's/Version://; s/^.://g;'`
|
||||
arch=`required_field Architecture`
|
||||
|
||||
if echo $pkg | grep '[^a-zA-Z0-9_.+-]'; then
|
||||
echo "*** Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])" >&2
|
||||
PKG_ERROR=1;
|
||||
fi
|
||||
|
||||
if [ -f $CONTROL/conffiles ]; then
|
||||
rm -f $CONTROL/conffiles.resolved
|
||||
|
||||
for cf in `$FIND $(sed -e "s!^/!$pkg_dir/!" $CONTROL/conffiles) -type f`; do
|
||||
echo "${cf#$pkg_dir}" >> $CONTROL/conffiles.resolved
|
||||
done
|
||||
|
||||
rm $CONTROL/conffiles
|
||||
if [ -f $CONTROL/conffiles.resolved ]; then
|
||||
mv $CONTROL/conffiles.resolved $CONTROL/conffiles
|
||||
chmod 0644 $CONTROL/conffiles
|
||||
fi
|
||||
fi
|
||||
|
||||
cd $owd
|
||||
return $PKG_ERROR
|
||||
}
|
||||
|
||||
resolve_file_mode_id() {
|
||||
local var=$1 type=$2 name=$3 id
|
||||
|
||||
case "$name" in
|
||||
root)
|
||||
id=0
|
||||
;;
|
||||
*[!0-9]*)
|
||||
id=$(sed -ne "s#^$type $name \\([0-9]\\+\\)\\b.*\$#\\1#p" "$TOPDIR/tmp/.packageusergroup" 2>/dev/null)
|
||||
;;
|
||||
*)
|
||||
id=$name
|
||||
;;
|
||||
esac
|
||||
|
||||
export "$var=$id"
|
||||
|
||||
[ -n "$id" ]
|
||||
}
|
||||
|
||||
###
|
||||
# ipkg-build "main"
|
||||
###
|
||||
file_modes=""
|
||||
usage="Usage: $0 [-v] [-h] [-m] <pkg_directory> [<destination_directory>]"
|
||||
while getopts "hvm:" opt; do
|
||||
case $opt in
|
||||
v ) echo $version
|
||||
exit 0
|
||||
;;
|
||||
h ) echo $usage >&2 ;;
|
||||
m ) file_modes=$OPTARG ;;
|
||||
\? ) echo $usage >&2
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
# continue on to process additional arguments
|
||||
|
||||
case $# in
|
||||
1)
|
||||
dest_dir=$PWD
|
||||
;;
|
||||
2)
|
||||
dest_dir=$2
|
||||
if [ "$dest_dir" = "." -o "$dest_dir" = "./" ] ; then
|
||||
dest_dir=$PWD
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
pkg_dir=$1
|
||||
|
||||
if [ ! -d $pkg_dir ]; then
|
||||
echo "*** Error: Directory $pkg_dir does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# CONTROL is second so that it takes precedence
|
||||
CONTROL=
|
||||
[ -d $pkg_dir/CONTROL ] && CONTROL=CONTROL
|
||||
if [ -z "$CONTROL" ]; then
|
||||
echo "*** Error: Directory $pkg_dir has no CONTROL subdirectory." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! pkg_appears_sane $pkg_dir; then
|
||||
echo >&2
|
||||
echo "ipkg-build: Please fix the above errors and try again." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_dir=$dest_dir/IPKG_BUILD.$$
|
||||
mkdir $tmp_dir
|
||||
|
||||
echo $CONTROL > $tmp_dir/tarX
|
||||
cd $pkg_dir
|
||||
for file_mode in $file_modes; do
|
||||
case $file_mode in
|
||||
/*:*:*:*)
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: file modes must use absolute path and contain user:group:mode"
|
||||
echo "$file_mode"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mode=${file_mode##*:}; path=${file_mode%:*}
|
||||
group=${path##*:}; path=${path%:*}
|
||||
user=${path##*:}; path=${path%:*}
|
||||
|
||||
if ! resolve_file_mode_id uid user "$user"; then
|
||||
echo "ERROR: unable to resolve uid of $user" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! resolve_file_mode_id gid group "$group"; then
|
||||
echo "ERROR: unable to resolve gid of $group" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chown "$uid:$gid" "$pkg_dir/$path"
|
||||
chmod "$mode" "$pkg_dir/$path"
|
||||
done
|
||||
$TAR -X $tmp_dir/tarX --format=gnu --sort=name -cpf - --mtime="$TIMESTAMP" . | $GZIP -n - > $tmp_dir/data.tar.gz
|
||||
|
||||
installed_size=`stat -c "%s" $tmp_dir/data.tar.gz`
|
||||
sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \
|
||||
$pkg_dir/$CONTROL/control
|
||||
|
||||
( cd $pkg_dir/$CONTROL && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" . | $GZIP -n - > $tmp_dir/control.tar.gz )
|
||||
rm $tmp_dir/tarX
|
||||
|
||||
echo "2.0" > $tmp_dir/debian-binary
|
||||
|
||||
pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk
|
||||
rm -f $pkg_file
|
||||
( cd $tmp_dir && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" ./debian-binary ./data.tar.gz ./control.tar.gz | $GZIP -n - > $pkg_file )
|
||||
|
||||
rm $tmp_dir/debian-binary $tmp_dir/data.tar.gz $tmp_dir/control.tar.gz
|
||||
rmdir $tmp_dir
|
||||
|
||||
echo "Packaged contents of $pkg_dir into $pkg_file"
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
for i in "$@"; do
|
||||
echo "$i" | grep -s -q "/etc/uci-defaults/" \
|
||||
&& mkdir -p /etc/istore/uci-defaults_bak \
|
||||
&& cp -f "$i" /etc/istore/uci-defaults_bak/
|
||||
done
|
||||
/bin/rm "$@"
|
@ -1,23 +0,0 @@
|
||||
clean:
|
||||
compile:
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_NAME:=luci-lib-dummy
|
||||
INCLUDE_DIR:=./dummy
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
install:
|
||||
[ -n "$(APP_STORE_VERSION)" ]
|
||||
mkdir -p "$(DESTDIR)/www/luci-static"
|
||||
cp -a "$(FRONTEND_DIST)/luci-static/istore" "$(DESTDIR)/www/luci-static/"
|
||||
$(SED) 's#\.js"#.js?v=$(APP_STORE_VERSION)"#g' "$(DESTDIR)/www/luci-static/istore/index.js"
|
||||
mkdir -p "$(DESTDIR)/etc/opkg/keys"
|
||||
echo "$(APP_STORE_VERSION)" > "$(DESTDIR)/etc/.app_store.version"
|
||||
cp -a ./compat.conf "$(DESTDIR)/etc/opkg/compatfeeds.conf"
|
||||
cp -a ./key-build.pub $(DESTDIR)/etc/opkg/keys/`$(STAGING_DIR_HOST)/bin/usign -F -p ./key-build.pub`
|
||||
mkdir -p "$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n"
|
||||
$(foreach lang,$(LUCI_LANGUAGES),$(foreach po,$(wildcard ${CURDIR}/po/$(lang)/*.po), \
|
||||
po2lmo $(po) \
|
||||
$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n/$(basename $(notdir $(po))).$(lang).lmo;))
|
@ -1 +0,0 @@
|
||||
src/gz istore_compat https://istore.linkease.com/repo/all/compat
|
@ -1,2 +0,0 @@
|
||||
define BuildPackage
|
||||
endef
|
@ -1,2 +0,0 @@
|
||||
untrusted comment: istore key
|
||||
RWSlbxYnTG1Ia0BvB+xd7YdP7QDQACljfpve7sx9KYq94QgIqtlljuME
|
@ -1,11 +0,0 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "en"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr ""
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr ""
|
@ -1,11 +0,0 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "zh-cn"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr "iStore"
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr "此软件包已损坏!请重新安装或卸载它。"
|
@ -1,11 +0,0 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "zh-cn"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr "iStore"
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr "此軟體包已損壞!請重新安裝或卸載它。"
|
@ -1,20 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2022 jjm2473 <jjm2473@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the MIT License.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Task library
|
||||
LUCI_DEPENDS:=+luci-lib-xterm +taskd
|
||||
LUCI_EXTRA_DEPENDS:=taskd (>=1.0.3-1)
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_VERSION:=1.0.18
|
||||
PKG_RELEASE:=
|
||||
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
@ -1,112 +0,0 @@
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#tasks_detail_container {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: #0008;
|
||||
}
|
||||
#tasks_dialog {
|
||||
position: absolute;
|
||||
width: 770px;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: #000;
|
||||
|
||||
border-radius: 10px;
|
||||
box-shadow: 2px 2px 6px #000a;
|
||||
padding: 20px;
|
||||
|
||||
color: white;
|
||||
}
|
||||
.dialog-title-bar {
|
||||
margin-top: -10px;
|
||||
margin-right: -10px;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
.dialog-title-bar .dialog-title {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dialog-content {
|
||||
max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
margin-right: -10px;
|
||||
}
|
||||
.dialog-icons {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.dialog-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
color: black;
|
||||
border-radius: 50%;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
margin-left: 10px;
|
||||
line-height: 1;
|
||||
font-family: sans-serif;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dialog-icon.dialog-icon-min {
|
||||
background-color: darkorange;
|
||||
}
|
||||
.dialog-icon.dialog-icon-close {
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
.dialog-icons:hover .dialog-icon.dialog-icon-min:before {
|
||||
content: "_";
|
||||
}
|
||||
.dialog-icons:hover .dialog-icon.dialog-icon-close:before {
|
||||
content: "X";
|
||||
}
|
||||
|
||||
.tasks_stopped .dialog-icon.dialog-icon-close {
|
||||
background-color: #27c840;
|
||||
}
|
||||
.tasks_stopped #tasks_dialog, .tasks_unknown #tasks_dialog {
|
||||
padding: 19px;
|
||||
border: 1px #27c840 solid;
|
||||
|
||||
animation: border-blink 1s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.tasks_failed #tasks_dialog {
|
||||
border-color: #ff0000;
|
||||
}
|
||||
|
||||
.tasks_failed .dialog-icon.dialog-icon-close {
|
||||
background-color: #ff0000;
|
||||
}
|
||||
|
||||
.tasks_unknown #tasks_dialog {
|
||||
border-color: darkorange;
|
||||
}
|
||||
|
||||
@keyframes border-blink { 50% { border-color:#fff ; } }
|
@ -1,232 +0,0 @@
|
||||
|
||||
(function(){
|
||||
const taskd={};
|
||||
const $gettext = function(str) {
|
||||
return taskd.i18n[str] || str;
|
||||
};
|
||||
const retryPromise = function(fn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const retry = function() {
|
||||
fn(resolve, reject, retry);
|
||||
};
|
||||
retry();
|
||||
});
|
||||
};
|
||||
const retry403XHR = function(url, method, responseType) {
|
||||
return retryPromise((resolve, reject, retry) => {
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.onerror = reject;
|
||||
oReq.open(method || 'GET', url, true);
|
||||
if (responseType) {
|
||||
oReq.responseType = responseType;
|
||||
}
|
||||
oReq.onload = function (oEvent) {
|
||||
if (oReq.status == 403) {
|
||||
alert($gettext("Lost login status"));
|
||||
location.href = location.href;
|
||||
} else if (oReq.status == 404) {
|
||||
reject(oEvent);
|
||||
} else {
|
||||
resolve(oReq);
|
||||
}
|
||||
};
|
||||
if (method=='POST') {
|
||||
oReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
oReq.send(method=='POST'?("token="+taskd.csrfToken):null);
|
||||
});
|
||||
};
|
||||
const request = function(url, method) {
|
||||
return retry403XHR(url, method).then(oReq => oReq.responseText);
|
||||
};
|
||||
const getBin = function(url) {
|
||||
return retry403XHR(url, null, "arraybuffer").then(oReq => {return {status: oReq.status, buffer: new Uint8Array(oReq.response)}});
|
||||
};
|
||||
const getTaskDetail = function(task_id) {
|
||||
return request("/cgi-bin/luci/admin/system/tasks/status?task_id="+task_id).then(data=>JSON.parse(data));
|
||||
};
|
||||
const create_dialog = function(cfg) {
|
||||
const container = document.createElement('div');
|
||||
container.id = "tasks_detail_container";
|
||||
container.innerHTML = taskd.dialog_template;
|
||||
|
||||
document.body.appendChild(container);
|
||||
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
|
||||
title_view.innerText = cfg.title;
|
||||
|
||||
const term = new Terminal({convertEol: cfg.convertEol||false});
|
||||
if (cfg.nohide) {
|
||||
container.querySelector(".dialog-icon-min").hidden = true;
|
||||
} else {
|
||||
container.querySelector(".dialog-icon-min").onclick = function(){
|
||||
container.hidden=true;
|
||||
term.dispose();
|
||||
document.body.removeChild(container);
|
||||
cfg.onhide && cfg.onhide();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
term.open(document.getElementById("tasks_xterm_log"));
|
||||
|
||||
return {term,container};
|
||||
};
|
||||
const show_log_txt = function(title, content, onclose) {
|
||||
const dialog = create_dialog({title, convertEol:true, onhine:onclose});
|
||||
const container = dialog.container;
|
||||
const term = dialog.term;
|
||||
container.querySelector(".dialog-icon-close").hidden = true;
|
||||
term.write(content);
|
||||
};
|
||||
const show_log = function(task_id, nohide) {
|
||||
let showing = true;
|
||||
let running = true;
|
||||
const dialog = create_dialog({title:task_id, nohide, onhide:function(){showing=false;}});
|
||||
const container = dialog.container;
|
||||
const term = dialog.term;
|
||||
|
||||
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
|
||||
container.querySelector(".dialog-icon-close").onclick = function(){
|
||||
if (!running || confirm($gettext("Stop running task?"))) {
|
||||
running=false;
|
||||
showing=false;
|
||||
del_task(task_id).then(()=>{
|
||||
location.href = location.href;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const checkTask = function() {
|
||||
return getTaskDetail(task_id).then(data=>{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
running = data.running;
|
||||
let title = task_id;
|
||||
if (!data.running && data.stop) {
|
||||
title += " (" + (data.exit_code?$gettext("Failed at:"):$gettext("Finished at:")) + " " + new Date(data.stop * 1000).toLocaleString() + ")";
|
||||
}
|
||||
title += " > " + (data.command || '');
|
||||
title_view.title = title;
|
||||
title_view.innerText = title;
|
||||
if (!data.running) {
|
||||
container.classList.add('tasks_stopped');
|
||||
if (data.exit_code) {
|
||||
container.classList.add('tasks_failed');
|
||||
}
|
||||
}
|
||||
// last pull
|
||||
return showing;
|
||||
});
|
||||
};
|
||||
let logoffset = 0;
|
||||
const pulllog = function(check) {
|
||||
let starter = Promise.resolve(showing);
|
||||
if (check) {
|
||||
starter = checkTask();
|
||||
}
|
||||
starter.then(again => {
|
||||
if (again)
|
||||
return getBin("/cgi-bin/luci/admin/system/tasks/log?task_id="+task_id+"&offset="+logoffset);
|
||||
else
|
||||
return {status: 204};
|
||||
}).then(function(res){
|
||||
if (!showing) {
|
||||
return false;
|
||||
}
|
||||
switch(res.status){
|
||||
case 205:
|
||||
term.reset();
|
||||
logoffset = 0;
|
||||
return running;
|
||||
break;
|
||||
case 204:
|
||||
return running && checkTask();
|
||||
break;
|
||||
case 200:
|
||||
logoffset += res.buffer.byteLength;
|
||||
term.write(res.buffer);
|
||||
return running;
|
||||
break;
|
||||
}
|
||||
}).then(again => {
|
||||
if (again) {
|
||||
setTimeout(pulllog, 0);
|
||||
}
|
||||
}).catch(err => {
|
||||
if (showing) {
|
||||
if (err.target.status == 0) {
|
||||
title_view.innerText = task_id + ' (' + $gettext("Fetch log failed, retrying...") + ')';
|
||||
setTimeout(()=>pulllog(true), 1000);
|
||||
} else if (err.target.status == 403 || err.target.status == 404) {
|
||||
title_view.innerText = task_id + ' (' + $gettext(err.target.status == 403?"Lost login status":"Task does not exist or has been deleted") + ')';
|
||||
container.querySelector(".dialog-icon-close").hidden = true;
|
||||
container.classList.add('tasks_unknown');
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
pulllog(true);
|
||||
};
|
||||
const del_task = function(task_id) {
|
||||
return request("/cgi-bin/luci/admin/system/tasks/stop?task_id="+task_id, "POST");
|
||||
};
|
||||
taskd.show_log = show_log;
|
||||
taskd.remove = del_task;
|
||||
taskd.show_log_txt = show_log_txt;
|
||||
window.taskd=taskd;
|
||||
})();
|
||||
|
||||
(function(){
|
||||
// compat
|
||||
if (typeof(window.findParent) !== 'function') {
|
||||
const elem = function(e) {
|
||||
return (e != null && typeof(e) == 'object' && 'nodeType' in e);
|
||||
};
|
||||
const matches = function(node, selector) {
|
||||
var m = elem(node) ? node.matches || node.msMatchesSelector : null;
|
||||
return m ? m.call(node, selector) : false;
|
||||
};
|
||||
window.findParent = function (node, selector) {
|
||||
if (elem(node) && node.closest)
|
||||
return node.closest(selector);
|
||||
|
||||
while (elem(node))
|
||||
if (matches(node, selector))
|
||||
return node;
|
||||
else
|
||||
node = node.parentNode;
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
if (typeof(window.cbi_submit) !== 'function') {
|
||||
const makeHidden = function(name) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = name;
|
||||
return input;
|
||||
};
|
||||
window.cbi_submit = function(elem, name, value, action) {
|
||||
var form = elem.form || findParent(elem, 'form');
|
||||
|
||||
if (!form)
|
||||
return false;
|
||||
|
||||
if (action)
|
||||
form.action = action;
|
||||
|
||||
if (name) {
|
||||
var hidden = form.querySelector('input[type="hidden"][name="%s"]'.format(name)) ||
|
||||
makeHidden(name);
|
||||
|
||||
hidden.value = value || '1';
|
||||
form.appendChild(hidden);
|
||||
}
|
||||
|
||||
form.submit();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
})();
|
@ -1,98 +0,0 @@
|
||||
|
||||
module("luci.controller.tasks-lib", package.seeall)
|
||||
|
||||
|
||||
function index()
|
||||
entry({"admin", "system", "tasks"}, call("tasks_ping")).dependent=false -- just for compatible
|
||||
entry({"admin", "system", "tasks", "status"}, call("tasks_status")).dependent=false
|
||||
entry({"admin", "system", "tasks", "log"}, call("tasks_log")).dependent=false
|
||||
entry({"admin", "system", "tasks", "stop"}, post("tasks_stop")).dependent=false
|
||||
end
|
||||
|
||||
local util = require "luci.util"
|
||||
local jsonc = require "luci.jsonc"
|
||||
local ltn12 = require "luci.ltn12"
|
||||
|
||||
local taskd = require "luci.model.tasks"
|
||||
|
||||
function tasks_ping()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({})
|
||||
end
|
||||
|
||||
function tasks_status()
|
||||
local data = taskd.status(luci.http.formvalue("task_id"))
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(data)
|
||||
end
|
||||
|
||||
function tasks_log()
|
||||
local wait = 107
|
||||
local task_id = luci.http.formvalue("task_id")
|
||||
local offset = luci.http.formvalue("offset")
|
||||
offset = offset and tonumber(offset) or 0
|
||||
local logpath = "/var/log/tasks/"..task_id..".log"
|
||||
local i
|
||||
local logfd = io.open(logpath, "rb")
|
||||
if logfd == nil then
|
||||
luci.http.status(404)
|
||||
luci.http.write("log not found")
|
||||
return
|
||||
end
|
||||
|
||||
local size = logfd:seek("end")
|
||||
|
||||
if size < offset then
|
||||
luci.http.status(205, "Reset Content")
|
||||
luci.http.write("reset offset")
|
||||
return
|
||||
end
|
||||
|
||||
i = 0
|
||||
while (i < wait)
|
||||
do
|
||||
if size > offset then
|
||||
break
|
||||
end
|
||||
nixio.nanosleep(0, 10000000) -- sleep 10ms
|
||||
size = logfd:seek("end")
|
||||
i = i+1
|
||||
end
|
||||
if i == wait then
|
||||
logfd:close()
|
||||
luci.http.status(204)
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
return
|
||||
end
|
||||
logfd:seek("set", offset)
|
||||
|
||||
local write_log = function()
|
||||
local buffer = logfd:read(4096)
|
||||
if buffer and #buffer > 0 then
|
||||
return buffer
|
||||
else
|
||||
logfd:close()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
|
||||
if logfd then
|
||||
ltn12.pump.all(write_log, luci.http.write)
|
||||
end
|
||||
end
|
||||
|
||||
function tasks_stop()
|
||||
local sys = require("luci.sys")
|
||||
local task_id = luci.http.formvalue("task_id") or ""
|
||||
if task_id == "" then
|
||||
luci.http.status(400)
|
||||
luci.http.write("task_id is empty")
|
||||
return
|
||||
end
|
||||
if sys.call("/etc/init.d/tasks task_del "..task_id.." >/dev/null 2>&1") ~= 0 then
|
||||
nixio.nanosleep(2, 10000000)
|
||||
end
|
||||
luci.http.status(204)
|
||||
end
|
@ -1,100 +0,0 @@
|
||||
local util = require "luci.util"
|
||||
local jsonc = require "luci.jsonc"
|
||||
|
||||
local taskd = {}
|
||||
|
||||
local function output(data)
|
||||
local ret={}
|
||||
ret.running=data.running
|
||||
if not data.running then
|
||||
ret.exit_code=data.exit_code
|
||||
if nil == ret.exit_code then
|
||||
if data["data"] and data["data"]["exit_code"] and data["data"]["exit_code"] ~= "" then
|
||||
ret.exit_code=tonumber(data["data"]["exit_code"])
|
||||
else
|
||||
ret.exit_code=143
|
||||
end
|
||||
end
|
||||
end
|
||||
ret.command=data["command"] and data["command"][4] or '#'
|
||||
if data["data"] then
|
||||
ret.start=tonumber(data["data"]["start"])
|
||||
if not data.running and data["data"]["stop"] then
|
||||
ret.stop=tonumber(data["data"]["stop"])
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
taskd.status = function (task_id)
|
||||
task_id = task_id or ""
|
||||
local data = util.trim(util.exec("/etc/init.d/tasks task_status "..task_id.." 2>/dev/null")) or ""
|
||||
if data ~= "" then
|
||||
data = jsonc.parse(data)
|
||||
else
|
||||
if task_id == "" then
|
||||
data = {}
|
||||
else
|
||||
data = {running=false, exit_code=404}
|
||||
end
|
||||
end
|
||||
if task_id ~= "" then
|
||||
return output(data)
|
||||
end
|
||||
local ary={}
|
||||
for k, v in pairs(data) do
|
||||
ary[k] = output(v)
|
||||
end
|
||||
return ary
|
||||
end
|
||||
|
||||
taskd.docker_map = function(config, task_id, script_path, title, desc)
|
||||
require("luci.cbi")
|
||||
require("luci.http")
|
||||
require("luci.sys")
|
||||
local translate = require("luci.i18n").translate
|
||||
local m
|
||||
m = luci.cbi.Map(config, title, desc)
|
||||
m.template = "tasks/docker"
|
||||
-- hide default buttons
|
||||
m.pageaction = false
|
||||
-- we want hook 'on_after_apply' works, 'apply_on_parse' can be true (rollback) or false (no rollback),
|
||||
-- but 'apply_on_parse' must be true for luci 17.01 and below
|
||||
m.apply_on_parse = true
|
||||
m.script_path = script_path
|
||||
m.task_id = task_id
|
||||
m.auto_show_task = true
|
||||
m.on_before_apply = function(self)
|
||||
if self.uci.rollback then
|
||||
-- luci 18.06+ has 'rollback' function
|
||||
-- rollback dialog will show because 'apply_on_parse' is true,
|
||||
-- hide rollback dialog by hook 'apply' function
|
||||
local apply = self.uci.apply
|
||||
self.uci.apply = function(uci, rollback)
|
||||
apply(uci, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
m.on_after_apply = function(self)
|
||||
local cmd
|
||||
local action = luci.http.formvalue("cbi.apply") or "null"
|
||||
if "upgrade" == action or "install" == action
|
||||
or "start" == action or "stop" == action or "restart" == action or "rm" == action then
|
||||
cmd = string.format("\"%s\" %s", script_path, action)
|
||||
end
|
||||
if cmd then
|
||||
if luci.sys.call("/etc/init.d/tasks task_add " .. task_id .. " " .. luci.util.shellquote(cmd) .. " >/dev/null 2>&1") ~= 0 then
|
||||
self.task_start_failed = true
|
||||
self.message = translate("Config saved, but apply failed")
|
||||
end
|
||||
else
|
||||
self.message = translate("Unknown command: ") .. action
|
||||
end
|
||||
if self.message then
|
||||
self.auto_show_task = false
|
||||
end
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
||||
return taskd
|
@ -1,56 +0,0 @@
|
||||
|
||||
<% if self.task_start_failed then %>
|
||||
<div class="alert-message warning"><%:Another task running, try again later.%> <a href="javascript:void(taskd.show_log('<%=self.task_id%>'))"><%:Click here to check running task%></a></div>
|
||||
<% end %>
|
||||
|
||||
<%+cbi/map%>
|
||||
<%
|
||||
local task_running = false
|
||||
local taskd = require "luci.model.tasks"
|
||||
local status = taskd.status(self.task_id)
|
||||
task_running = status.running
|
||||
-%>
|
||||
<div class="cbi-page-actions control-group">
|
||||
<%
|
||||
if not task_running then
|
||||
%>
|
||||
<%
|
||||
local util = require "luci.util"
|
||||
local container_status = util.trim(util.exec(self.script_path.." status"))
|
||||
local container_install = (string.len(container_status) > 0)
|
||||
local container_running = container_status == "running"
|
||||
if container_install then
|
||||
-%>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Upgrade%>/<%:Apply%>" onclick="cbi_submit(this, 'cbi.apply', 'upgrade')" />
|
||||
<%
|
||||
if container_running then
|
||||
-%>
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Stop%>" onclick="cbi_submit(this, 'cbi.apply', 'stop')" />
|
||||
|
||||
<input class="btn cbi-button cbi-button-reload" type="button" value="<%:Restart%>" onclick="cbi_submit(this, 'cbi.apply', 'restart')" />
|
||||
<% else %>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Start%>" onclick="cbi_submit(this, 'cbi.apply', 'start')" />
|
||||
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Remove%>" onclick="cbi_submit(this, 'cbi.apply', 'rm')" />
|
||||
<% end
|
||||
else %>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Install%>" onclick="cbi_submit(this, 'cbi.apply', 'install')" />
|
||||
<% end
|
||||
else
|
||||
%>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Task Running%>…" onclick="taskd.show_log('<%=self.task_id%>')" />
|
||||
<%
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
|
||||
<%+tasks/embed%>
|
||||
<%
|
||||
if self.auto_show_task and task_running then
|
||||
-%>
|
||||
<script>
|
||||
taskd.show_log("<%=self.task_id%>");
|
||||
</script>
|
||||
<%
|
||||
end
|
||||
%>
|
@ -1,34 +0,0 @@
|
||||
<%+xterm/embed%>
|
||||
<link rel="stylesheet" href="<%=resource%>/tasks/tasks.css<%# ?v=PKG_VERSION %>">
|
||||
<script src="<%=resource%>/tasks/tasks.js<%# ?v=PKG_VERSION %>"></script>
|
||||
<%
|
||||
local i18n = {}
|
||||
local function tr(str)
|
||||
i18n[str]=translate(str)
|
||||
end
|
||||
tr("Stop running task?")
|
||||
tr("Stopped at:")
|
||||
tr("Finished at:")
|
||||
tr("Failed at:")
|
||||
tr("Lost login status")
|
||||
tr("Fetch log failed, retrying...")
|
||||
tr("Task does not exist or has been deleted")
|
||||
-%>
|
||||
<script>
|
||||
window.taskd.csrfToken="<%=token%>";
|
||||
window.taskd.i18n=<% luci.http.write_json(i18n) %>;
|
||||
window.taskd.dialog_template=`
|
||||
<div id="tasks_dialog">
|
||||
<div class="dialog-title-bar">
|
||||
<span class="dialog-title" id="tasks_id"></span>
|
||||
<span class="dialog-icons">
|
||||
<span class="dialog-icon dialog-icon-close" title="<%:Stop and Remove%>"></span>
|
||||
<span class="dialog-icon dialog-icon-min" title="<%:Hide%>"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<div id="tasks_xterm_log"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
</script>
|
@ -1,15 +0,0 @@
|
||||
clean:
|
||||
compile:
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_NAME:=luci-lib-dummy
|
||||
INCLUDE_DIR:=./dummy
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
install:
|
||||
mkdir -p "$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n"
|
||||
$(foreach lang,$(LUCI_LANGUAGES),$(foreach po,$(wildcard ${CURDIR}/po/$(lang)/*.po), \
|
||||
po2lmo $(po) \
|
||||
$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n/$(basename $(notdir $(po))).$(lang).lmo;))
|
@ -1,2 +0,0 @@
|
||||
define BuildPackage
|
||||
endef
|
@ -1,41 +0,0 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Stop running task?"
|
||||
msgstr "删除运行中的任务?"
|
||||
|
||||
msgid "Finished at:"
|
||||
msgstr "完成于:"
|
||||
|
||||
msgid "Failed at:"
|
||||
msgstr "失败于:"
|
||||
|
||||
msgid "Lost login status"
|
||||
msgstr "丢失登陆状态"
|
||||
|
||||
msgid "Fetch log failed, retrying..."
|
||||
msgstr "拉取日志失败,正在重试..."
|
||||
|
||||
msgid "Task does not exist or has been deleted"
|
||||
msgstr "任务不存在或已删除"
|
||||
|
||||
msgid "Stop and Remove"
|
||||
msgstr "停止并删除"
|
||||
|
||||
msgid "Hide"
|
||||
msgstr "隐藏"
|
||||
|
||||
msgid "Config saved, but apply failed"
|
||||
msgstr "配置已保存,但应用失败"
|
||||
|
||||
msgid "Unknown command: "
|
||||
msgstr "未知命令:"
|
||||
|
||||
msgid "Another task running, try again later."
|
||||
msgstr "已有后台任务运行中,请稍后重试。"
|
||||
|
||||
msgid "Click here to check running task"
|
||||
msgstr "点此查看运行中的任务"
|
||||
|
||||
msgid "Task Running"
|
||||
msgstr "任务执行中"
|
@ -1,21 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2017-2019, The xterm.js authors (MIT License)
|
||||
# Copyright (c) 2014-2017, SourceLair, Private Company (www.sourcelair.com) (MIT License)
|
||||
# Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
#
|
||||
# This is free software, licensed under the MIT License.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Xterm.js library
|
||||
LUCI_DEPENDS:=
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_VERSION:=4.18.0
|
||||
PKG_RELEASE:=
|
||||
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
@ -1,180 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* https://github.com/chjj/term.js
|
||||
* @license MIT
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Originally forked from (with the author's permission):
|
||||
* Fabrice Bellard's javascript vt100 for jslinux:
|
||||
* http://bellard.org/jslinux/
|
||||
* Copyright (c) 2011 Fabrice Bellard
|
||||
* The original design remains. The terminal itself
|
||||
* has been extended to include xterm CSI codes, among
|
||||
* other features.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default styles for xterm.js
|
||||
*/
|
||||
|
||||
.xterm {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.xterm.focus,
|
||||
.xterm:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.xterm .xterm-helpers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/**
|
||||
* The z-index of the helpers must be higher than the canvases in order for
|
||||
* IMEs to appear on top.
|
||||
*/
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.xterm .xterm-helper-textarea {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
left: -9999em;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: -5;
|
||||
/** Prevent wrapping so the IME appears against the textarea at the correct position */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.xterm .composition-view {
|
||||
/* TODO: Composition position got messed up somewhere */
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
display: none;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.xterm .composition-view.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
/* On OS X this is required in order for the scroll bar to appear fully opaque */
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-scroll-area {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.xterm-char-measure-element {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -9999em;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.xterm {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.xterm.enable-mouse-events {
|
||||
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm.xterm-cursor-pointer,
|
||||
.xterm .xterm-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.xterm.column-select.focus {
|
||||
/* Column selection mode */
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.xterm .xterm-accessibility,
|
||||
.xterm .xterm-message {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.xterm .live-region {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.xterm-dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.xterm-underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.xterm-strikethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.xterm-screen .xterm-decoration-container .xterm-decoration {
|
||||
z-index: 6;
|
||||
position: absolute;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
|
||||
<link rel="stylesheet" href="<%=resource%>/xterm/xterm.css<%# ?v=PKG_VERSION %>">
|
||||
<script src="<%=resource%>/xterm/xterm.js<%# ?v=PKG_VERSION %>"></script>
|
@ -1,41 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2022 jjm2473 <jjm2473@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the MIT License.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
|
||||
PKG_NAME:=taskd
|
||||
PKG_VERSION:=1.0.3
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Simple Task Manager
|
||||
DEPENDS:=+procd +script-utils +coreutils-stty
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
Simple Task Manager based on procd
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec
|
||||
$(INSTALL_BIN) ./files/tasks.init $(1)/etc/init.d/tasks
|
||||
$(INSTALL_BIN) ./files/taskd.sh $(1)/usr/libexec/taskd
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
TASK_ID="$1"
|
||||
TASK_CMD="$2"
|
||||
|
||||
exec </dev/null >>"/var/log/tasks/$TASK_ID.log" 2>&1
|
||||
|
||||
export HOME=/root
|
||||
export TERM=xterm-256color
|
||||
|
||||
exec script -efqc 'onexit() {
|
||||
/etc/init.d/tasks _task_onstop "'"$TASK_ID"'" "$?"
|
||||
}
|
||||
trap onexit EXIT;
|
||||
stty cols 80 rows 24;
|
||||
'"$TASK_CMD" /dev/null
|
@ -1,157 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2022 jjm2473@gmail.com
|
||||
|
||||
USE_PROCD=1
|
||||
START=49
|
||||
|
||||
extra_command "task_add" "<task_id> <task_cmd> [<time_wait>] Add and run a task, time_wait is wait time before auto delete stopped task, in seconds, -1 means forever"
|
||||
extra_command "task_del" "<task_id> Stop and delete task"
|
||||
extra_command "task_status" "[<task_id>] Dump task status, dump all tasks if no task_id specified"
|
||||
extra_command "task_gc" "Auto delete exipred (stopped and after timw_wait) tasks"
|
||||
extra_command "_task_onstop" "<task_id> Update stop time, for internal usage"
|
||||
|
||||
_task_add() {
|
||||
local task_id="${1}"
|
||||
local task_cmd="${2}"
|
||||
local time_wait="${3}"
|
||||
> "/var/log/tasks/$task_id.log"
|
||||
procd_open_instance "$task_id"
|
||||
procd_set_param data start=`date +'%s'` time_wait="$time_wait"
|
||||
procd_set_param command sh -c "exec /usr/libexec/taskd '$task_id' \"\$0\"" "$task_cmd"
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
task_add() {
|
||||
local task_id="${1}"
|
||||
local task_cmd="${2}"
|
||||
local time_wait="${3}"
|
||||
[ -z "$task_id" -o -z "$task_cmd" ] && return 127
|
||||
|
||||
if service_running "$task_id"; then
|
||||
echo "already running" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! mkdir -p /var/log/tasks; then
|
||||
echo "create /var/log/tasks failed!" >&2
|
||||
return 1
|
||||
fi
|
||||
rc_procd _task_add "$task_id" "$task_cmd" "$time_wait"
|
||||
return 0
|
||||
}
|
||||
|
||||
_task_del() {
|
||||
local service="${1}"
|
||||
local task_id="${2}"
|
||||
procd_kill "$service" "$task_id"
|
||||
> "/var/log/tasks/$task_id.log"
|
||||
rm -f "/var/log/tasks/$task_id.log"
|
||||
}
|
||||
|
||||
task_del() {
|
||||
local task_id="${1}"
|
||||
[ -z "$task_id" ] && return 127
|
||||
procd_lock
|
||||
_task_del "$(basename ${basescript:-$initscript})" "$task_id"
|
||||
if [ "$(_task_status "$task_id" | jsonfilter -e '$.running' 2>/dev/null)" = "true" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
_task_status() {
|
||||
local service="$(basename ${basescript:-$initscript})"
|
||||
local instance="$1"
|
||||
local data
|
||||
|
||||
json_init
|
||||
json_add_string name "$service"
|
||||
|
||||
data=$(_procd_ubus_call list | jsonfilter -e '@["'"$service"'"]')
|
||||
[ -z "$data" ] && return 1
|
||||
|
||||
data=$(echo "$data" | jsonfilter -e '$.instances')
|
||||
if [ -z "$data" ]; then
|
||||
if [ -z "$instance" ]; then
|
||||
echo "{}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$instance" ]; then
|
||||
echo "$data"
|
||||
else
|
||||
instance="\"$instance\""
|
||||
echo "$data" | jsonfilter -e '$['"$instance"']'
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
task_status() {
|
||||
local task_id="${1}"
|
||||
_task_status "$task_id"
|
||||
}
|
||||
|
||||
task_gc() {
|
||||
local service="$(basename ${basescript:-$initscript})"
|
||||
local task_id instance time_wait
|
||||
local data
|
||||
|
||||
json_init
|
||||
[ -n "$service" ] && json_add_string name "$service"
|
||||
|
||||
data=$(_procd_ubus_call list | jsonfilter -e '@["'"$service"'"]')
|
||||
[ -z "$data" ] && return 1
|
||||
|
||||
data=$(echo "$data" | jsonfilter -e '$.instances')
|
||||
[ -z "$data" ] && return 1
|
||||
|
||||
procd_lock
|
||||
|
||||
ls /var/log/tasks/ | sed 's/.log$//g' | while read task_id; do
|
||||
instance=$(echo "$data" | jsonfilter -e '$["'"$task_id"'"]')
|
||||
[ "$(echo "$instance" | jsonfilter -e '$.running')" = "false" ] || continue
|
||||
time_wait=$(echo "$instance" | jsonfilter -e '$.data.time_wait')
|
||||
[ "$time_wait" = "-1" ] && continue
|
||||
[ $(($(date +'%s' -r "/var/log/tasks/$task_id.log") + ${time_wait:-0})) -lt `date +'%s'` ] && _task_del "$service" "$task_id"
|
||||
done
|
||||
}
|
||||
|
||||
_insert_exit() {
|
||||
local exit_code="$2"
|
||||
eval "`jshn -r "$1" | grep -v json_init`"
|
||||
json_select data || {
|
||||
_procd_set_param data stop=`date +'%s'` exit_code="$exit_code"
|
||||
return
|
||||
}
|
||||
json_add_string stop `date +'%s'`
|
||||
json_add_string exit_code "$exit_code"
|
||||
json_select ..
|
||||
}
|
||||
|
||||
_task_exit() {
|
||||
local task_id="$1"
|
||||
local exit_code="$2"
|
||||
local inst_json="$3"
|
||||
|
||||
_procd_call json_add_object "$task_id"
|
||||
_procd_call _insert_exit "$inst_json" "$exit_code"
|
||||
_procd_call json_close_object
|
||||
}
|
||||
|
||||
_task_onstop() {
|
||||
local task_id="${1}"
|
||||
local exit_code="${2}"
|
||||
[ -z "$task_id" ] && return 127
|
||||
local service="$(basename ${basescript:-$initscript})"
|
||||
|
||||
json_init
|
||||
json_add_string name "$service"
|
||||
data=$(_procd_ubus_call list | jsonfilter -e '@["'"$service"'"].instances["'"$task_id"'"]')
|
||||
[ -z "$data" ] && return 1
|
||||
json_cleanup
|
||||
|
||||
rc_procd _task_exit "$task_id" "$exit_code" "$data"
|
||||
}
|
Before Width: | Height: | Size: 1.2 MiB |
@ -1,377 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: istore 0.1\n"
|
||||
"Last-Translator: jjm2473\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/components/app/index.vue:24
|
||||
msgid "%{ num } download"
|
||||
msgid_plural "%{ num } downloads"
|
||||
msgstr[0] "%{ num } download"
|
||||
msgstr[1] "%{ num } downloads"
|
||||
|
||||
#: src/components/app/index.vue:31
|
||||
msgid "%{ num } like"
|
||||
msgid_plural "%{ num } likes"
|
||||
msgstr[0] "%{ num } like"
|
||||
msgstr[1] "%{ num } likes"
|
||||
|
||||
#: src/components/tabs/index.vue:27
|
||||
msgid "all app"
|
||||
msgstr "all app"
|
||||
|
||||
#: src/pages/maintance/index.vue:8
|
||||
msgid "app backup"
|
||||
msgstr "app backup"
|
||||
|
||||
#: src/components/app/index.vue:179
|
||||
msgid "are you sure you want to uninstall %{name}?"
|
||||
msgstr "are you sure you want to uninstall %{name}?"
|
||||
|
||||
#: src/components/app/index.vue:50
|
||||
msgid "author"
|
||||
msgstr "author"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:42
|
||||
#: src/pages/maintance/localBackup.vue:208
|
||||
msgid "backup fail"
|
||||
msgstr "backup fail"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:18
|
||||
#: src/pages/maintance/localBackup.vue:34
|
||||
msgid "backup now"
|
||||
msgstr "backup now"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:62
|
||||
msgid ""
|
||||
"backup now backs up installed software (unlimited installation sources) to "
|
||||
"external storage"
|
||||
msgstr ""
|
||||
"backup now backs up installed software (unlimited installation sources) to "
|
||||
"external storage"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:9
|
||||
msgid "backup now will download a list of iStore installed software"
|
||||
msgstr "backup now will download a list of iStore installed software"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:41
|
||||
#: src/pages/maintance/localBackup.vue:200
|
||||
msgid "backup success"
|
||||
msgstr "backup success"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:40
|
||||
#: src/pages/maintance/localBackup.vue:195
|
||||
msgid "backuping"
|
||||
msgstr "backuping"
|
||||
|
||||
#: src/pages/store/components/sort.vue:24
|
||||
msgid "By download"
|
||||
msgstr "By download"
|
||||
|
||||
#: src/pages/store/components/sort.vue:28
|
||||
msgid "By rating"
|
||||
msgstr "By rating"
|
||||
|
||||
#: src/pages/maintance/update.vue:4
|
||||
msgid "checking for latest version"
|
||||
msgstr "checking for latest version"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:22
|
||||
msgid "choose"
|
||||
msgstr "choose"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:41
|
||||
msgid "choose backup file"
|
||||
msgstr "choose backup file"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:43
|
||||
msgid "click to download"
|
||||
msgstr "click to download"
|
||||
|
||||
#: src/pages/maintance/update.vue:11
|
||||
msgid "click to update"
|
||||
msgstr "click to update"
|
||||
|
||||
#: src/components/app/index.vue:131 src/components/app/index.vue:154
|
||||
#: src/components/app/index.vue:188 src/components/toast/index.vue:3
|
||||
#: src/pages/upload/index.vue:86
|
||||
msgid "closed"
|
||||
msgstr "closed"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:26
|
||||
msgid "customize"
|
||||
msgstr "customize"
|
||||
|
||||
#: src/pages/store/components/sort.vue:20 src/pages/store/components/tag.vue:8
|
||||
msgid "default"
|
||||
msgstr "default"
|
||||
|
||||
#: src/components/app/index.vue:130 src/components/app/index.vue:153
|
||||
#: src/components/app/index.vue:187 src/pages/upload/index.vue:85
|
||||
msgid "do not refresh this page during plugin installation/uninstallation"
|
||||
msgstr "do not refresh this page during plugin installation/uninstallation"
|
||||
|
||||
#: src/plugins/i18n/index.ts:38
|
||||
msgid "download"
|
||||
msgstr "Download"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:4 src/pages/maintance/localBackup.vue:4
|
||||
msgid "explain"
|
||||
msgstr "explain"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:16
|
||||
msgid "external storage directory"
|
||||
msgstr "external storage directory"
|
||||
|
||||
#: src/pages/upload/index.vue:6
|
||||
msgid "from this page, you can upload plugin packages to install plugins"
|
||||
msgstr "from this page, you can upload plugin packages to install plugins"
|
||||
|
||||
#: src/components/app/index.vue:6
|
||||
msgid "Icon is gone"
|
||||
msgstr "Icon is gone"
|
||||
|
||||
#: src/components/app/index.vue:83
|
||||
msgid "install"
|
||||
msgstr "install"
|
||||
|
||||
#: src/components/app/index.vue:172
|
||||
msgid "installation failed, error code"
|
||||
msgstr "installation failed, error code"
|
||||
|
||||
#: src/components/app/index.vue:169
|
||||
msgid "installation is complete, please close the current window"
|
||||
msgstr "installation is complete, please close the current window"
|
||||
|
||||
#: src/components/tabs/index.vue:23
|
||||
msgid "installed"
|
||||
msgstr "installed"
|
||||
|
||||
#. `正在安装插件`,
|
||||
#: src/components/app/index.vue:152
|
||||
msgid "installing plugin"
|
||||
msgstr "installing plugin"
|
||||
|
||||
#: src/pages/maintance/update.vue:9
|
||||
msgid "last version"
|
||||
msgstr "last version"
|
||||
|
||||
#: src/pages/maintance/index.vue:13
|
||||
msgid "light backup"
|
||||
msgstr "light backup"
|
||||
|
||||
#: src/components/app/index.vue:40
|
||||
msgid "like"
|
||||
msgstr "like"
|
||||
|
||||
#: src/components/app/index.vue:37
|
||||
msgid "liked"
|
||||
msgstr "liked"
|
||||
|
||||
#: src/pages/store/components/apps.vue:7
|
||||
msgid "loading data"
|
||||
msgstr "loading data"
|
||||
|
||||
#: src/pages/maintance/index.vue:18
|
||||
msgid "local backup"
|
||||
msgstr "local backup"
|
||||
|
||||
#: src/components/tabs/index.vue:35
|
||||
msgid "maintain"
|
||||
msgstr "maintain"
|
||||
|
||||
#: src/components/tabs/index.vue:31
|
||||
msgid "manual install"
|
||||
msgstr "manual install"
|
||||
|
||||
#: src/plugins/i18n/index.ts:42
|
||||
msgid "monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: src/plugins/i18n/index.ts:40
|
||||
msgid "multimedia"
|
||||
msgstr "Multimedia"
|
||||
|
||||
#: src/plugins/i18n/index.ts:41
|
||||
msgid "nas"
|
||||
msgstr "NAS"
|
||||
|
||||
#: src/plugins/i18n/index.ts:36
|
||||
msgid "net"
|
||||
msgstr "Net"
|
||||
|
||||
#: src/plugins/i18n/index.ts:44
|
||||
msgid "networking"
|
||||
msgstr "Networking"
|
||||
|
||||
#: src/pages/upload/index.vue:14 src/pages/upload/index.vue:15
|
||||
msgid "no files selected"
|
||||
msgstr "no files selected"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:12
|
||||
msgid "no internet required for recovery"
|
||||
msgstr "no internet required for recovery"
|
||||
|
||||
#: src/pages/upload/index.vue:4
|
||||
msgid "offline install"
|
||||
msgstr "offline install"
|
||||
|
||||
#: src/pages/upload/index.vue:101
|
||||
msgid "offline installation failed with error code"
|
||||
msgstr "offline installation failed with error code"
|
||||
|
||||
#: src/pages/upload/index.vue:98
|
||||
msgid "offline installation is successful, please close the current window"
|
||||
msgstr "offline installation is successful, please close the current window"
|
||||
|
||||
#: src/components/app/index.vue:74
|
||||
msgid "open"
|
||||
msgstr "open"
|
||||
|
||||
#: src/pages/store/components/sort.vue:3
|
||||
msgid "order"
|
||||
msgstr "order"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:29
|
||||
msgid "please enter an absolute path starting with %{name}"
|
||||
msgstr "please enter an absolute path starting with %{name}"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:140
|
||||
msgid "please enter the path, give up the input, please clear the input box"
|
||||
msgstr "please enter the path, give up the input, please clear the input box"
|
||||
|
||||
#: src/pages/store/components/search.vue:6
|
||||
msgid "please enter the search keyword"
|
||||
msgstr "please enter the search keyword"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:158
|
||||
#: src/pages/maintance/localBackup.vue:192
|
||||
msgid "please fill in the external storage directory"
|
||||
msgstr "please fill in the external storage directory"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:225
|
||||
msgid "please select a backup file to restore"
|
||||
msgstr "please select a backup file to restore"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:21
|
||||
#: src/pages/maintance/localBackup.vue:36
|
||||
msgid "restore backup"
|
||||
msgstr "restore backup"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:47
|
||||
msgid "restore now"
|
||||
msgstr "restore now"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:228
|
||||
msgid "restoring backup"
|
||||
msgstr "restoring backup"
|
||||
|
||||
#: src/pages/upload/index.vue:17
|
||||
msgid "select or drag and drop files"
|
||||
msgstr "select or drag and drop files"
|
||||
|
||||
#: src/plugins/i18n/index.ts:39
|
||||
msgid "service"
|
||||
msgstr "Service"
|
||||
|
||||
#: src/pages/upload/index.vue:9
|
||||
msgid "support .ipk plug-in, .run self-extracting format"
|
||||
msgstr "support .ipk plug-in, .run self-extracting format"
|
||||
|
||||
#: src/plugins/i18n/index.ts:43
|
||||
msgid "system"
|
||||
msgstr "System"
|
||||
|
||||
#: src/pages/store/components/tag.vue:4
|
||||
msgid "tag"
|
||||
msgstr "Tag"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:241
|
||||
msgid "the backup was restored fail"
|
||||
msgstr "the backup was restored fail"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:233
|
||||
msgid "the backup was restored success"
|
||||
msgstr "the backup was restored success"
|
||||
|
||||
#: src/pages/maintance/update.vue:13
|
||||
msgid "the is last version"
|
||||
msgstr "the is last version"
|
||||
|
||||
#: src/components/app/index.vue:141
|
||||
msgid "the update is success, please close the current window"
|
||||
msgstr "the update is success, please close the current window"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:168
|
||||
msgid "there are no backup files in this path"
|
||||
msgstr "there are no backup files in this path"
|
||||
|
||||
#: src/plugins/i18n/index.ts:37
|
||||
msgid "tool"
|
||||
msgstr "Tool"
|
||||
|
||||
#: src/components/app/index.vue:77 src/components/app/index.vue:78
|
||||
msgid "uninstall"
|
||||
msgstr "uninstall"
|
||||
|
||||
#: src/components/app/index.vue:201
|
||||
msgid "uninstall failed, error code"
|
||||
msgstr "uninstall failed, error code"
|
||||
|
||||
#: src/components/app/index.vue:198
|
||||
msgid "uninstallation succeeded, please close the current window"
|
||||
msgstr "uninstallation succeeded, please close the current window"
|
||||
|
||||
#: src/components/app/index.vue:186
|
||||
msgid "uninstalling plugin"
|
||||
msgstr "uninstalling plugin"
|
||||
|
||||
#: src/components/app/index.vue:54
|
||||
msgid "update date"
|
||||
msgstr "update date"
|
||||
|
||||
#: src/pages/maintance/update.vue:46
|
||||
msgid "update error"
|
||||
msgstr "update error"
|
||||
|
||||
#: src/components/app/index.vue:144
|
||||
msgid "update failed with error code"
|
||||
msgstr "update failed with error code"
|
||||
|
||||
#: src/pages/maintance/update.vue:37
|
||||
msgid "update success"
|
||||
msgstr "update success"
|
||||
|
||||
#: src/pages/maintance/update.vue:32
|
||||
msgid "updateing"
|
||||
msgstr "updateing"
|
||||
|
||||
#. `正在更新插件`,
|
||||
#: src/components/app/index.vue:129
|
||||
msgid "updating plugin"
|
||||
msgstr "updating plugin"
|
||||
|
||||
#: src/components/app/index.vue:68 src/pages/maintance/index.vue:4
|
||||
msgid "upgrade"
|
||||
msgstr "upgrade"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:13
|
||||
msgid "upload software list and install from iStore when restoring backup"
|
||||
msgstr "upload software list and install from iStore when restoring backup"
|
||||
|
||||
#: src/pages/upload/index.vue:84
|
||||
msgid "uploading plugin"
|
||||
msgstr "uploading plugin"
|
||||
|
||||
#: src/components/app/index.vue:61
|
||||
msgid "website"
|
||||
msgstr "website"
|
||||
|
||||
#: src/components/app/index.vue:223
|
||||
msgid "you have already liked"
|
||||
msgstr "you have already liked"
|
@ -1,375 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
#: src/components/app/index.vue:24
|
||||
msgid "%{ num } download"
|
||||
msgid_plural "%{ num } downloads"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/components/app/index.vue:31
|
||||
msgid "%{ num } like"
|
||||
msgid_plural "%{ num } likes"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/components/tabs/index.vue:27
|
||||
msgid "all app"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/index.vue:8
|
||||
msgid "app backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:179
|
||||
msgid "are you sure you want to uninstall %{name}?"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:50
|
||||
msgid "author"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:42
|
||||
#: src/pages/maintance/localBackup.vue:208
|
||||
msgid "backup fail"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:18
|
||||
#: src/pages/maintance/localBackup.vue:34
|
||||
msgid "backup now"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:62
|
||||
msgid "backup now backs up installed software (unlimited installation sources) to external storage"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:9
|
||||
msgid "backup now will download a list of iStore installed software"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:41
|
||||
#: src/pages/maintance/localBackup.vue:200
|
||||
msgid "backup success"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:40
|
||||
#: src/pages/maintance/localBackup.vue:195
|
||||
msgid "backuping"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/sort.vue:24
|
||||
msgid "By download"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/sort.vue:28
|
||||
msgid "By rating"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:4
|
||||
msgid "checking for latest version"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:22
|
||||
msgid "choose"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:41
|
||||
msgid "choose backup file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:43
|
||||
msgid "click to download"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:11
|
||||
msgid "click to update"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:131
|
||||
#: src/components/app/index.vue:154
|
||||
#: src/components/app/index.vue:188
|
||||
#: src/components/toast/index.vue:3
|
||||
#: src/pages/upload/index.vue:86
|
||||
msgid "closed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:26
|
||||
msgid "customize"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/sort.vue:20
|
||||
#: src/pages/store/components/tag.vue:8
|
||||
msgid "default"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:130
|
||||
#: src/components/app/index.vue:153
|
||||
#: src/components/app/index.vue:187
|
||||
#: src/pages/upload/index.vue:85
|
||||
msgid "do not refresh this page during plugin installation/uninstallation"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:38
|
||||
msgid "download"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:4
|
||||
#: src/pages/maintance/localBackup.vue:4
|
||||
msgid "explain"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:16
|
||||
msgid "external storage directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:6
|
||||
msgid "from this page, you can upload plugin packages to install plugins"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:6
|
||||
msgid "Icon is gone"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:83
|
||||
msgid "install"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:172
|
||||
msgid "installation failed, error code"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:169
|
||||
msgid "installation is complete, please close the current window"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tabs/index.vue:23
|
||||
msgid "installed"
|
||||
msgstr ""
|
||||
|
||||
#. `正在安装插件`,
|
||||
#: src/components/app/index.vue:152
|
||||
msgid "installing plugin"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:9
|
||||
msgid "last version"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/index.vue:13
|
||||
msgid "light backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:40
|
||||
msgid "like"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:37
|
||||
msgid "liked"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/apps.vue:7
|
||||
msgid "loading data"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/index.vue:18
|
||||
msgid "local backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tabs/index.vue:35
|
||||
msgid "maintain"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tabs/index.vue:31
|
||||
msgid "manual install"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:42
|
||||
msgid "monitor"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:40
|
||||
msgid "multimedia"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:41
|
||||
msgid "nas"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:36
|
||||
msgid "net"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:44
|
||||
msgid "networking"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:14
|
||||
#: src/pages/upload/index.vue:15
|
||||
msgid "no files selected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:12
|
||||
msgid "no internet required for recovery"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:4
|
||||
msgid "offline install"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:101
|
||||
msgid "offline installation failed with error code"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:98
|
||||
msgid "offline installation is successful, please close the current window"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:74
|
||||
msgid "open"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/sort.vue:3
|
||||
msgid "order"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:29
|
||||
msgid "please enter an absolute path starting with %{name}"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:140
|
||||
msgid "please enter the path, give up the input, please clear the input box"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/search.vue:6
|
||||
msgid "please enter the search keyword"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:158
|
||||
#: src/pages/maintance/localBackup.vue:192
|
||||
msgid "please fill in the external storage directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:225
|
||||
msgid "please select a backup file to restore"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:21
|
||||
#: src/pages/maintance/localBackup.vue:36
|
||||
msgid "restore backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:47
|
||||
msgid "restore now"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:228
|
||||
msgid "restoring backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:17
|
||||
msgid "select or drag and drop files"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:39
|
||||
msgid "service"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:9
|
||||
msgid "support .ipk plug-in, .run self-extracting format"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:43
|
||||
msgid "system"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/store/components/tag.vue:4
|
||||
msgid "tag"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:241
|
||||
msgid "the backup was restored fail"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:233
|
||||
msgid "the backup was restored success"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:13
|
||||
msgid "the is last version"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:141
|
||||
msgid "the update is success, please close the current window"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:168
|
||||
msgid "there are no backup files in this path"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/i18n/index.ts:37
|
||||
msgid "tool"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:77
|
||||
#: src/components/app/index.vue:78
|
||||
msgid "uninstall"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:201
|
||||
msgid "uninstall failed, error code"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:198
|
||||
msgid "uninstallation succeeded, please close the current window"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:186
|
||||
msgid "uninstalling plugin"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:54
|
||||
msgid "update date"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:46
|
||||
msgid "update error"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:144
|
||||
msgid "update failed with error code"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:37
|
||||
msgid "update success"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/update.vue:32
|
||||
msgid "updateing"
|
||||
msgstr ""
|
||||
|
||||
#. `正在更新插件`,
|
||||
#: src/components/app/index.vue:129
|
||||
msgid "updating plugin"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:68
|
||||
#: src/pages/maintance/index.vue:4
|
||||
msgid "upgrade"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:13
|
||||
msgid "upload software list and install from iStore when restoring backup"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/upload/index.vue:84
|
||||
msgid "uploading plugin"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:61
|
||||
msgid "website"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/app/index.vue:223
|
||||
msgid "you have already liked"
|
||||
msgstr ""
|
@ -1,374 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: istore 0.1\n"
|
||||
"Last-Translator: jjm2473\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: zh-cn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/components/app/index.vue:24
|
||||
msgid "%{ num } download"
|
||||
msgid_plural "%{ num } downloads"
|
||||
msgstr[0] "%{ num } 次下载"
|
||||
msgstr[1] "%{ num } 次下载"
|
||||
|
||||
#: src/components/app/index.vue:31
|
||||
msgid "%{ num } like"
|
||||
msgid_plural "%{ num } likes"
|
||||
msgstr[0] "%{ num } 次点赞"
|
||||
msgstr[1] "%{ num } 次点赞"
|
||||
|
||||
#: src/components/tabs/index.vue:27
|
||||
msgid "all app"
|
||||
msgstr "全部软件"
|
||||
|
||||
#: src/pages/maintance/index.vue:8
|
||||
msgid "app backup"
|
||||
msgstr "软件备份"
|
||||
|
||||
#: src/components/app/index.vue:179
|
||||
msgid "are you sure you want to uninstall %{name}?"
|
||||
msgstr "确定要卸载 %{name} 吗?"
|
||||
|
||||
#: src/components/app/index.vue:50
|
||||
msgid "author"
|
||||
msgstr "作者"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:42
|
||||
#: src/pages/maintance/localBackup.vue:208
|
||||
msgid "backup fail"
|
||||
msgstr "备份失败"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:18
|
||||
#: src/pages/maintance/localBackup.vue:34
|
||||
msgid "backup now"
|
||||
msgstr "立即备份"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:62
|
||||
msgid ""
|
||||
"backup now backs up installed software (unlimited installation sources) to "
|
||||
"external storage"
|
||||
msgstr "立即备份将备份已安装软件(不限安装来源)到外部存储"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:9
|
||||
msgid "backup now will download a list of iStore installed software"
|
||||
msgstr "立即备份将下载iStore已安装的软件列表"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:41
|
||||
#: src/pages/maintance/localBackup.vue:200
|
||||
msgid "backup success"
|
||||
msgstr "备份成功"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:40
|
||||
#: src/pages/maintance/localBackup.vue:195
|
||||
msgid "backuping"
|
||||
msgstr "正在备份"
|
||||
|
||||
#: src/pages/store/components/sort.vue:24
|
||||
msgid "By download"
|
||||
msgstr "按下载"
|
||||
|
||||
#: src/pages/store/components/sort.vue:28
|
||||
msgid "By rating"
|
||||
msgstr "按评分"
|
||||
|
||||
#: src/pages/maintance/update.vue:4
|
||||
msgid "checking for latest version"
|
||||
msgstr "正在检查最新版本"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:22
|
||||
msgid "choose"
|
||||
msgstr "请选择"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:41
|
||||
msgid "choose backup file"
|
||||
msgstr "选择备份文件"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:43
|
||||
msgid "click to download"
|
||||
msgstr "点此下载"
|
||||
|
||||
#: src/pages/maintance/update.vue:11
|
||||
msgid "click to update"
|
||||
msgstr "点我更新"
|
||||
|
||||
#: src/components/app/index.vue:131 src/components/app/index.vue:154
|
||||
#: src/components/app/index.vue:188 src/components/toast/index.vue:3
|
||||
#: src/pages/upload/index.vue:86
|
||||
msgid "closed"
|
||||
msgstr "关闭"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:26
|
||||
msgid "customize"
|
||||
msgstr "自定义"
|
||||
|
||||
#: src/pages/store/components/sort.vue:20 src/pages/store/components/tag.vue:8
|
||||
msgid "default"
|
||||
msgstr "默认"
|
||||
|
||||
#: src/components/app/index.vue:130 src/components/app/index.vue:153
|
||||
#: src/components/app/index.vue:187 src/pages/upload/index.vue:85
|
||||
msgid "do not refresh this page during plugin installation/uninstallation"
|
||||
msgstr "插件安装/卸载过程中请勿刷新此页面"
|
||||
|
||||
#: src/plugins/i18n/index.ts:38
|
||||
msgid "download"
|
||||
msgstr "下载"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:4 src/pages/maintance/localBackup.vue:4
|
||||
msgid "explain"
|
||||
msgstr "说明"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:16
|
||||
msgid "external storage directory"
|
||||
msgstr "外部存储目录"
|
||||
|
||||
#: src/pages/upload/index.vue:6
|
||||
msgid "from this page, you can upload plugin packages to install plugins"
|
||||
msgstr "通过本页,你可以上传插件包来安装插件"
|
||||
|
||||
#: src/components/app/index.vue:6
|
||||
msgid "Icon is gone"
|
||||
msgstr "图标出走啦"
|
||||
|
||||
#: src/components/app/index.vue:83
|
||||
msgid "install"
|
||||
msgstr "安装"
|
||||
|
||||
#: src/components/app/index.vue:172
|
||||
msgid "installation failed, error code"
|
||||
msgstr "安装失败,错误码"
|
||||
|
||||
#: src/components/app/index.vue:169
|
||||
msgid "installation is complete, please close the current window"
|
||||
msgstr "安装完成,请关闭当前窗口"
|
||||
|
||||
#: src/components/tabs/index.vue:23
|
||||
msgid "installed"
|
||||
msgstr "已安装"
|
||||
|
||||
#. `正在安装插件`,
|
||||
#: src/components/app/index.vue:152
|
||||
msgid "installing plugin"
|
||||
msgstr "正在安装插件"
|
||||
|
||||
#: src/pages/maintance/update.vue:9
|
||||
msgid "last version"
|
||||
msgstr "最新版本"
|
||||
|
||||
#: src/pages/maintance/index.vue:13
|
||||
msgid "light backup"
|
||||
msgstr "轻量备份"
|
||||
|
||||
#: src/components/app/index.vue:40
|
||||
msgid "like"
|
||||
msgstr "点赞"
|
||||
|
||||
#: src/components/app/index.vue:37
|
||||
msgid "liked"
|
||||
msgstr "已点赞"
|
||||
|
||||
#: src/pages/store/components/apps.vue:7
|
||||
msgid "loading data"
|
||||
msgstr "正在努力的获取数据"
|
||||
|
||||
#: src/pages/maintance/index.vue:18
|
||||
msgid "local backup"
|
||||
msgstr "本地备份"
|
||||
|
||||
#: src/components/tabs/index.vue:35
|
||||
msgid "maintain"
|
||||
msgstr "维护"
|
||||
|
||||
#: src/components/tabs/index.vue:31
|
||||
msgid "manual install"
|
||||
msgstr "手动安装"
|
||||
|
||||
#: src/plugins/i18n/index.ts:42
|
||||
msgid "monitor"
|
||||
msgstr "监控"
|
||||
|
||||
#: src/plugins/i18n/index.ts:40
|
||||
msgid "multimedia"
|
||||
msgstr "多媒体"
|
||||
|
||||
#: src/plugins/i18n/index.ts:41
|
||||
msgid "nas"
|
||||
msgstr "NAS"
|
||||
|
||||
#: src/plugins/i18n/index.ts:36
|
||||
msgid "net"
|
||||
msgstr "网络"
|
||||
|
||||
#: src/plugins/i18n/index.ts:44
|
||||
msgid "networking"
|
||||
msgstr "组网"
|
||||
|
||||
#: src/pages/upload/index.vue:14 src/pages/upload/index.vue:15
|
||||
msgid "no files selected"
|
||||
msgstr "未选择任何文件"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:12
|
||||
msgid "no internet required for recovery"
|
||||
msgstr "恢复时不需要网络"
|
||||
|
||||
#: src/pages/upload/index.vue:4
|
||||
msgid "offline install"
|
||||
msgstr "离线安装"
|
||||
|
||||
#: src/pages/upload/index.vue:101
|
||||
msgid "offline installation failed with error code"
|
||||
msgstr "离线安装失败,错误码"
|
||||
|
||||
#: src/pages/upload/index.vue:98
|
||||
msgid "offline installation is successful, please close the current window"
|
||||
msgstr "离线安装成功,请关闭当前窗口"
|
||||
|
||||
#: src/components/app/index.vue:74
|
||||
msgid "open"
|
||||
msgstr "打开"
|
||||
|
||||
#: src/pages/store/components/sort.vue:3
|
||||
msgid "order"
|
||||
msgstr "排序"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:29
|
||||
msgid "please enter an absolute path starting with %{name}"
|
||||
msgstr "请输入 %{name} 开头的绝对路径"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:140
|
||||
msgid "please enter the path, give up the input, please clear the input box"
|
||||
msgstr "请输入路径,放弃输入请清空输入框"
|
||||
|
||||
#: src/pages/store/components/search.vue:6
|
||||
msgid "please enter the search keyword"
|
||||
msgstr "请输入搜索关键词"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:158
|
||||
#: src/pages/maintance/localBackup.vue:192
|
||||
msgid "please fill in the external storage directory"
|
||||
msgstr "请填写外部存储目录"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:225
|
||||
msgid "please select a backup file to restore"
|
||||
msgstr "请选择要恢复的备份文件"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:21
|
||||
#: src/pages/maintance/localBackup.vue:36
|
||||
msgid "restore backup"
|
||||
msgstr "恢复备份"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:47
|
||||
msgid "restore now"
|
||||
msgstr "立即恢复"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:228
|
||||
msgid "restoring backup"
|
||||
msgstr "正在恢复备份"
|
||||
|
||||
#: src/pages/upload/index.vue:17
|
||||
msgid "select or drag and drop files"
|
||||
msgstr "选择或拖放文件"
|
||||
|
||||
#: src/plugins/i18n/index.ts:39
|
||||
msgid "service"
|
||||
msgstr "服务"
|
||||
|
||||
#: src/pages/upload/index.vue:9
|
||||
msgid "support .ipk plug-in, .run self-extracting format"
|
||||
msgstr "支持 .ipk 插件,.run 自解压格式"
|
||||
|
||||
#: src/plugins/i18n/index.ts:43
|
||||
msgid "system"
|
||||
msgstr "系统"
|
||||
|
||||
#: src/pages/store/components/tag.vue:4
|
||||
msgid "tag"
|
||||
msgstr "标签"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:241
|
||||
msgid "the backup was restored fail"
|
||||
msgstr "恢复备份失败"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:233
|
||||
msgid "the backup was restored success"
|
||||
msgstr "恢复备份成功"
|
||||
|
||||
#: src/pages/maintance/update.vue:13
|
||||
msgid "the is last version"
|
||||
msgstr "当前已经是最新版本"
|
||||
|
||||
#: src/components/app/index.vue:141
|
||||
msgid "the update is success, please close the current window"
|
||||
msgstr "更新成功,请关闭当前窗口"
|
||||
|
||||
#: src/pages/maintance/localBackup.vue:168
|
||||
msgid "there are no backup files in this path"
|
||||
msgstr "此路径下没有备份文件"
|
||||
|
||||
#: src/plugins/i18n/index.ts:37
|
||||
msgid "tool"
|
||||
msgstr "工具"
|
||||
|
||||
#: src/components/app/index.vue:77 src/components/app/index.vue:78
|
||||
msgid "uninstall"
|
||||
msgstr "卸载"
|
||||
|
||||
#: src/components/app/index.vue:201
|
||||
msgid "uninstall failed, error code"
|
||||
msgstr "卸载失败,错误码"
|
||||
|
||||
#: src/components/app/index.vue:198
|
||||
msgid "uninstallation succeeded, please close the current window"
|
||||
msgstr "卸载完成,请关闭当前窗口"
|
||||
|
||||
#: src/components/app/index.vue:186
|
||||
msgid "uninstalling plugin"
|
||||
msgstr "正在卸载插件"
|
||||
|
||||
#: src/components/app/index.vue:54
|
||||
msgid "update date"
|
||||
msgstr "更新日期"
|
||||
|
||||
#: src/pages/maintance/update.vue:46
|
||||
msgid "update error"
|
||||
msgstr "更新失败"
|
||||
|
||||
#: src/components/app/index.vue:144
|
||||
msgid "update failed with error code"
|
||||
msgstr "更新失败,错误代码"
|
||||
|
||||
#: src/pages/maintance/update.vue:37
|
||||
msgid "update success"
|
||||
msgstr "更新成功"
|
||||
|
||||
#: src/pages/maintance/update.vue:32
|
||||
msgid "updateing"
|
||||
msgstr "正在更新中"
|
||||
|
||||
#. `正在更新插件`,
|
||||
#: src/components/app/index.vue:129
|
||||
msgid "updating plugin"
|
||||
msgstr "正在更新插件"
|
||||
|
||||
#: src/components/app/index.vue:68 src/pages/maintance/index.vue:4
|
||||
msgid "upgrade"
|
||||
msgstr "更新"
|
||||
|
||||
#: src/pages/maintance/lightBackup.vue:13
|
||||
msgid "upload software list and install from iStore when restoring backup"
|
||||
msgstr "复备份时上传软件列表并从iStore安装"
|
||||
|
||||
#: src/pages/upload/index.vue:84
|
||||
msgid "uploading plugin"
|
||||
msgstr "正在上传插件"
|
||||
|
||||
#: src/components/app/index.vue:61
|
||||
msgid "website"
|
||||
msgstr "官网"
|
||||
|
||||
#: src/components/app/index.vue:223
|
||||
msgid "you have already liked"
|
||||
msgstr "您已经点赞过啦"
|
@ -1,68 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015-2016 OpenWrt.org
|
||||
# Copyright (C) 2020 jjm2473@gmail.com
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_ARCH_LINKEASE:=$(ARCH)
|
||||
|
||||
PKG_NAME:=linkease
|
||||
PKG_VERSION:=1.2.9
|
||||
PKG_RELEASE:=$(PKG_ARCH_LINKEASE)-2
|
||||
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=http://fw0.koolcenter.com/binary/LinkEase/LinuxStorage/
|
||||
PKG_HASH:=31e3eea526d8328a59e1bfd39e7800cea935d62721958227f40d52b495ce3712
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=LinkEase - the file cloud
|
||||
DEPENDS:=@(arm||x86_64||aarch64) +ffmpeg-remux
|
||||
PKGARCH:=all
|
||||
URL:=https://www.ddnsto.com/linkease/
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
LinkEase is a file cloud
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/linkease
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
[ -f /etc/uci-defaults/linkease ] && /etc/uci-defaults/linkease && rm -f /etc/uci-defaults/linkease
|
||||
fi
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin/linkease-plugins $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/linkease
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/heif-converter.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/heif-converter
|
||||
$(INSTALL_BIN) ./files/linkease-config.sh $(1)/usr/sbin/linkease-config.sh
|
||||
$(INSTALL_BIN) ./files/aria2.sh $(1)/usr/sbin/linkease-plugins/aria2.sh
|
||||
$(INSTALL_CONF) ./files/linkease.config $(1)/etc/config/linkease
|
||||
$(INSTALL_BIN) ./files/linkease.init $(1)/etc/init.d/linkease
|
||||
$(INSTALL_BIN) ./files/linkease.uci-default $(1)/etc/uci-defaults/linkease
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
34
linkease/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# nas-packages-luci
|
||||
luci for [nas-packages](https://github.com/linkease/nas-packages)
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 增加feed源
|
||||
|
||||
```shell
|
||||
echo >> feeds.conf.default
|
||||
echo 'src-git nas https://github.com/linkease/nas-packages.git;master' >> feeds.conf.default
|
||||
echo 'src-git nas_luci https://github.com/linkease/nas-packages-luci.git;main' >> feeds.conf.default
|
||||
./scripts/feeds update nas nas_luci
|
||||
./scripts/feeds install -a -p nas
|
||||
./scripts/feeds install -a -p nas_luci
|
||||
```
|
||||
|
||||
### 集成软件包
|
||||
|
||||
```shell
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
选择软件包
|
||||
```plain
|
||||
LuCI --->
|
||||
3. Applications --->
|
||||
<*> luci-app-ddnsto.................................. LuCI support for ddnsto
|
||||
<*> luci-app-linkease.................................. LuCI support for linkease
|
||||
```
|
||||
|
||||
### 构建固件
|
||||
```shell
|
||||
make
|
||||
```
|
@ -1,134 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
sh_ver="1.0.0"
|
||||
export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin
|
||||
aria2_conf_dir=/var/etc/aria2/
|
||||
#替换成你设备aria2.conf路径
|
||||
aria2_conf=${aria2_conf_dir}/aria2.conf.main
|
||||
#替换成你设备的aria2c路径
|
||||
aria2c=/usr/bin/aria2c
|
||||
Green_font_prefix="\033[32m"
|
||||
Red_font_prefix="\033[31m"
|
||||
Green_background_prefix="\033[42;37m"
|
||||
Red_background_prefix="\033[41;37m"
|
||||
Font_color_suffix="\033[0m"
|
||||
Info="[${Green_font_prefix}信息${Font_color_suffix}]"
|
||||
Error="[${Red_font_prefix}错误${Font_color_suffix}]"
|
||||
Tip="[${Green_font_prefix}注意${Font_color_suffix}]"
|
||||
error_code=11
|
||||
success_code=0
|
||||
|
||||
return_error(){
|
||||
echo 'Content-Type:application/json;charset=utf-8'
|
||||
echo
|
||||
echo "{
|
||||
"\"success\"":$error_code,
|
||||
"\"error\"":"\"$1\"",
|
||||
"\"result"\":null
|
||||
}"
|
||||
exit 1
|
||||
}
|
||||
return_ok(){
|
||||
echo 'Content-Type:application/json;charset=utf-8'
|
||||
echo
|
||||
echo "{
|
||||
"\"success\"":$success_code,
|
||||
"\"error\"":"\"$1\"",
|
||||
"\"result"\":null
|
||||
}"
|
||||
exit 0
|
||||
}
|
||||
return_result(){
|
||||
echo 'Content-Type:application/json;charset=utf-8'
|
||||
echo
|
||||
echo "{
|
||||
"\"success\"":$success_code,
|
||||
"\"error\"":"\"\"",
|
||||
"\"result"\":$1
|
||||
}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
#进程中是否运行aria2
|
||||
check_pid() {
|
||||
PID=$(ps -ef | grep "aria2c" | grep -v grep | grep -v "aria2.sh" | grep -v "init.d" | grep -v "service" | awk '{print $2}')
|
||||
}
|
||||
|
||||
#aria2是否正在运行
|
||||
aria2_work_status(){
|
||||
check_pid
|
||||
# [[ ! -z ${PID} ]] && echo -e "${Error} Aria2 正在运行,请检查 !" && exit 1
|
||||
[[ ! -z ${PID} ]] && return_ok "Aria2正在运行"
|
||||
return_error "Aria2未运行"
|
||||
}
|
||||
|
||||
#检测设备是否安装aria2
|
||||
check_installed_status() {
|
||||
[[ ! -e ${aria2c} ]] && return_error "Aria2 没有安装,请检查 !"
|
||||
[[ ! -e ${aria2_conf} ]] && return_error "Aria2 配置文件不存在,请检查 !"
|
||||
# return_ok "Aria2已安装"
|
||||
}
|
||||
#读取aria2配置信息
|
||||
read_config() {
|
||||
check_installed_status
|
||||
if [[ ! -e ${aria2_conf} ]]; then
|
||||
return_error "Aria2 配置文件不存在,请检查 !"
|
||||
else
|
||||
conf_text=$(cat ${aria2_conf} | grep -v '#')
|
||||
aria2_dir=$(echo -e "${conf_text}" | grep "^dir=" | awk -F "=" '{print $NF}')
|
||||
aria2_port=$(echo -e "${conf_text}" | grep "^rpc-listen-port=" | awk -F "=" '{print $NF}')
|
||||
aria2_passwd=$(echo -e "${conf_text}" | grep "^rpc-secret=" | awk -F "=" '{print $NF}')
|
||||
aria2_bt_port=$(echo -e "${conf_text}" | grep "^listen-port=" | awk -F "=" '{print $NF}')
|
||||
aria2_dht_port=$(echo -e "${conf_text}" | grep "^dht-listen-port=" | awk -F "=" '{print $NF}')
|
||||
|
||||
return_result "{
|
||||
"\"dir"\":"\"$aria2_dir"\",
|
||||
"\"rpc-listen-port"\":"\"$aria2_port"\",
|
||||
"\"rpc-secret"\":"\"$aria2_passwd"\",
|
||||
"\"listen-port"\":"\"$aria2_bt_port"\",
|
||||
"\"dht-listen-port"\":"\"$aria2_dht_port"\"}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
#"Content-Type:text/html;charset=utf-8"
|
||||
#echo
|
||||
|
||||
#SERVER_SOFTWARE = $SERVER_SOFTWARE #服务器软件
|
||||
#SERVER_NAME = $SERVER_NAME #服务器主机名
|
||||
#GATEWAY_INTERFACE = $GATEWAY_INTERFACE #CGI版本
|
||||
#SERVER_PROTOCOL = $SERVER_PROTOCOL #通信使用的协议
|
||||
#SERVER_PORT = $SERVER_PORT #服务器的端口号
|
||||
#REQUEST_METHOD = $REQUEST_METHOD #请求方法(GET/POST/PUT/DELETE..)
|
||||
#HTTP_ACCEPT = $HTTP_ACCEPT #HTTP定义的浏览器能够接受的数据类型
|
||||
#SCRIPT_NAME = $SCRIPT_NAME #当前运行的脚本名称(包含路径)
|
||||
#QUERY_STRING = $QUERY_STRING #地址栏中传的数据(get方式)
|
||||
#REMOTE_ADDR = $REMOTE_ADDR #客户端的ip
|
||||
|
||||
#根据url QUERY调不同方法
|
||||
query(){
|
||||
aria2Query=${QUERY_STRING}
|
||||
parse(){
|
||||
echo $1 | sed 's/.*'$2'=\([[:alnum:]]*\).*/\1/'
|
||||
}
|
||||
value=$(parse $aria2Query "action")
|
||||
|
||||
if [ ! -z = "$value" ]
|
||||
then
|
||||
if [ "$value" = "status" ]
|
||||
then
|
||||
check_installed_status
|
||||
elif [ "$value" = "readConfig" ]
|
||||
then
|
||||
read_config
|
||||
elif [ "$value" = "workStatus" ]
|
||||
then
|
||||
aria2_work_status
|
||||
else
|
||||
echo
|
||||
fi
|
||||
else
|
||||
return_error "action不能为空"
|
||||
fi
|
||||
}
|
||||
query
|
@ -1,89 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
source /lib/functions.sh
|
||||
|
||||
case "$1" in
|
||||
save)
|
||||
if [ ! -z "$2" ]; then
|
||||
uci set "linkease.@linkease[0].preconfig=$2"
|
||||
uci commit
|
||||
fi
|
||||
;;
|
||||
|
||||
load)
|
||||
if [ -f "/usr/sbin/preconfig.data" ]; then
|
||||
data="`cat /usr/sbin/preconfig.data`"
|
||||
uci set "linkease.@linkease[0].preconfig=${data}"
|
||||
uci commit
|
||||
rm /usr/sbin/preconfig.data
|
||||
else
|
||||
data="`uci -q get linkease.@linkease[0].preconfig`"
|
||||
fi
|
||||
|
||||
if [ -z "${data}" ]; then
|
||||
echo "nil"
|
||||
else
|
||||
echo "${data}"
|
||||
fi
|
||||
|
||||
;;
|
||||
|
||||
local_save)
|
||||
if [ ! -z "$2" ]; then
|
||||
uci set "linkease.@linkease[0].local_home=$2"
|
||||
uci commit
|
||||
ROOT_DIR="$2"
|
||||
if [ -f "/etc/config/quickstart" ]; then
|
||||
config_load quickstart
|
||||
config_get MAIN_DIR main main_dir ""
|
||||
config_get CONF_DIR main conf_dir ""
|
||||
config_get PUB_DIR main pub_dir ""
|
||||
config_get DL_DIR main dl_dir ""
|
||||
config_get TMP_DIR main tmp_dir ""
|
||||
# echo "$MAIN_DIR $CONF_DIR $PUB_DIR $DL_DIR $TMP_DIR"
|
||||
if [ "$ROOT_DIR" = "$MAIN_DIR" ]; then
|
||||
exit 0
|
||||
fi
|
||||
uci set "quickstart.main.main_dir=$ROOT_DIR"
|
||||
if [ -z "$CONF_DIR" -o "$CONF_DIR" = "$MAIN_DIR/Configs" ]; then
|
||||
uci set "quickstart.main.conf_dir=$ROOT_DIR/Configs"
|
||||
fi
|
||||
if [ -z "$PUB_DIR" -o "$PUB_DIR" = "$MAIN_DIR/Public" ]; then
|
||||
uci set "quickstart.main.pub_dir=$ROOT_DIR/Public"
|
||||
fi
|
||||
if [ -z "$DL_DIR" -o "$DL_DIR" = "$MAIN_DIR/Public/Downloads" ]; then
|
||||
uci set "quickstart.main.dl_dir=$ROOT_DIR/Public/Downloads"
|
||||
fi
|
||||
if [ -z "$TMP_DIR" -o "$TMP_DIR" = "$MAIN_DIR/Caches" ]; then
|
||||
uci set "quickstart.main.tmp_dir=$ROOT_DIR/Caches"
|
||||
fi
|
||||
uci commit
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
local_load)
|
||||
if [ -f "/etc/config/quickstart" ]; then
|
||||
data="`uci -q get quickstart.main.main_dir`"
|
||||
fi
|
||||
if [ -z "$data" ]; then
|
||||
data="`uci -q get linkease.@linkease[0].local_home`"
|
||||
fi
|
||||
|
||||
if [ -z "${data}" ]; then
|
||||
echo "nil"
|
||||
else
|
||||
echo "${data}"
|
||||
fi
|
||||
|
||||
;;
|
||||
|
||||
status)
|
||||
echo "TODO"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {save|load|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
@ -1,3 +0,0 @@
|
||||
config linkease
|
||||
option port '8897'
|
||||
option enabled '1'
|
@ -1,28 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 1
|
||||
config_get_bool logger $1 logger
|
||||
config_get port $1 port 8897
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load linkease
|
||||
config_foreach get_config linkease
|
||||
[ $enabled != 1 ] && return 1
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param limits nofile="65535 65535"
|
||||
procd_set_param command /usr/sbin/linkease
|
||||
[ -n "$port" ] && procd_append_param command --deviceAddr ":$port" --localApi /var/run/linkease.sock
|
||||
[ "$logger" == 1 ] && procd_set_param stderr 1
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "linkease"
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@linkease[-1]
|
||||
add ucitrack linkease
|
||||
set ucitrack.@linkease[-1].init=linkease
|
||||
commit ucitrack
|
||||
|
||||
delete firewall.linkease
|
||||
set firewall.linkease=rule
|
||||
set firewall.linkease.name="linkease"
|
||||
set firewall.linkease.target="ACCEPT"
|
||||
set firewall.linkease.src="wan"
|
||||
set firewall.linkease.proto="tcp"
|
||||
set firewall.linkease.dest_port="8897"
|
||||
commit firewall
|
||||
EOF
|
||||
|
||||
/etc/init.d/linkease enable
|
||||
/etc/init.d/linkease start
|
||||
|
||||
exit 0
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 527 B After Width: | Height: | Size: 527 B |
Before Width: | Height: | Size: 692 B After Width: | Height: | Size: 692 B |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |