1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-02-15 03:51:51 +00:00

Merge pull request #239 from Ysurac/develop

sync
This commit is contained in:
suyuan 2022-05-24 03:19:58 +08:00 committed by GitHub
commit 012b2710d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 804 additions and 4673 deletions

9
contributors/flesser.md Normal file
View file

@ -0,0 +1,9 @@
2022-05-20
I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00.
I furthermore declare that I am authorized and able to make this agreement and sign this declaration.
Signed,
Florian Karuhtz https://github.com/flesser

View file

@ -1489,6 +1489,9 @@ function interfaces_status()
whois = ut.trim(sys.exec("whois " .. publicIP .. " | grep -i 'netname' | awk '{print $2}'"))
--whois = ut.trim(sys.exec("wget -4 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP .. "' | jsonfilter -q -e '@.as_description'"))
end
if publicIP == mArray.openmptcprouter["wan_addr"] then
mArray.openmptcprouter["direct_output"] = true
end
end
if publicIP6 ~= "" then
whois6 = uci:get("openmptcprouter",interface,"asn") or ""
@ -1496,6 +1499,9 @@ function interfaces_status()
whois6 = ut.trim(sys.exec("whois " .. publicIP6 .. " | grep -i 'netname' | awk '{print $2}'"))
--whois6 = ut.trim(sys.exec("wget -6 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP6 .. "' | jsonfilter -q -e '@.as_description'"))
end
if publicIP6 == mArray.openmptcprouter["wan_addr6"] then
mArray.openmptcprouter["direct_output"] = true
end
end
if ifname ~= "" and ifname ~= nil then
if fs.access("/sys/class/net/" .. ifname) then

201
luci-theme-argon/LICENSE Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -7,9 +7,9 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Argon Theme
LUCI_DEPENDS:=
PKG_VERSION:=2.2.6
PKG_RELEASE:=20210215
LUCI_DEPENDS:=+curl +jsonfilter
PKG_VERSION:=2.2.9.4
PKG_RELEASE:=20220425
include $(TOPDIR)/feeds/luci/luci.mk

View file

@ -6,30 +6,20 @@
<h3 align="center">
Argon is a clean HTML5 theme for LuCI. Users may<br>setup their own favorite logins, including beautiful<br>pics and customized mp4 videos.<br><br>
</h3>
<a href="/LICENSE">
<img src="https://img.shields.io/badge/license-MIT-brightgreen.svg" alt="">
<a href="/LICENSE">
<img src="https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1" alt="">
</a>
<a href="https://github.com/jerrykuku/luci-theme-argon/pulls">
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="">
</a>
<a href="https://github.com/jerrykuku/luci-theme-argon/issues/new">
<img src="https://img.shields.io/badge/Issues-welcome-brightgreen.svg">
</a>
<a href="https://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/badge/release-v2.2.5-blue.svg?">
</a>
<a href="https://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total">
</a>
<a href="https://t.me/jerryk6">
<img src="https://img.shields.io/badge/Contact-telegram-blue">
</a>
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="">
</a><a href="https://github.com/jerrykuku/luci-theme-argon/issues/new">
<img src="https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square">
</a><a href="https://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/github/release/jerrykuku/luci-theme-argon.svg?style=flat-square">
</a><a href="hhttps://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total?style=flat-square">
</a><a href="https://t.me/jerryk6">
<img src="https://img.shields.io/badge/Contact-telegram-blue?style=flat-square">
</a>
</div>
<br>
<div align="center">
@ -46,8 +36,12 @@ FireFox does not enable the backdrop-filter by default, see here for the opening
v2.x.x Adapt to official mainline snapshot.
You can checkout branch 18.06 for OpenWRT 18.06 or lean 19.07.
## Update Log 2020.09.13 v2.2.5
## Update Log 2021.10.16 v2.2.9
- 【v2.2.9】Fix the problem that the menu could not pop up in mobile mode
- 【v2.2.9】Unify the settings of css spacing
- 【v2.2.9】Refactored the code of the login page
- 【v2.2.8】Fix the problem that the Minify Css option is turned on when compiling, which causes the frosted glass effect to be invalid and the logo font is lost.
- 【v2.2.5】New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk)
- 【v2.2.5】Automatically set as the default theme when compiling.
- 【v2.2.5】Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config.
@ -100,7 +94,7 @@ make -j1 V=s
### For Lean openwrt 18.06 LuCI
```
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.3/luci-theme-argon-18.06_1.7.3-20220421_all.ipk
opkg install luci-theme-argon*.ipk
```
@ -108,7 +102,8 @@ opkg install luci-theme-argon*.ipk
```
opkg install luci-compat
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk
opkg install luci-lib-ipkg
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.9/luci-theme-argon_2.2.9-20211016-1_all.ipk
opkg install luci-theme-argon*.ipk
```
![](/Screenshots/screenshot_pc.jpg)

View file

@ -1,26 +1,30 @@
# luci-theme-argon ([English](/README.md))
[1]: https://img.shields.io/badge/license-MIT-brightgreen.svg
[2]: /LICENSE
[3]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
[4]: https://github.com/jerrykuku/luci-theme-argon/pulls
[5]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg
[6]: https://github.com/jerrykuku/luci-theme-argon/issues/new
[7]: https://img.shields.io/badge/release-v2.2.5-blue.svg?
[8]: https://github.com/jerrykuku/luci-theme-argon/releases
[9]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total
[10]: https://img.shields.io/badge/Contact-telegram-blue
[11]: https://t.me/jerryk6
[![license][1]][2]
[![PRs Welcome][3]][4]
[![Issue Welcome][5]][6]
[![Release Version][7]][8]
[![Release Count][9]][8]
[![Contact Me][10]][11]
<div align="center">
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon_title2.png" >
<h1 align="center">
全新的 Openwrt 主题
</h1>
<h3 align="center">
Argon 是一个干净整洁的Openwrt主题用户可以自定义登录界面<br>包含图片或者视频,同时支持深色浅色的自动与手动切换
</h3>
<a href="/LICENSE">
<img src="https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1" alt="">
</a><a href="https://github.com/jerrykuku/luci-theme-argon/pulls">
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="">
</a><a href="https://github.com/jerrykuku/luci-theme-argon/issues/new">
<img src="https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square">
</a><a href="https://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/github/release/jerrykuku/luci-theme-argon.svg?style=flat-square">
</a><a href="hhttps://github.com/jerrykuku/luci-theme-argon/releases">
<img src="https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total?style=flat-square">
</a><a href="https://t.me/jerryk6">
<img src="https://img.shields.io/badge/Contact-telegram-blue?style=flat-square">
</a>
</div>
![](/Screenshots/screenshot_pc.jpg)
![](/Screenshots/screenshot_phone.jpg)
全新的 Openwrt 主题基于luci-theme-material 和 开源免费的 Argon 模板进行移植。
## 注意
强烈建议使用Chrome 浏览器。主题中使用了一些新的css3特性目前只有Chrome有最佳的兼容性。
@ -31,8 +35,13 @@ v2.x.x 适配主线快照版本。
v1.x.x 适配18.06 和 Lean Openwrt [如果你是lean代码 请选择这个版本]
## 更新日志 2020.09.13 v2.2.5
## 更新日志 2021.10.16 v2.2.9
- 【v2.2.9】修复了在手机模式下无法弹出菜单的bug
- 【v2.2.9】统一css间距的设置
- 【v2.2.9】重构了登录页面的代码
- 【v2.2.9】为导航菜单添加滑动效果
- 【v2.2.8】修复编译时打开Minify Css选项导致磨砂玻璃效果无效logo字体丢失的问题
- 【v2.2.5】全新的设置app.你可以设置argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk)
- 【v2.2.5】当编译固件时,将自动设置为默认主题。
- 【v2.2.5】修改文件结构以适应luci-app-argon-config旧的开启暗色模式方法将不再适用请搭配luci-app-argon-config使用。

View file

@ -1,2 +1,2 @@
Drop background here!
accept jpg png gif and mp4
accept jpg png gif mp4 webm

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#202124" d="m8,10.033663l-6.898535,-6.013274l-1.060688,0.972974l7.959223,6.986249l7.959223,-6.986249l-1.060688,-0.972974l-6.898535,6.013274z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#adaeaf" d="m8,10.033663l-6.898535,-6.013274l-1.060688,0.972974l7.959223,6.986249l7.959223,-6.986249l-1.060688,-0.972974l-6.898535,6.013274z"/></svg>

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 222 B

View file

@ -1,219 +0,0 @@
/**
* Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template
*
* luci-theme-argon
* Copyright 2019 Jerrykuku <jerrykuku@qq.com>
*
* Have a bug? Please create an issue here on GitHub!
* https://github.com/jerrykuku/luci-theme-argon/issues
*
* luci-theme-material:
* Copyright 2015 Lutty Yang <lutty@wcan.in>
* https://github.com/LuttyYang/luci-theme-material/
*
* Agron Theme
* https://demos.creative-tim.com/argon-dashboard/index.html
*
* Login background
* https://unsplash.com/
* Font generate by Icomoon<icomoon.io>
*
* Licensed to the public under the Apache License 2.0
*/
document.addEventListener('luci-loaded', function(ev) {
(function ($) {
/**
* trim text, Remove spaces, wrap
* @param text
* @returns {string}
*/
function trimText(text) {
return text.replace(/[ \t\n\r]+/g, " ");
}
var lastNode = undefined;
var mainNodeName = undefined;
var nodeUrl = "";
(function(node){
var luciLocation;
if (node[0] == "admin"){
luciLocation = [node[1], node[2]];
}else{
luciLocation = node;
}
for(var i in luciLocation){
nodeUrl += luciLocation[i];
if (i != luciLocation.length - 1){
nodeUrl += "/";
}
}
})(luciLocation);
/**
* get the current node by Burl (primary)
* @returns {boolean} success?
*/
function getCurrentNodeByUrl() {
var ret = false;
if (!$('body').hasClass('logged-in')) {
luciLocation = ["Main", "Login"];
return true;
}
$(".main > .main-left > .nav > .slide > .menu").each(function () {
var ulNode = $(this);
ulNode.next().find("a").each(function () {
var that = $(this);
var href = that.attr("href");
if (href.indexOf(nodeUrl) != -1) {
ulNode.click();
ulNode.next(".slide-menu").stop(true, true);
lastNode = that.parent();
lastNode.addClass("active");
ret = true;
return true;
}
});
});
return ret;
}
/**
* menu click
*/
$(".main > .main-left > .nav > .slide > .menu").click(function () {
var ul = $(this).next(".slide-menu");
var menu = $(this);
$(".main > .main-left > .nav > .slide > .menu").each(function () {
var ulNode = $(this);
ulNode.removeClass("active");
ulNode.next(".slide-menu").stop(true).slideUp("fast")
});
if (!ul.is(":visible")) {
menu.addClass("active");
ul.addClass("active");
ul.stop(true).slideDown("fast");
} else {
ul.stop(true).slideUp("fast", function () {
menu.removeClass("active");
ul.removeClass("active");
});
}
return false;
});
/**
* hook menu click and add the hash
*/
$(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
if (lastNode != undefined) lastNode.removeClass("active");
$(this).parent().addClass("active");
return true;
});
/**
* fix menu click
*/
$(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
if (lastNode != undefined) lastNode.removeClass("active");
$(this).addClass("active");
window.location = $($(this).find("a")[0]).attr("href");
return false;
});
/**
* get current node and open it
*/
if (getCurrentNodeByUrl()) {
mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1];
mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase();
$("body").addClass(mainNodeName);
}
/**
* Sidebar expand
*/
var showSide = false;
$(".showSide").click(function () {
if (showSide) {
$(".darkMask").stop(true).fadeOut("fast");
$(".main-left").width(0);
$(".main-right").css("overflow-y", "visible");
showSide = false;
} else {
$(".darkMask").stop(true).fadeIn("fast");
$(".main-left").width("13rem")
$(".main-right").css("overflow-y", "hidden");
showSide = true;
}
});
$(".darkMask").click(function () {
if (showSide) {
showSide = false;
$(".darkMask").stop(true).fadeOut("fast");
$(".main-left").width(0);
$(".main-right").css("overflow-y", "visible");
}
});
$(window).resize(function () {
if ($(window).width() > 921) {
$(".main-left").css("width", "");
$(".darkMask").stop(true);
$(".darkMask").css("display", "none");
showSide = false;
}
});
/**
* fix legend position
*/
$("legend").each(function () {
var that = $(this);
that.after("<span class='panel-title'>" + that.text() + "</span>");
});
$(".cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr").each(function () {
var that = $(this);
if (that.text().trim() == ""){
that.css("display", "none");
}
});
$(".main-right").focus();
$(".main-right").blur();
$("input").attr("size", "0");
$(".cbi-button-up").val("__");
$(".cbi-button-down").val("__");
$(".slide > a").removeAttr("href");
if (mainNodeName != undefined) {
console.log(mainNodeName);
switch (mainNodeName) {
case "node-status-system_log":
case "node-status-kernel_log":
$("#syslog").focus(function () {
$("#syslog").blur();
$(".main-right").focus();
$(".main-right").blur();
});
break;
case "node-status-firewall":
var button = $(".node-status-firewall > .main fieldset li > a");
button.addClass("cbi-button cbi-button-reset a-to-btn");
break;
case "node-system-reboot":
var button = $(".node-system-reboot > .main > .main-right p > a");
button.addClass("cbi-button cbi-input-reset a-to-btn");
break;
}
}
})(jQuery);
});

