update 2024-11-06 09:24:05

This commit is contained in:
kenzok8 2024-11-06 09:24:05 +08:00
parent e8843bfa74
commit b98484ed04
7 changed files with 382 additions and 200 deletions

View File

@ -9,4 +9,4 @@ LUCI_PKGARCH:=all
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
# call BuildPackage - OpenWrt buildroot signature

View File

@ -91,6 +91,40 @@ String.prototype.replaceAll = function(search, replacement) {
}
}
function chmodPath(filename, isdir) {
var newmod = prompt('请输入新的权限位支持八进制权限位或者a+x格式', isdir === "1" ? "0755" : "0644");
if (newmod) {
iwxhr.get('/cgi-bin/luci/admin/system/fileassistant/chmod',
{
filepath: concatPath(currentPath, filename),
newmod: newmod
},
function (x, res) {
if (res.ec === 0) {
refresh_list(res.data, currentPath);
}
}
);
}
}
function chownPath(filename) {
var newown = prompt('请输入新的用户名(支持用户名或用户名:群组格式):', "root");
if (newown) {
iwxhr.get('/cgi-bin/luci/admin/system/fileassistant/chown',
{
filepath: concatPath(currentPath, filename),
newown: newown
},
function (x, res) {
if (res.ec === 0) {
refresh_list(res.data, currentPath);
}
}
);
}
}
function openpath(filename, dirname) {
dirname = dirname || currentPath;
window.open('/cgi-bin/luci/admin/system/fileassistant/open?path='
@ -130,6 +164,13 @@ String.prototype.replaceAll = function(search, replacement) {
else if (targetElem.className.indexOf('cbi-button-edit') > -1) {
renamePath(targetElem.parentNode.parentNode.dataset['filename']);
}
else if (targetElem.className.indexOf('cbi-button-chmod') > -1) {
infoElem = targetElem.parentNode.parentNode;
chmodPath(infoElem.dataset['filename'] , infoElem.dataset['isdir']);
}
else if (targetElem.className.indexOf('cbi-button-chown') > -1) {
chownPath(targetElem.parentNode.parentNode.dataset['filename']);
}
else if (targetElem = getFileElem(targetElem)) {
if (targetElem.className.indexOf('parent-icon') > -1) {
update_list(currentPath.replace(/\/[^/]+($|\/$)/, ''));
@ -156,7 +197,14 @@ String.prototype.replaceAll = function(search, replacement) {
}
}
function refresh_list(filenames, path) {
var listHtml = '<table class="cbi-section-table"><tbody>';
var listHtml = '<table class="cbi-section-table"><thead><tr class="cbi-section-table-row cbi-rowstyle-2">'
+'<td class="cbi-value-field">文件</td>'
+'<td class="cbi-value-field">所有者</td>'
+'<td class="cbi-value-field">修改时间</td>'
+'<td class="cbi-value-field">大小</td>'
+'<td class="cbi-value-field">权限</td>'
+'<td class="cbi-section-table-cell">操作</td>'
+'</tr></thead><tbody>';
if (path !== '/') {
listHtml += '<tr class="cbi-section-table-row cbi-rowstyle-2"><td class="parent-icon" colspan="6"><strong>..</strong></td></tr>';
}
@ -196,7 +244,9 @@ String.prototype.replaceAll = function(search, replacement) {
+ '<td class="cbi-value-field cbi-value-perm">'+o.perms+'</td>'
+ '<td class="cbi-section-table-cell">\
<button class="cbi-button cbi-button-edit">重命名</button>\
<button class="cbi-button cbi-button-remove">删除</button>'
<button class="cbi-button cbi-button-remove">删除</button>\
<button class="cbi-button cbi-button-apply cbi-button-chmod">改权限</button>\
<button class="cbi-button cbi-button-apply cbi-button-chown">改用户</button>'
+ install_btn
+ '</td>'
+ '</tr>';
@ -270,6 +320,26 @@ String.prototype.replaceAll = function(search, replacement) {
}
};
document.getElementById('mkdir-toggle').onclick = function() {
var dirname = null;
if (dirname = prompt("请输入文件夹名称:")) {
var formData = new FormData();
formData.append('path', currentPath);
formData.append('dirname', dirname);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/cgi-bin/luci/admin/system/fileassistant/mkdir", true);
xhr.onload = function() {
if (xhr.status == 200) {
var res = JSON.parse(xhr.responseText);
refresh_list(res.data, currentPath);
}
else {
alert('创建失败,请稍后再试...');
}
};
xhr.send(formData);
}
};
document.addEventListener('DOMContentLoaded', function(evt) {
var initPath = '/';
if (/path=([/\w]+)/.test(location.search)) {

View File

@ -6,7 +6,6 @@ function index()
page = entry({"admin", "system", "fileassistant"}, template("fileassistant"), _("文件管理"), 50)
page.i18n = "base"
page.dependent = true
page.acl_depends = { "luci-app-fileassistant" }
page = entry({"admin", "system", "fileassistant", "list"}, call("fileassistant_list"), nil)
page.leaf = true
@ -26,6 +25,14 @@ function index()
page = entry({"admin", "system", "fileassistant", "install"}, call("fileassistant_install"), nil)
page.leaf = true
page = entry({"admin", "system", "fileassistant", "mkdir"}, call("fileassistant_mkdir"), nil)
page.leaf = true
page = entry({"admin", "system", "fileassistant", "chmod"}, call("fileassistant_chmod"), nil)
page.leaf = true
page = entry({"admin", "system", "fileassistant", "chown"}, call("fileassistant_chown"), nil)
page.leaf = true
end
function list_response(path, success)
@ -109,15 +116,18 @@ function installIPK(filepath)
end
function fileassistant_upload()
local filecontent = luci.http.formvalue("upload-file")
local filename = luci.http.formvalue("upload-filename")
local uploaddir = luci.http.formvalue("upload-dir")
local filepath = uploaddir..filename
local fp
-- MUST setfilehandler before formvalue,
-- beacuse formvalue will parse form and write body to /tmp if filehandler not present
luci.http.setfilehandler(
function(meta, chunk, eof)
if not fp and meta and meta.name == "upload-file" then
local filename = luci.http.formvalue("upload-filename")
local uploaddir = luci.http.formvalue("upload-dir")
if not uploaddir or not filename then
error("uploaddir or filename is nil")
end
local filepath = uploaddir..filename
fp = io.open(filepath, "w")
end
if fp and chunk then
@ -129,7 +139,28 @@ function fileassistant_upload()
end
)
list_response(uploaddir, true)
list_response(luci.http.formvalue("upload-dir"), true)
end
function fileassistant_mkdir()
local path = luci.http.formvalue("path")
local dirname = luci.http.formvalue("dirname")
local success = os.execute('sh -c \'cd "'..path..'" && mkdir -p "'..dirname..'"\'')
list_response(path, success)
end
function fileassistant_chmod()
local path = luci.http.formvalue("filepath")
local newmod = luci.http.formvalue("newmod")
local success = os.execute('chmod '..newmod..' "'..path..'"')
list_response(nixio.fs.dirname(path), success)
end
function fileassistant_chown()
local path = luci.http.formvalue("filepath")
local newown = luci.http.formvalue("newown")
local success = os.execute('chown '..newown..' "'..path..'"')
list_response(nixio.fs.dirname(path), success)
end
function scandir(directory)

View File

@ -1,12 +1,13 @@
<%+header%>
<link rel="stylesheet" href="/luci-static/resources/fileassistant/fb.css?v=@ver">
<link rel="stylesheet" href="/luci-static/resources/fileassistant/fb.css<%# ?v=PKG_VERSION %>">
<h2 name="content">文件助手</h2>
<fieldset class="cbi-section fb-container">
<input id="current-path" type="text" class="current-path cbi-input-text" value="/"/>
<div class="panel-container">
<div class="panel-title">文件列表</div>
<button id="upload-toggle" class="upload-toggle cbi-button cbi-button-edit">上传</button>
<button id="mkdir-toggle" class="upload-toggle cbi-button cbi-button-edit">新建文件夹&hellip; </button>
</div>
<div class="upload-container" id="upload-container">
<input id="upload-file" name="upload-file" class="upload-file" type="file">
@ -15,6 +16,6 @@
<div id="list-content"></div>
</fieldset>
<script src="/luci-static/resources/fileassistant/fb.js?v=@ver"></script>
<script src="/luci-static/resources/fileassistant/fb.js<%# ?v=PKG_VERSION %>"></script>
<%+footer%>

View File

@ -1,11 +0,0 @@
{
"luci-app-fileassistant": {
"description": "Grant UCI access for luci-app-fileassistant",
"read": {
"uci": [ "fileassistant" ]
},
"write": {
"uci": [ "fileassistant" ]
}
}
}

View File

@ -82,117 +82,141 @@ $uiVersion = getUiVersion();
<a href="./configs.php" class="col btn btn-lg">⚙️ 配置</a>
<a href="/nekobox/mon.php" class="col btn btn-lg d-flex align-items-center justify-content-center"></i>📦 订阅</a>
<a href="#" class="col btn btn-lg">🛠️ 设定</a>
<h2 class="text-center p-2 mb-3">主题设定</h2>
<form action="settings.php" method="post">
<div class="container text-center justify-content-md-center">
<div class="container px-4">
<h2 class="text-center p-2 mb-3">主题设定</h2>
<form action="settings.php" method="post">
<div class="text-center justify-content-md-center">
<div class="row justify-content-md-center">
<div class="col mb-3 justify-content-md-center">
<select class="form-select" name="themechange" aria-label="themex">
<option selected>Change Theme (<?php echo $neko_theme ?>)</option>
<?php foreach ($arrFiles as $file) echo "<option value=\"".$file.'">'.$file."</option>" ?>
</select>
</div>
<div class="row justify-content-md-center">
<div class="col mb-3 justify-content-md-center">
<select class="form-select" name="themechange" aria-label="themex">
<option selected>Change Theme (<?php echo $neko_theme ?>)</option>
<?php foreach ($arrFiles as $file) echo "<option value=\"".$file.'">'.$file."</option>" ?>
</select>
</div>
<div class="row justify-content-md-center">
<div class="col justify-content-md-center mb-3">
<input class="btn btn-info" type="submit" value="🖫 更改主题">
</div>
<div class="col justify-content-md-center mb-3">
<input class="btn btn-info" type="submit" value="🖫 更改主题">
</div>
</div>
</div>
</form>
<h2 class="text-center p-2 mb-3">软体资讯</h2>
<table class="table table-borderless mb-3">
<tbody>
<tr>
<td colspan="2">
<h3 class="text-center mb-3">自动重载防火墙</h3>
<form action="settings.php" method="post">
<div class="btn-group d-flex justify-content-center">
<button type="submit" name="fw" value="enable" class="btn btn<?php if($fwstatus==1) echo "-outline" ?>-success <?php if($fwstatus==1) echo "disabled" ?>">启用</button>
<button type="submit" name="fw" value="disable" class="btn btn<?php if($fwstatus==0) echo "-outline" ?>-danger <?php if($fwstatus==0) echo "disabled" ?>">停用</button>
</div>
</form>
</td>
</tr>
<tr>
<td colspan="2">
<div class="row">
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>客户端版本</h3>
<div class="form-control text-center" style="font-family: monospace; text-align: center;">
<span id="cliver"></span>&nbsp;<span id="NewCliver"> </span>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkCliverButton">🔍 检测版本</button>
<button class="btn btn-info" id="updateButton" title="更新到最新版本">🔄 更新版本</button>
</div>
</div>
</form>
<div class="card mb-4">
<div class="card-body">
<table class="table table-borderless mb-3">
<tbody>
<tr>
<td colspan="2">
<h2 class="text-center mb-3">自动重载防火墙</h2>
<form action="settings.php" method="post">
<div class="btn-group d-flex justify-content-center">
<button type="submit" name="fw" value="enable" class="btn btn<?php if($fwstatus==1) echo "-outline" ?>-success <?php if($fwstatus==1) echo "disabled" ?>">启用</button>
<button type="submit" name="fw" value="disable" class="btn btn<?php if($fwstatus==0) echo "-outline" ?>-danger <?php if($fwstatus==0) echo "disabled" ?>">停用</button>
</div>
</form>
</td>
</tr>
<tr>
<td colspan="2">
<div class="row g-4">
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>客户端版本</h3>
<div class="form-control text-center" style="font-family: monospace; text-align: center;">
<span id="cliver"></span>&nbsp;<span id="NewCliver"> </span>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Metacubexd 面板</h3>
<div class="form-control text-center">
<?php echo htmlspecialchars($uiVersion); ?>&nbsp;<span id="NewUi"> </span>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkUiButton">🔍 检测版本</button>
<button class="btn btn-info" id="updateUiButton" title="更新 Metacubexd 面板">🔄 更新版本</button>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Sing-box 核心版本</h3>
<div class="form-control text-center">
<div id="singBoxCorever">
<?php echo htmlspecialchars($singBoxVersion); ?>&nbsp;<span id="NewSingbox"></span>
</div>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkSingboxButton">🔍 检测版本</button>
<button class="btn btn-success" id="updatePuernyaButton" title="切换 Puernya 内核">🔄 切换内核</button>
<button class="btn btn-primary" id="updateRuleButton" title="更新 Singbox 规则集<配合 Puernya 内核可以使用 Singbox 的配置文件和本地规则集>">🔄 更新规则</button>
<button class="btn btn-info" id="updateSingboxButton" title="更新 Singbox 内核">🔄 更新版本</button>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Mihomo 核心版本</h3>
<div class="form-control text-center">
<span id="corever"></span>&nbsp;<span id="NewMihomo"> </span>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkMihomoButton">🔍 检测版本</button>
<button id="updateConfigButton" class="btn btn-primary" title="更新 Mihomo 配置文件">🔄 更新配置</button>
<button class="btn btn-info" id="updateCoreButton" title="更新 Mihomo 内核">🔄 更新版本</button>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkCliverButton">🔍 检测版本</button>
<button class="btn btn-info" id="updateButton" title="更新到最新版本">🔄 更新版本</button>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">更新状态</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center">
<pre id="logOutput" style="white-space: pre-wrap; word-wrap: break-word; text-align: left; display: inline-block;">开始下载更新...</pre>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Metacubexd 面板</h3>
<div class="form-control text-center">
<?php echo htmlspecialchars($uiVersion); ?>&nbsp;<span id="NewUi"> </span>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkUiButton">🔍 检测版本</button>
<button class="btn btn-info" id="updateUiButton" title="更新 Metacubexd 面板">🔄 更新版本</button>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Sing-box 核心版本</h3>
<div class="form-control text-center">
<div id="singBoxCorever">
<?php echo htmlspecialchars($singBoxVersion); ?>&nbsp;<span id="NewSingbox"></span>
</div>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkSingboxButton">🔍 检测版本</button>
<button class="btn btn-info" id="singboxOptionsButton" title="Singbox 相关操作">🔄 更新版本</button>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="text-center">
<h3>Mihomo 核心版本</h3>
<div class="form-control text-center">
<span id="corever"></span>&nbsp;<span id="NewMihomo"> </span>
</div>
<div class="text-center mt-2">
<button class="btn btn-pink" id="checkMihomoButton">🔍 检测版本</button>
<button class="btn btn-info" id="updateCoreButton" title="更新 Mihomo 内核">🔄 更新版本</button>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="optionsModal" tabindex="-1" aria-labelledby="optionsModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="optionsModalLabel">选择操作</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="d-grid gap-2">
<button class="btn btn-info" onclick="selectOperation('singbox')">更新 Singbox 内核(官方稳定版)</button>
<button class="btn btn-success" onclick="selectOperation('sing-box')">更新 Singbox 内核(未编译版本)</button>
<button class="btn btn-success" onclick="selectOperation('puernya')">切换 Puernya 内核</button>
<button class="btn btn-primary" onclick="selectOperation('rule')">更新 Singbox 规则集</button>
<button class="btn btn-primary" onclick="selectOperation('config')">更新 Mihomo 配置文件</button>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="updateModal" tabindex="-1" aria-labelledby="updateModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">更新状态</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center">
<div id="updateDescription" class="alert alert-info mb-3"></div>
<pre id="logOutput" style="white-space: pre-wrap; word-wrap: break-word; text-align: left; display: inline-block;">等待操作开始...</pre>
<div class="alert alert-info mt-3" role="alert">
提示: 如遇到更新失败,请在终端输入 <code>nekobox</code> 进行更新!
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="logOutput" class="mt-3"></div>
<style>
@ -235,89 +259,97 @@ $uiVersion = getUiVersion();
}
}
#updateButton:hover {
background-color: #20B2AA;
}
#updateSingboxButton:hover {
background-color: #FF69B4;
}
#updateCoreButton:hover {
background-color: #90EE90;
}
#updatePuernyaButton:hover {
background-color: #87CEFA;
}
#updateModal #logOutput {
font-family: 'Courier New', monospace;
font-size: 1rem;
color: #333;
}
</style>
<script>
function initiateUpdate(url, logMessage) {
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
$('#updateModal').modal('show');
document.getElementById('logOutput').textContent = logMessage;
xhr.onload = function() {
if (xhr.status === 200) {
document.getElementById('logOutput').textContent += '\n更新完成';
document.getElementById('logOutput').textContent += '\n' + xhr.responseText;
setTimeout(function() {
$('#updateModal').modal('hide');
setTimeout(function() {
location.reload();
}, 500);
}, 10000);
} else {
document.getElementById('logOutput').textContent += '\n发生错误' + xhr.statusText;
}
};
xhr.onerror = function() {
document.getElementById('logOutput').textContent += '\n网络错误请稍后再试。';
};
xhr.send();
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('singboxOptionsButton').addEventListener('click', function() {
$('#optionsModal').modal('show');
});
document.getElementById('updateButton').addEventListener('click', function() {
initiateUpdate('update_script.php', '开始下载更新...');
});
document.getElementById('updateSingboxButton').addEventListener('click', function() {
initiateUpdate('singbox.php', '开始下载 Singbox 核心更新...');
});
document.getElementById('updatePuernyaButton').addEventListener('click', function() {
initiateUpdate('puernya.php', '开始下载 Puernya 核心更新...');
});
document.getElementById('updateCoreButton').addEventListener('click', function() {
initiateUpdate('core.php', '开始下载 Mihomo 核心更新...');
initiateUpdate('update_script.php', '开始下载客户端更新...', '正在更新客户端到最新版本');
});
document.getElementById('updateUiButton').addEventListener('click', function() {
initiateUpdate('ui.php', '开始下载 UI 面板更新...');
initiateUpdate('ui.php', '开始下载 UI 面板更新...', '正在更新 Metacubexd 面板到最新版本');
});
document.getElementById('updateConfigButton').addEventListener('click', function() {
initiateUpdate('update_config.php', '开始下载 Mihomo 配置文件更新...');
document.getElementById('updateCoreButton').addEventListener('click', function() {
initiateUpdate('core.php', '开始下载 Mihomo 核心更新...', '正在更新 Mihomo 核心到最新版本');
});
});
document.getElementById('updateRuleButton').addEventListener('click', function() {
initiateUpdate('update_rule.php', '开始下载 Singbox 规则集更新...');
});
function selectOperation(type) {
$('#optionsModal').modal('hide');
const operations = {
'singbox': {
url: 'update_singbox_core.php',
message: '开始下载 Singbox 核心更新...',
description: '正在更新 Singbox 核心到最新版本'
},
'sing-box': {
url: 'singbox.php',
message: '开始下载 Singbox 核心更新...',
description: '正在更新 Singbox 核心到最新版本'
},
'puernya': {
url: 'puernya.php',
message: '开始切换 Puernya 核心...',
description: '正在切换到 Puernya 内核,此操作将替换当前的 Singbox 核心'
},
'rule': {
url: 'update_rule.php',
message: '开始下载 Singbox 规则集...',
description: '正在更新 Singbox 规则集,配合 Puernya 内核可以使用 Singbox 的配置文件和本地规则集'
},
'config': {
url: 'update_config.php',
message: '开始下载 Mihomo 配置文件...',
description: '正在更新 Mihomo 配置文件到最新版本'
}
};
const operation = operations[type];
if (operation) {
setTimeout(function() {
initiateUpdate(operation.url, operation.message, operation.description);
}, 500);
}
}
function initiateUpdate(url, logMessage, description) {
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
$('#updateModal').modal('show');
document.getElementById('updateDescription').textContent = description;
document.getElementById('logOutput').textContent = logMessage;
xhr.onload = function() {
if (xhr.status === 200) {
document.getElementById('logOutput').textContent += '\n更新完成';
document.getElementById('logOutput').textContent += '\n' + xhr.responseText;
setTimeout(function() {
$('#updateModal').modal('hide');
setTimeout(function() {
location.reload();
}, 500);
}, 10000);
} else {
document.getElementById('logOutput').textContent += '\n发生错误' + xhr.statusText;
}
};
xhr.onerror = function() {
document.getElementById('logOutput').textContent += '\n网络错误请稍后再试。';
};
xhr.send();
}
</script>
<script>
@ -358,23 +390,23 @@ $uiVersion = getUiVersion();
<script>
function compareVersions(v1, v2) {
const v1parts = v1.split(/[-.]/).filter(x => x !== 'alpha' && x !== 'beta');
const v2parts = v2.split(/[-.]/).filter(x => x !== 'alpha' && x !== 'beta');
const v1parts = v1.split(/[-.]/).filter(x => !isNaN(x));
const v2parts = v2.split(/[-.]/).filter(x => !isNaN(x));
for (let i = 0; i < Math.max(v1parts.length, v2parts.length); ++i) {
const v1part = parseInt(v1parts[i]) || 0;
const v2part = parseInt(v2parts[i]) || 0;
const v1part = parseInt(v1parts[i]) || 0;
const v2part = parseInt(v2parts[i]) || 0;
if (v1part > v2part) return 1;
if (v1part < v2part) return -1;
}
return 0;
return 0;
}
function checkSingboxVersion() {
var currentVersion = '<?php echo getSingboxVersion(); ?>';
var minVersion = '1.10.0';
var minVersion = '1.10.0';
if (compareVersions(currentVersion, minVersion) >= 0) {
return;
@ -481,6 +513,10 @@ $uiVersion = getUiVersion();
text-decoration: none;
color: #000000;
}
.container {
padding-left: 10px;
padding-right: 10px;
}
</style>
</head>
<body>

View File

@ -0,0 +1,55 @@
<?php
$repo_owner = "Thaolga";
$repo_name = "openwrt-nekobox";
$package_name = "sing-box";
$new_version = "1.11.0-alpha.6";
$api_url = "https://api.github.com/repos/$repo_owner/$repo_name/releases/latest";
$local_api_response = "/tmp/api_response.json";
$curl_command = "curl -H 'User-Agent: PHP' -s " . escapeshellarg($api_url) . " -o " . escapeshellarg($local_api_response);
exec($curl_command . " 2>&1", $output, $return_var);
if (!file_exists($local_api_response)) {
die("无法访问GitHub API。请检查URL或网络连接。输出: " . implode("\n", $output));
}
$response = file_get_contents($local_api_response);
$data = json_decode($response, true);
unlink($local_api_response);
$new_version = $data['tag_name'] ?? '';
if (empty($new_version)) {
die("未找到最新版本或版本信息为空。");
}
$arch = shell_exec("opkg info " . escapeshellarg($package_name) . " | grep 'Architecture'");
if (strpos($arch, 'aarch64') !== false || strpos($arch, 'arm') !== false) {
$arch = "aarch64_generic";
$download_url = "https://github.com/$repo_owner/$repo_name/releases/download/$new_version/{$package_name}_1.11.0-alpha.6-1_aarch64_generic.ipk";
} elseif (strpos($arch, 'x86_64') !== false) {
$arch = "x86_64";
$download_url = "https://github.com/$repo_owner/$repo_name/releases/download/$new_version/{$package_name}_1.11.0-alpha.6-1_x86_64.ipk";
} elseif (strpos($arch, 'mips') !== false) {
$arch = "mips";
$download_url = "https://github.com/$repo_owner/$repo_name/releases/download/$new_version/{$package_name}_1.11.0-alpha.6-1_mips.ipk";
} else {
die("当前设备架构不受支持");
}
$local_file = "/tmp/{$package_name}_{$new_version}_{$arch}.ipk";
echo "<pre>最新版本: $new_version</pre>";
echo "<pre>下载URL: $download_url</pre>";
echo "<pre id='logOutput'></pre>";
echo "<script>
function appendLog(message) {
document.getElementById('logOutput').innerHTML += message + '\\n';
}
</script>";
echo "<script>appendLog('开始下载...');</script>";
$curl_command = "curl -sL " . escapeshellarg($download_url) . " -o " . escapeshellarg($local_file);
exec($curl_command . " 2>&1", $output, $return_var);
if ($return_var !== 0 || !file_exists($local_file)) {
echo "<pre>下载失败。输出: " . implode("\n", $output) . "</pre>";
die("下载失败。未找到下载的文件。");
}
echo "<script>appendLog('下载完成。');</script>";
echo "<script>appendLog('开始安装...');</script>";
$output = shell_exec("opkg install --force-reinstall " . escapeshellarg($local_file));
echo "<pre>$output</pre>";
echo "<script>appendLog('安装完成。');</script>";
unlink($local_file);
?>