View file

@ -1,4 +1,4 @@
// out: ../css/cascade.css, compress: false , sourceMap: false
// out: ../css/cascade.css, compress: true , sourceMap: false
/**
* Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template
*
@ -8,7 +8,7 @@
* Have a bug? Please create an issue here on GitHub!
* https://github.com/jerrykuku/luci-theme-argon/issues
*
* luci-theme-material:
* luci-theme-material:
* Copyright 2015 Lutty Yang <lutty@wcan.in>
* https://github.com/LuttyYang/luci-theme-material/
*
@ -25,9 +25,9 @@
/*
* Include base and custom css
*/
@import url("pure-min.less");
@import url("fonts.less");
@import url("fonts.css?v=3");
@import url("pure-min.css?v=1");
:root {
--primary: #5e72e4;
@ -102,9 +102,11 @@ html {
body {
font-size: 0.875rem;
background-color: #f4f5f7;
background-color: var(--background-color);
color: #32325d;
color: var(--gray-dark);
-webkit-tap-highlight-color: transparent;
}
* {
@ -364,13 +366,14 @@ hr {
background-color: #000;
background-color: var(--darker);
overflow: hidden;
video {
width: 100%;
height: auto;
}
}
.volume-control{
.volume-control {
position: fixed;
right: 1rem;
top: 1rem;
@ -380,12 +383,13 @@ hr {
cursor: pointer;
background-size: contain;
background-image: url(../img/volume_high.svg);
&.mute{
&.mute {
background-image: url(../img/volume_off.svg);
}
}
.main-bg{
.main-bg {
position: absolute;
width: 100%;
height: 100%;
@ -427,6 +431,9 @@ hr {
max-width: 420px;
background-color: #fff;
background-color: var(--white);
-webkit-backdrop-filter: blur(var(--blur-radius));
backdrop-filter: blur(var(--blur-radius));
background-color: rgba(244, 245, 247, var(--blur-opacity));
.brand {
display: flex;
@ -509,7 +516,7 @@ hr {
box-sizing: border-box;
transition: all .3s cubic-bezier(.68, -.55, .265, 1.55);
color: #525461;
color:var(--default);
color: var(--default);
border: 0;
border-radius: 0;
border-bottom: 1px solid #fff;
@ -585,7 +592,8 @@ hr {
color: var(--default);
position: absolute;
bottom: 0;
.ftc{
.ftc {
position: absolute;
bottom: 30px;
width: 100%;
@ -598,15 +606,6 @@ hr {
}
}
@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {
.login-page .login-container .login-form {
-webkit-backdrop-filter: blur(var(--blur-radius));
backdrop-filter: blur(var(--blur-radius));
background-color: rgba(244, 245, 247, var(--blur-opacity));
}
}
header,
.main {
@ -659,7 +658,7 @@ small {
.sidenav-header {
padding: 1.5rem;
padding: 1.5rem .5rem;
text-align: center;
.brand {
@ -671,7 +670,6 @@ small {
text-align: center;
cursor: default;
vertical-align: text-bottom;
white-space: nowrap;
}
}
@ -741,31 +739,40 @@ header {
.fill {
padding: 0.8rem 0;
border-bottom: 0px solid rgba(255, 255, 255, .08) !important;
display: flex;
.container {
height: 2rem;
padding: 0 1.25rem;
display: flex;
align-items: center;
width: 100%;
.showSide {
display: none;
color: #fff;
font-size: 1.4rem;
.flex1 {
flex: 1;
&:hover {
.showSide {
display: none;
color: #fff;
font-size: 1.4rem;
&:hover {
text-decoration: none;
}
}
.brand {
font-size: 1.5rem;
color: #fff;
font-family: "TypoGraphica";
text-decoration: none;
padding-left: 1rem;
cursor: default;
vertical-align: text-bottom;
display: none;
}
}
.brand {
font-size: 1.5rem;
color: #fff;
font-family: "TypoGraphica";
text-decoration: none;
padding-left: 1rem;
cursor: default;
vertical-align: text-bottom;
display: none;
}
.pull-right {
float: right;
@ -775,29 +782,33 @@ header {
}
.status {
position: absolute;
top: 25%;
right: 1.25rem;
float: right;
span[data-indicator] {
span{
display: inline-block;
font-size: 0.8rem;
font-weight: bold;
padding: 0.3rem 0.8rem;
margin: 0 0.5rem;
white-space: nowrap;
text-decoration: none;
text-transform: uppercase;
text-shadow: none;
border-radius: 3px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12);
margin: 0 0.25rem;
&:last-child{
margin-right: 0;
}
}
span[data-indicator="poll-status"] {
color: #32325d;
background-color: #fff;
}
span[data-style="active"] {
color: #32325d !important;
background-color: #fff;
background-color: var(--green);
}
@ -849,8 +860,8 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
.alert,
.alert-message {
font-weight: bold;
margin-bottom: 1em;
padding: 1rem;
margin-bottom: 1.25rem;
padding: 1rem 1.25rem;
border: 0;
border-radius: 0.375rem !important;
background-color: #fff;
@ -862,7 +873,9 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
}
h4 {
padding: 0rem 1.5rem 0.75rem 0rem;
padding: 0.25rem 0rem;
border-radius: 4px;
background-color: #ffd600;
}
.btn {
@ -885,7 +898,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
.container .alert,
.container .alert-message {
margin-top: 1rem;
margin-top: 0rem;
}
@ -976,10 +989,9 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
ul {
display: none;
overflow: hidden;
}
&:hover {
background: none;
}
@ -988,6 +1000,12 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
margin: 0 0.5rem 0 2.5rem;
padding: 0rem 0.5rem;
&.active {
display: block;
}
li {
position: relative;
border-radius: 0.375rem;
@ -997,7 +1015,6 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] {
list-style: none;
a {
white-space: nowrap;
text-decoration: none;
}
@ -1274,11 +1291,12 @@ h2 {
margin: 0 0 1rem 0;
font-size: 1.25rem;
letter-spacing: 0.1rem;
padding: 1rem 1.5rem;
padding: 1rem 1.25rem;
color: #32325d;
border-radius: .375rem;
background: #fff;
box-shadow: 0 4px 8px rgba(0, 0, 0, .03);
font-weight: bold;
}
@ -1289,21 +1307,23 @@ h3 {
width: 100%;
margin: 0;
margin-bottom: 0;
padding: 0.8755rem 1.5rem;
padding: 0.8755rem 1.25rem;
color: #32325d;
color: var(--gray-dark);
border-radius: .375rem;
background: #fff;
font-weight: bold;
}
h4 {
margin: 0;
padding: 0.75rem 1.5rem;
padding: 0.75rem 1.25rem;
font-size: 0.7rem;
font-weight: 600;
color: #525f7f;
background-color: #e9ecef;
background-color: var(--lighter);
font-weight: bold;
em {
padding: 0 0.5rem;
@ -1332,7 +1352,7 @@ h5 {
font-style: normal;
line-height: normal;
min-width: inherit;
margin: 1.5rem 0;
margin: 1.25rem 0;
padding: 0rem;
border: 0;
@ -1351,11 +1371,17 @@ h5 {
margin-left: 0;
}
.cbi-map-descr,
.cbi-section-descr {
.cbi-map-descr {
font-size: small;
line-height: 1.42857143;
padding: .5rem 1.5rem;
line-height: 1.5;
padding: 0 1.25rem;
}
.cbi-section-descr:not(:empty) {
font-size: small;
line-height: 1.5;
padding: 1rem 1.25rem 0 1.25rem;
}
.cbi-map-descr+fieldset {
@ -1387,7 +1413,7 @@ fieldset>fieldset,
width: 100%;
margin: 0;
margin-bottom: 0;
padding: 0.8755rem 1.5rem;
padding: 0.8755rem 1.25rem;
color: #32325d;
color: var(--gray-dark);
@ -1399,13 +1425,17 @@ fieldset>fieldset,
[data-tab-title]>h3:first-child,
[data-tab-title]>h4:first-child,
[data-tab-title]>p:first-child {
padding: 1rem;
padding: 1rem 1.25rem;
}
.cbi-section p {
padding: 1rem;
}
.cbi-tblsection {
overflow-x: scroll;
}
table {
border-spacing: 0;
border-collapse: collapse;
@ -1457,7 +1487,7 @@ tr>th,
.cbi-section-table-row::before,
#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) {
border-top: thin solid #ddd;
padding: 1.1em 1.5rem;
padding: 1.1em 1.25rem;
}
#cbi-wireless .td,
@ -1468,7 +1498,7 @@ tr>th,
.tr.cbi-section-table-titles>.th {
border-top: 0 !important;
background-color: #f6f9fc;
padding: 1.1em 1.5rem;
padding: 1.1em 1.25rem;
line-height: 1.3rem;
}
@ -1493,6 +1523,11 @@ tr>th,
width: 100%;
}
.cbi-section-table-row>.cbi-value-field .cbi-input-text,
.cbi-section-table-row>.cbi-value-field .cbi-input-password {
min-width: 80px;
}
.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,
.cbi-section-table-row>.cbi-value-field input.cbi-input-password {
width: calc(100% - 1.5rem);
@ -1502,6 +1537,13 @@ tr>th,
text-align: center !important;
}
.control-group {
display: inline-flex;
width: 100%;
flex-wrap: wrap;
gap: 2px;
}
div>table>tbody>tr:nth-of-type(2n),
div>.table>.tr:nth-of-type(2n) {
background-color: #f9f9f9;
@ -1553,7 +1595,8 @@ td>table>tbody>tr>td,
font-size: 1.2rem;
display: inline-block;
min-width: 0;
padding: .2rem .3rem;
padding: .2rem 1rem;
font-size: 0;
color: transparent !important;
background: url(../icon/arrow.svg) no-repeat center;
background-size: 12px 20px;
@ -1778,7 +1821,8 @@ td>table>tbody>tr>td,
display: inline-block;
padding: 0.875rem 0rem;
border-bottom: 0.18751rem solid rgba(0, 0, 0, 0);
margin: 0 0.2rem;
margin: 0;
transition: all 0.2s;
a {
text-decoration: none;
@ -1865,6 +1909,9 @@ td>table>tbody>tr>td,
padding: 0.5rem 1.5rem;
}
.cbi-section-node {
padding: 1rem 0;
}
.cbi-section .cbi-section-remove:nth-of-type(2n),
.container>.cbi-section .cbi-section-node:nth-of-type(2n) {
@ -2404,12 +2451,12 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
/* progressbar */
.cbi-progressbar {
position: relative;
min-width: 170px;
height: 20px;
margin: 6px 0;
min-width: 11rem;
height: 1.5rem;
margin: 0 0;
border: thin solid #999;
background: #eee;
border-radius: 0.2rem;
border-radius: 4px;
overflow: hidden;
}
@ -2417,8 +2464,8 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
width: 0;
height: 100%;
transition: width .25s ease-in;
background: #5e72e4;
background: var(--primary);
background: #5bc0de;
background: var(--bar-bg);
}
.cbi-progressbar::after {
@ -2426,11 +2473,11 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child {
font-size: 1em;
font-weight: bold;
font-size-adjust: .38;
line-height: normal;
line-height: 1.5rem;
position: absolute;
top: 2px;
top: 0;
right: 0;
bottom: 2px;
bottom: 0;
left: 0;
overflow: hidden;
content: attr(title);
@ -2596,6 +2643,7 @@ body.modal-overlay-active #modal_overlay {
.cbi-page-actions {
padding-top: 1rem;
text-align: right;
justify-content: flex-end;
}
.cbi-page-actions>form[method="post"] {
@ -2612,10 +2660,12 @@ body.modal-overlay-active #modal_overlay {
.ifacebadge {
display: inline-flex;
gap: .2rem;
padding: .5rem .8rem;
border-bottom: thin solid #ccc;
background: #eee;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
border-radius: 4px;
}
td>.ifacebadge,
@ -2628,7 +2678,6 @@ td>.ifacebadge,
.ifacebadge>img {
display: inline-block;
align-self: flex-start;
margin: 0 .2rem;
}
.ifacebadge>img+img {
@ -2642,13 +2691,16 @@ td>.ifacebadge,
.network-status-table .ifacebox {
flex-grow: 1;
margin: .5em;
border-radius: 4px;
overflow: hidden;
margin: 0 1.25rem 1rem 1.25rem;
}
.network-status-table .ifacebox-body {
display: flex;
flex-direction: column;
height: 100%;
gap: 0.5em;
}
.network-status-table .ifacebox-body>span {
@ -2659,15 +2711,21 @@ td>.ifacebadge,
.network-status-table .ifacebox-body>div {
display: flex;
flex-wrap: wrap;
gap: .5rem;
}
.network-status-table .ifacebox-body .ifacebadge {
align-items: center;
flex: 1 1 auto;
min-width: 220px;
margin: .5em 0em 0 0em;
padding: .5em;
background-color: #fff;
>span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
/* textarea */
@ -2787,7 +2845,9 @@ td>.ifacebadge,
.ifacebox {
line-height: 1.25;
display: inline-flex;
overflow: hidden;
flex-direction: column;
border-radius: 4px;
min-width: 100px;
border-bottom: thin solid #ccc;
background-color: #f9f9f9;
@ -2811,7 +2871,7 @@ td>.ifacebadge,
}
.ifacebox-body {
padding: .5em 1rem;
padding: 0.875rem 1rem;
line-height: 1.6em;
}
@ -2822,6 +2882,7 @@ td>.ifacebadge,
.zonebadge {
display: inline-block;
padding: .2rem .5rem;
border-radius: 4px;
}
.zonebadge .ifacebadge {
@ -2862,17 +2923,17 @@ td>.ifacebadge,
}
.cbi-section-table-row>.cbi-value-field .cbi-dropdown {
min-width: 7rem;
min-width: 3rem;
}
.cbi-section-create {
display: inline-flex;
align-items: center;
margin: 0.25rem 0 0.25rem 1rem;
margin: 0.25rem 1.25rem;
}
.cbi-section-create>* {
margin: .5rem;
margin: .5rem 0;
}
.cbi-section-remove {
@ -2992,6 +3053,11 @@ label[data-index][data-depends] {
content: "";
top: 0;
background-color: rgba(0, 0, 0, .56);
transition: all 0.2s;
&.active {
display: block;
}
}
/* diagnostics */
@ -3773,8 +3839,7 @@ pre.command-output {
}
.cbi-progressbar::after {
font-size: .5rem;
line-height: 1.5;
font-size: .6rem;
}
@ -3783,10 +3848,22 @@ pre.command-output {
position: fixed;
z-index: 100;
width: 0;
&.active {
width: 13rem;
}
}
.main-right {
width: 100%;
&.active {
overflow-y: hidden;
}
}
.darkMask.active {
display: block;
}
.showSide {
@ -3810,7 +3887,7 @@ pre.command-output {
}
header>.fill>.container>.brand {
header>.fill>.container>.flex1>.brand {
display: inline-block;
}
@ -3915,6 +3992,10 @@ pre.command-output {
right: 0 !important;
margin-bottom: 1rem;
}
.login-page .login-container footer {
display: none;
}
}
@ -3979,4 +4060,4 @@ pre.command-output {
}
}
}

View file

@ -1,4 +1,4 @@
// compress: false , sourceMap: false
// compress: true , sourceMap: false
/**
* Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template
*
@ -37,6 +37,9 @@ body {
.login-form {
background-color: #1e1e1e;
-webkit-backdrop-filter: blur(var(--blur-radius-dark));
backdrop-filter: blur(var(--blur-radius-dark));
background-color: rgba(0, 0, 0, var(--blur-opacity-dark));
.brand {
color: #adb5bd;
@ -289,6 +292,12 @@ tr>th,
background-color: #252526;
}
.cbi-rowstyle-2 .cbi-button-up,
.cbi-rowstyle-2 .cbi-button-down,
body:not(.Interfaces) .cbi-rowstyle-2:first-child {
background-color: rgb(102, 102, 102) !important;
}
.cbi-section>h3:first-child,
.panel-title,
h3 {
@ -808,14 +817,7 @@ input,
color: #ccc !important;
}
@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {
.login-page .login-container .login-form {
-webkit-backdrop-filter: blur(var(--blur-radius-dark));
backdrop-filter: blur(var(--blur-radius-dark));
background-color: rgba(0, 0, 0, var(--blur-opacity-dark));
}
}
@media screen and (max-width: 480px) {

View file

@ -1,3 +1,4 @@
// out: false
/*!
Pure v2.0.3
Copyright 2013 Yahoo!

View file

@ -0,0 +1,158 @@
'use strict';
'require baseclass';
'require ui';
return baseclass.extend({
__init__: function () {
ui.menu.load().then(L.bind(this.render, this));
},
render: function (tree) {
var node = tree,
url = '',
children = ui.menu.getChildren(tree);
for (var i = 0; i < children.length; i++) {
var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0);
if (isActive)
this.renderMainMenu(children[i], children[i].name);
}
if (L.env.dispatchpath.length >= 3) {
for (var i = 0; i < 3 && node; i++) {
node = node.children[L.env.dispatchpath[i]];
url = url + (url ? '/' : '') + L.env.dispatchpath[i];
}
if (node)
this.renderTabMenu(node, url);
}
document.querySelector('a.showSide')
.addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle'));
document.querySelector('.darkMask')
.addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle'));
},
handleMenuExpand: function (ev) {
var a = ev.target, slide = a.parentNode, slide_menu = a.nextElementSibling;
var collapse = false;
document.querySelectorAll('.main .main-left .nav > li >ul.active').forEach(function (ul) {
$(ul).stop(true).slideUp("fast", function () {
ul.classList.remove('active');
ul.previousElementSibling.classList.remove('active');
});
if (!collapse && ul === slide_menu) {
collapse = true;
}
});
if (!slide_menu)
return;
if (!collapse) {
$(slide).find(".slide-menu").slideDown("fast",function(){
slide_menu.classList.add('active');
a.classList.add('active');
});
a.blur();
}
ev.preventDefault();
ev.stopPropagation();
},
renderMainMenu: function (tree, url, level) {
var l = (level || 0) + 1,
ul = E('ul', { 'class': level ? 'slide-menu' : 'nav' }),
children = ui.menu.getChildren(tree);
if (children.length == 0 || l > 2)
return E([]);
for (var i = 0; i < children.length; i++) {
var isActive = ((L.env.dispatchpath[l] == children[i].name) && (L.env.dispatchpath[l - 1] == tree.name)),
submenu = this.renderMainMenu(children[i], url + '/' + children[i].name, l),
hasChildren = submenu.children.length,
slideClass = hasChildren ? 'slide' : null,
menuClass = hasChildren ? 'menu' : null;
if (isActive) {
ul.classList.add('active');
slideClass += " active";
menuClass += " active";
}
ul.appendChild(E('li', { 'class': slideClass }, [
E('a', {
'href': L.url(url, children[i].name),
'click': (l == 1) ? ui.createHandlerFn(this, 'handleMenuExpand') : null,
'class': menuClass,
'data-title': hasChildren ? children[i].title.replace(" ", "_") : children[i].title.replace(" ", "_"),
}, [_(children[i].title)]),
submenu
]));
}
if (l == 1) {
document.querySelector('#mainmenu').appendChild(ul);
document.querySelector('#mainmenu').style.display = '';
}
return ul;
},
renderTabMenu: function (tree, url, level) {
var container = document.querySelector('#tabmenu'),
l = (level || 0) + 1,
ul = E('ul', { 'class': 'tabs' }),
children = ui.menu.getChildren(tree),
activeNode = null;
if (children.length == 0)
return E([]);
for (var i = 0; i < children.length; i++) {
var isActive = (L.env.dispatchpath[l + 2] == children[i].name),
activeClass = isActive ? ' active' : '',
className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass);
ul.appendChild(E('li', { 'class': className }, [
E('a', { 'href': L.url(url, children[i].name) }, [_(children[i].title)])
]));
if (isActive)
activeNode = children[i];
}
container.appendChild(ul);
container.style.display = '';
if (activeNode)
container.appendChild(this.renderTabMenu(activeNode, url + '/' + activeNode.name, l));
return ul;
},
handleSidebarToggle: function (ev) {
var showside = document.querySelector('a.showSide'),
sidebar = document.querySelector('#mainmenu'),
darkmask = document.querySelector('.darkMask'),
scrollbar = document.querySelector('.main-right');
if (showside.classList.contains('active')) {
showside.classList.remove('active');
sidebar.classList.remove('active');
scrollbar.classList.remove('active');
darkmask.classList.remove('active');
}
else {
showside.classList.add('active');
sidebar.classList.add('active');
scrollbar.classList.add('active');
darkmask.classList.add('active');
}
}
});

View file

@ -7,13 +7,13 @@
Have a bug? Please create an issue here on GitHub!
https://github.com/jerrykuku/luci-theme-argon/issues
luci-theme-material:
luci-theme-material:
Copyright 2015 Lutty Yang <lutty@wcan.in>
Agron Theme
https://demos.creative-tim.com/argon-dashboard/index.html
https://demos.creative-tim.com/argon-dashboard/index.html
Licensed to the public under the Apache License 2.0
Licensed to the public under the Apache License 2.0
-%>
<% local ver = require "luci.version" %>
@ -41,6 +41,6 @@
}
})
</script>
<script src="<%=media%>/js/script.js"></script>
<script type="text/javascript">L.require('menu-argon')</script>
</body>
</html>

View file

@ -18,12 +18,11 @@
<% local ver = require "luci.version" %>
</div>
<footer class="mobile-hide">
<footer>
<div>
<a class="luci-link" href="https://github.com/openwrt/luci">Powered by <%= ver.luciname %> (<%= ver.luciversion %>)</a> /
<a href="https://github.com/jerrykuku/luci-theme-argon">ArgonTheme <%# vPKG_VERSION %></a> /
<%= ver.distversion %>
<ul class="breadcrumb pull-right" id="modemenu" style="display:none"></ul>
</div>
</footer>
</div>
@ -41,6 +40,5 @@
}
})
</script>
<script src="<%=media%>/js/script.js"></script>
</body>
</html>

View file

@ -21,6 +21,7 @@
local util = require "luci.util"
local http = require "luci.http"
local disp = require "luci.dispatcher"
local ver = require "luci.version"
local boardinfo = util.ubus("system", "board")
@ -81,11 +82,11 @@
<link rel="icon" type="image/png" sizes="32x32" href="<%=media%>/icon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="<%=media%>/icon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%=media%>/icon/favicon-16x16.png">
<link rel="manifest" href="<%=media%>/icon/manifest.json">
<link rel="manifest" href="<%=media%>/icon/manifest.json" crossorigin="use-credentials">
<meta name="msapplication-TileColor" content="<%=bar_color%>">
<meta name="msapplication-TileImage" content="<%=media%>/icon/ms-icon-144x144.png">
<meta name="theme-color" content="<%=bar_color%>">
<link rel="stylesheet" href="<%=media%>/css/cascade.css?v=<%=math.random(1,100000)%>">
<link rel="stylesheet" href="<%=media%>/css/cascade.css<%# ?v=PKG_VERSION %>">
<style title="text/css">
<% if mode == 'normal' then %>
@media (prefers-color-scheme: dark) {
@ -115,110 +116,10 @@
</style>
<% end -%>
<script src="<%=media%>/js/polyfill.min.js"></script>
<script src="<%=url('admin/translations', luci.i18n.context.lang)%>?v=2.2.4"></script>
<script src="<%=resource%>/cbi.js?v=2.2.4"></script>
<script src="<%=resource%>/luci.js?v=2.2.4"></script>
<script src="<%=media%>/js/jquery.min.js?v=2.2.4"></script>
<script type="text/javascript">//<![CDATA[
function EF() { return L.dom.create.apply(L.dom, arguments) }
(function() {
function get_children(node) {
var children = [];
for (var k in node.children) {
if (!node.children.hasOwnProperty(k))
continue;
if (!node.children[k].satisfied)
continue;
if (!node.children[k].hasOwnProperty('title'))
continue;
children.push(Object.assign(node.children[k], { name: k }));
}
return children.sort(function(a, b) {
return ((a.order || 1000) - (b.order || 1000));
});
}
function render_mainmenu(tree, url, level) {
var l = (level || 0) + 1,
ul = EF('ul', { 'class': level ? 'slide-menu' : 'nav' }),
children = get_children(tree);
if (children.length == 0 || l > 2)
return EF([]);
for (var i = 0; i < children.length; i++) {
var submenu = render_mainmenu(children[i], url + '/' + children[i].name, l),
hasChildren = submenu.children.length;
ul.appendChild(EF('li', { 'class': hasChildren ? 'slide' : null }, [
EF('a', {
'href': hasChildren ? '#' : L.url(url, children[i].name),
'class': hasChildren ? 'menu' : null,
'data-title': hasChildren ? children[i].title.replace(" ", "_") : children[i].title.replace(" ", "_"),
}, [ _(children[i].title) ]),
submenu
]));
}
if (l == 1) {
var container = document.querySelector('#mainmenu');
container.appendChild(ul);
container.style.display = '';
}
return ul;
}
function render_modemenu(tree) {
var ul = document.querySelector('#modemenu'),
children = get_children(tree);
for (var i = 0; i < children.length; i++) {
var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0);
ul.appendChild(EF('li', {}, [
EF('a', {
'href': L.url(children[i].name),
'class': isActive ? 'active' : null
}, [ _(children[i].title) ])
]));
if (isActive)
render_mainmenu(children[i], children[i].name);
}
if (ul.children.length > 1)
ul.style.display = '';
}
function render_tabmenu(tree, url, level) {
var container = document.querySelector('#tabmenu'),
l = (level || 0) + 1,
ul = EF('ul', { 'class': 'tabs' }),
children = get_children(tree),
activeNode = null;
if (children.length == 0)
return EF([]);
for (var i = 0; i < children.length; i++) {
var isActive = (L.env.dispatchpath[l + 2] == children[i].name),
activeClass = isActive ? ' active' : '',
className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass);
ul.appendChild(EF('li', { 'class': className }, [
EF('a', { 'href': L.url(url, children[i].name) }, [ _(children[i].title) ] )
]));
if (isActive)
activeNode = children[i];
}
container.appendChild(ul);
container.style.display = '';
if (activeNode)
container.appendChild(render_tabmenu(activeNode, url + '/' + activeNode.name, l));
return ul;
}
document.addEventListener('luci-loaded', function(ev) {
var tree = <%= luci.http.write_json(luci.dispatcher.menu_json() or {}) %>,
node = tree,
url = '';
render_modemenu(tree);
if (L.env.dispatchpath.length >= 3) {
for (var i = 0; i < 3 && node; i++) {
node = node.children[L.env.dispatchpath[i]];
url = url + (url ? '/' : '') + L.env.dispatchpath[i];
}
if (node)
render_tabmenu(node, url);
}
});
})();
//]]></script>
<script src="<%=url('admin/translations', luci.i18n.context.lang)%>?v=<%=ver.luciversion%>"></script>
<script src="<%=resource%>/cbi.js?v=<%=ver.luciversion%>"></script>
<script src="<%=resource%>/luci.js?v=<%=ver.luciversion%>"></script>
<script src="<%=media%>/js/jquery.min.js?v=3.5.1"></script>
</head>
<body
@ -246,14 +147,11 @@
<header class="bg-primary">
<div class="fill">
<div class="container">
<a class="showSide"></a>
<a class="brand" href="#"><%=brand_name%></a>
<div class="status" id="indicators">
<span id="xhr_poll_status" style="display:none" onclick="XHR.running() ? XHR.halt() : XHR.run()">
<span class="label success" id="xhr_poll_status_on"><span class="mobile-hide"><%:Auto Refresh%></span> <%:on%></span>
<span class="label" id="xhr_poll_status_off" style="display:none"><span class="mobile-hide"><%:Auto Refresh%></span> <%:off%></span>
</span>
</div>
<div class="flex1">
<a class="showSide"></a>
<a class="brand" href="#"><%=brand_name%></a>
</div>
<div class="status" id="indicators"></div>
</div>
</div>
</header>

View file

@ -21,6 +21,7 @@
local util = require "luci.util"
local http = require "luci.http"
local disp = require "luci.dispatcher"
local ver = require "luci.version"
local boardinfo = util.ubus("system", "board")
@ -78,11 +79,11 @@
<link rel="icon" type="image/png" sizes="32x32" href="<%=media%>/icon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="<%=media%>/icon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%=media%>/icon/favicon-16x16.png">
<link rel="manifest" href="<%=media%>/icon/manifest.json">
<link rel="manifest" href="<%=media%>/icon/manifest.json" crossorigin="use-credentials">
<meta name="msapplication-TileColor" content="<%=bar_color%>">
<meta name="msapplication-TileImage" content="<%=media%>/icon/ms-icon-144x144.png">
<meta name="theme-color" content="<%=bar_color%>">
<link rel="stylesheet" href="<%=media%>/css/cascade.css?v=<%=math.random(1,100000)%>">
<link rel="stylesheet" href="<%=media%>/css/cascade.css<%# ?v=PKG_VERSION %>">
<style title="text/css">
<% if mode == 'normal' then %>
@media (prefers-color-scheme: dark) {
@ -111,13 +112,8 @@
<%=css %>
</style>
<% end -%>
<script src="<%=url('admin/translations', luci.i18n.context.lang)%><%# ?v=PKG_VERSION %>"></script>
<script src="<%=resource%>/cbi.js<%# ?v=PKG_VERSION %>"></script>
<script src="<%=resource%>/xhr.js<%# ?v=PKG_VERSION %>"></script>
<script src="<%=media%>/js/jquery.min.js<%# ?v=PKG_VERSION %>"></script>
<script src="<%=media%>/js/jquery.min.js?v=3.5.1"></script>
</head>
<body
class="lang_<%=luci.i18n.context.lang%> <% if node then %><%= striptags( node.title ) %><% end %> <% if luci.dispatcher.context.authsession then %>logged-in<% end %>"
data-page="<%= table.concat(disp.context.requestpath, "-") %>">
<body>

View file

@ -5,34 +5,10 @@
-%>
<%
local ver = require "luci.version"
if not luci.dispatcher.context.template_header_sent then
include("themes/" .. theme .. "/header_login")
luci.dispatcher.context.template_header_sent = true
end
local applyconf = luci.config and luci.config.apply
%>
<script type="text/javascript" src="<%=resource%>/promis.min.js"></script>
<script type="text/javascript" src="<%=resource%>/luci.js"></script>
<script type="text/javascript">
L = new LuCI(<%= luci.http.write_json({
token = token,
media = media,
resource = resource,
scriptname = luci.http.getenv("SCRIPT_NAME"),
pathinfo = luci.http.getenv("PATH_INFO"),
documentroot = luci.http.getenv("DOCUMENT_ROOT"),
requestpath = luci.dispatcher.context.requestpath,
dispatchpath = luci.dispatcher.context.path,
pollinterval = luci.config.main.pollinterval or 5,
ubuspath = luci.config.main.ubuspath or '/ubus/',
sessionid = luci.dispatcher.context.authsession,
nodespec = luci.dispatcher.context.dispatched,
apply_rollback = math.max(applyconf and applyconf.rollback or 90, 90),
apply_holdoff = math.max(applyconf and applyconf.holdoff or 4, 1),
apply_timeout = math.max(applyconf and applyconf.timeout or 5, 1),
apply_display = math.max(applyconf and applyconf.display or 1.5, 1),
rollback_token = rollback_token
}) %>);
</script>

View file

@ -23,12 +23,16 @@
<%+themes/argon/out_header_login%>
<%
local util = require "luci.util"
local boardinfo = util.ubus("system", "board")
local fs = require "nixio.fs"
local nutil = require "nixio.util"
local util = require "luci.util"
local fs = require "nixio.fs"
local nutil = require "nixio.util"
local json = require "luci.jsonc"
local sys = require "luci.sys"
local uci = require 'luci.model.uci'.cursor()
function glob(...)
-- Fetch Local Background Media
local function glob(...)
local iter, code, msg = fs.glob(...)
if iter then
return nutil.consume(iter)
@ -37,37 +41,69 @@
end
end
function getExtension(str)
return str:match(".+%.(%w+)$")
end
local bgcount = 0
local currentBg = {}
local bgs,attr = {}
local theme_dir = media .. "/background/"
for i, f in ipairs(glob("/www" .. theme_dir .. "*")) do
attr = fs.stat(f)
if attr then
local ext = getExtension(fs.basename(f))
if ext == "jpg" or ext == "png" or ext == "gif" or ext == "mp4" then
local bg = {}
bg.type = ext
bg.url = theme_dir .. fs.basename(f)
table.insert(bgs,bg)
bgcount = bgcount + 1
local imageTypes = " jpg png gif "
local videoTypes = " mp4 webm "
local allTypes = imageTypes .. videoTypes
local function fetchMedia(path,themeDir)
local backgroundTable = {}
local backgroundCount = 0
for i, f in ipairs(glob(path)) do
attr = fs.stat(f)
if attr then
local ext = fs.basename(f):match(".+%.(%w+)$")
if ext ~= nil then
ext = ext:lower()
end
if ext ~= nil and string.match(allTypes, " "..ext.." ") ~= nil then
local bg = {}
bg.type = ext
bg.url = themeDir .. fs.basename(f)
table.insert(backgroundTable,bg)
backgroundCount = backgroundCount + 1
end
end
end
return backgroundTable,backgroundCount
end
local function selectBackground(themeDir)
local bgUrl = media .. "/img/bg1.jpg"
local backgroundType = "Image"
local mimeType = ""
if fs.access("/etc/config/argon") then
if uci:get_first('argon', 'global', 'bing_background') == "1" then
local bing = sys.exec("/usr/libexec/argon/bing_wallpaper")
if (bing and bing ~= '') then
return bing, "Image", ""
end
end
end
local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*",themeDir)
if ( backgroundCount > 0 ) then
local currentBg = backgroundTable[math.random(1,backgroundCount)]
bgUrl = currentBg.url
if (string.match(videoTypes, " "..currentBg.type.." ") ~= nil) then
backgroundType = "Video"
mimeType = "video/" .. currentBg.type
end
end
return bgUrl,backgroundType,mimeType
end
if bgcount > 0 then
currentBg = bgs[math.random(1,bgcount)]
end
local boardinfo = util.ubus("system", "board")
local themeDir = media .. "/background/"
local bgUrl,backgroundType,mimeType = selectBackground(themeDir)
%>
<!-- Login Page Start -->
<div class="login-page">
<% if (bgcount > 0 and currentBg.type == "mp4") then %>
<% if ( backgroundType == "Video" ) then %>
<!-- Video Player Start -->
<div class="video">
<video autoplay loop muted id="video">
<source src="<%=currentBg.url%>" type="video/mp4">
<source src="<%=bgUrl%>" type="<%=mimeType%>">
</video>
</div>
<div class="volume-control mute"></div>
@ -82,28 +118,21 @@
}
})
</script>
<% else
local bg_url = media .. "/img/bg1.jpg"
local bing = "123"
if (bgcount == 0 ) then
local sys = require "luci.sys"
local json = require "luci.jsonc"
local remote_bg_url="http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US"
--bing = sys.httpget(remote_bg_url)
bing = sys.exec("wget --timeout=0.5 -qO- '%s'" %remote_bg_url)
if (bing and bing ~= '') then
bg_url = "https://www.bing.com" .. json.parse(bing).images[1].url
end
elseif (bgcount > 0 and currentBg["type"] ~= "mp4") then
bg_url = currentBg.url
end
%>
<div class="main-bg" id="main-bg" style="background-image:url(<%=bg_url%>)"></div>
<!-- Video Player End -->
<% else %>
<!-- Image Background Start -->
<div class="main-bg" id="main-bg" style="background-image:url(<%=bgUrl%>)"></div>
<!-- Image Background End -->
<% end %>
<!-- Login Container Start -->
<div class="login-container">
<div class="login-form">
<a class="brand" href="/"><img src="<%=media%>/img/argon.svg" class="icon"><span
class="brand-text"><%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %></span></a>
<!-- Logo Start -->
<a class="brand" href="/"><img src="<%=media%>/img/argon.svg" class="icon">
<span class="brand-text"><%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %></span>
</a>
<!-- Logo End -->
<!-- Login Form Start -->
<form class="form-login" method="post" action="<%=pcdata(luci.http.getenv("REQUEST_URI"))%>">
<%- if fuser then %>
@ -124,7 +153,7 @@
<input type="submit" value="<%:Login%>" class="cbi-button cbi-button-apply" />
</div>
</form>
<!-- Login Form End -->
<script type="text/javascript">//<![CDATA[
var input = document.getElementsByName('luci_password')[0];
if (input)

View file

@ -0,0 +1,52 @@
#!/bin/sh
# author jjm2473
BING_BASE=http://www.bing.com
CACHE=/var/run/argon_bing.url
WRLOCK=/var/lock/argon_bing.lock
fetch_url_path() {
curl --fail --show-error --max-time 1 \
"$BING_BASE/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US" 2>/dev/null \
| jsonfilter -q -e '@.images[0].url'
}
try_update() {
local lock="$WRLOCK"
exec 200>$lock
if flock -n 200 >/dev/null 2>&1; then
local path=`fetch_url_path`
if [ -n "$path" ]; then
echo "${BING_BASE}${path}" | tee "$CACHE"
else
if [ -s "$CACHE" ]; then
cat "$CACHE"
else
touch "$CACHE"
fi
fi
flock -u 200 >/dev/null 2>&1
elif [ -s "$CACHE" ]; then
cat "$CACHE"
fi
}
get_url() {
if [ -f "$CACHE" ]; then
local idle_t=$((`date '+%s'` - `date -r "$CACHE" '+%s' 2>/dev/null || echo '0'`))
if [ -s "$CACHE" ]; then
if [ $idle_t -le 43200 ]; then
cat "$CACHE"
return
fi
else
if [ $idle_t -le 120 ]; then
return
fi
fi
fi
try_update
}
get_url

View file

@ -10,13 +10,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=mptcpd
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/intel/mptcpd.git
PKG_SOURCE_VERSION:=0e7175adf721c95a3bd742be77cb85e0b47138cd
PKG_VERSION:=0.7-$(PKG_SOURCE_VERSION)
PKG_SOURCE_VERSION:=df4ea048cd3821f749bf06e0d01bb7d79faac812
PKG_VERSION:=0.9-$(PKG_SOURCE_VERSION)
PKG_RELEASE:=1
PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
PKG_FIXUP:=autoreconf
PKG_FORTIFY_SOURCE:=2
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
@ -36,7 +34,16 @@ define Package/$(PKG_NAME)/conffiles
/etc/mptcpd/mptcpd.conf
endef
TARGET_CFLAGS += -D_GNU_SOURCE -Wno-unused-result -Wno-format-nonliteral
CONFIGURE_ARGS += \
--disable-doxygen-doc \
--disable-logging
TARGET_CFLAGS += -Wno-unused-result -Wno-format-nonliteral
define Build/Prepare
$(Build/Prepare/Default)
( cd $(PKG_BUILD_DIR); $(AM_TOOL_PATHS) ./bootstrap )
endef
define Build/Compile
+$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS)

View file

@ -1,167 +0,0 @@
--- a/src/configuration.c 2021-06-29 17:44:20.481179981 +0200
+++ b/src/configuration.c 2021-06-29 17:44:52.580655950 +0200
@@ -37,21 +37,12 @@
* Preprocessor concatenation that expands preprocessor tokens as
* needed by leveraging the usual indirection technique.
*/
-///@{
-/// Underlying string concatenation macro.
-#define MPTCPD_CONCAT_IMPL(x, ...) x ## __VA_ARGS__
-
-/// Concatenate strings using the preprocessor.
-#define MPTCPD_CONCAT(x, ...) MPTCPD_CONCAT_IMPL(x, __VA_ARGS__)
-///@}
// Compile-time default logging choice
#ifndef MPTCPD_LOGGER
// This should never occur!
# error Problem configuring default log message destination.
#endif
-/// Name of the default logging function determined at compile-time.
-#define MPTCPD_SET_LOG_FUNCTION MPTCPD_CONCAT(l_log_set_, MPTCPD_LOGGER)
/**
* @brief Get the function that sets the log message destination.
@@ -474,7 +465,6 @@
struct mptcpd_config *mptcpd_config_create(int argc, char *argv[])
{
- MPTCPD_SET_LOG_FUNCTION(); // For early logging.
struct mptcpd_config *const config =
l_new(struct mptcpd_config, 1);
--- a/src/mptcpize.c 2021-06-29 19:29:57.810281053 +0200
+++ b/src/mptcpize.c 2021-06-29 19:29:29.942701557 +0200
@@ -17,7 +17,6 @@
#include <argp.h>
#include <dlfcn.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -79,7 +78,7 @@
nr++;
envp = calloc(nr + 3, sizeof(char *));
if (!envp)
- error(1, errno, "can't allocate env list");
+ fprintf(stderr, "can't allocate env list");
// ... filtering out any 'LD_PRELOAD' ...
nr = 0;
@@ -103,7 +102,7 @@
// build the NULL terminated arg list
argv = calloc(argc + 1, sizeof(char *));
if (!argv)
- error(1, errno, "can't allocate argument list");
+ fprintf(stderr, "can't allocate argument list");
memcpy(argv, av, argc * sizeof(char*));
return execvpe(argv[0], argv, envp);
@@ -124,33 +123,33 @@
len = strlen(name) + 1 + strlen(SYSTEMCTL_SHOW);
cmd = malloc(len);
if (!cmd)
- error(1, 0, "can't allocate systemctl command string");
+ fprintf(stderr, "can't allocate systemctl command string");
sprintf(cmd, SYSTEMCTL_SHOW"%s", name);
systemctl = popen(cmd, "r");
if (!systemctl)
- error(1, errno, "can't execute %s", cmd);
+ fprintf(stderr, "can't execute %s", cmd);
free(cmd);
while ((read = getline(&line, &len, systemctl)) != -1) {
if (strncmp(line, SYSTEMD_UNIT_VAR, strlen(SYSTEMD_UNIT_VAR)) == 0) {
char *ret = strdup(&line[strlen(SYSTEMD_UNIT_VAR)]);
if (!ret)
- error(1, errno, "failed to duplicate string");
+ fprintf(stderr, "failed to duplicate string");
// trim trailing newline, if any
len = strlen(ret);
if (len > 0 && ret[len - 1] == '\n')
ret[--len] = 0;
if (len == 0)
- error(1, 0, "can't find unit file for service %s", name);
+ fprintf(stderr, "can't find unit file for service %s", name);
free(line);
pclose(systemctl);
return ret;
}
}
- error(1, 0, "can't find FragmentPath attribute for unit %s", name);
+ fprintf(stderr, "can't find FragmentPath attribute for unit %s", name);
// never reached: just silence gcc
return NULL;
@@ -175,12 +174,12 @@
unit = locate_unit(argv[0]);
src = fopen(unit, "r");
if (!src)
- error(1, errno, "can't open file %s", unit);
+ fprintf(stderr, "can't open file %s", unit);
strcpy(dst_path, "/tmp/unit_XXXXXX");
dst = mkstemp(dst_path);
if (dst < 0)
- error(1, errno, "can't create tmp file");
+ fprintf(stderr, "can't create tmp file");
// reset any prior error, to allow later check on errno
errno = 0;
@@ -194,27 +193,27 @@
if (!is_env) {
if (write(dst, line, read) < 0)
- error(1, errno, "can't write '%s' into %s", line, dst_path);
+ fprintf(stderr, "can't write '%s' into %s", line, dst_path);
}
if (append_env &&
(is_env || strncmp(line, SYSTEMD_SERVICE_TAG, strlen(SYSTEMD_SERVICE_TAG)) == 0)) {
if (dprintf(dst, "%s%s\n", SYSTEMD_ENV_VAR, MPTCPWRAP_ENV) < 0)
- error(1, errno, "can't write to env string into %s", dst_path);
+ fprintf(stderr, "can't write to env string into %s", dst_path);
append_env = 0;
}
}
if (errno != 0)
- error(1, errno, "can't read from %s", unit);
+ fprintf(stderr, "can't read from %s", unit);
free(line);
fclose(src);
close(dst);
if (rename(dst_path, unit) < 0)
- error(1, errno, "can't rename %s to %s", dst_path, unit);
+ fprintf(stderr, "can't rename %s to %s", dst_path, unit);
if (system("systemctl daemon-reload") != 0)
- error(1, errno, "can't reload unit, manual 'systemctl daemon-reload' is required");
+ fprintf(stderr, "can't reload unit, manual 'systemctl daemon-reload' is required");
printf("mptcp successfully %s on unit %s\n",
enable ? "enabled" : "disabled", unit);
@@ -239,7 +238,7 @@
argp_program_version = "mptcpize "VERSION;
argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, &idx, 0) < 0)
- error(1, errno, "can't parse arguments");
+ fprintf(stderr, "can't parse arguments");
argc -= idx;
argv += idx;
--- a/src/mptcpize.c 2021-07-05 20:06:07.035838944 +0200
+++ b/src/mptcpize.c 2021-07-05 20:06:26.875505617 +0200
@@ -7,8 +7,6 @@
* Copyright (c) 2021, Red Hat, Inc.
*/
-#define _GNU_SOURCE
-
#include <linux/limits.h>
#include <sys/types.h>

View file

@ -0,0 +1,16 @@
--- a/src/error.h
+++ b/src/error.h
@@ -0,0 +1,13 @@
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// mimic the behaviour of https://man7.org/linux/man-pages/man3/error.3.html
+void error(int status, int errnum, const char *format, ...)
+{
+ fprintf(stderr, "Error %d: %s", errnum, format);
+ if (status != 0) exit(status);
+}
+#endif