From 7849f05687fec1741aa79af0d51149f7e73a4ab5 Mon Sep 17 00:00:00 2001 From: sbwml Date: Wed, 6 Nov 2024 04:41:25 +0800 Subject: [PATCH] luci-app-webdav: new package Signed-off-by: sbwml --- Makefile | 20 +++ README.md | 3 + htdocs/luci-static/resources/view/webdav.js | 112 ++++++++++++++++ po/zh_Hans/webdav.po | 47 +++++++ root/etc/config/webdav | 8 ++ root/etc/init.d/webdav | 125 ++++++++++++++++++ .../share/luci/menu.d/luci-app-webdav.json | 21 +++ .../usr/share/rpcd/acl.d/luci-app-webdav.json | 11 ++ root/usr/share/ucitrack/luci-app-webdav.json | 4 + 9 files changed, 351 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 htdocs/luci-static/resources/view/webdav.js create mode 100644 po/zh_Hans/webdav.po create mode 100644 root/etc/config/webdav create mode 100755 root/etc/init.d/webdav create mode 100644 root/usr/share/luci/menu.d/luci-app-webdav.json create mode 100644 root/usr/share/rpcd/acl.d/luci-app-webdav.json create mode 100644 root/usr/share/ucitrack/luci-app-webdav.json diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..654c2fc --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Copyright (C) 2019 Openwrt.org +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-webdav +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +LUCI_TITLE:=LuCI support for WebDav +LUCI_PKGARCH:=all +LUCI_DEPENDS:=+nginx-mod-dav-ext + +PKG_MAINTAINER:=sbwml + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/README.md b/README.md new file mode 100644 index 0000000..e6ce2b0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# luci-app-webdav - openwrt-24.10 + +A lightweight, simple, and fast WebDAV server based on NGINX. diff --git a/htdocs/luci-static/resources/view/webdav.js b/htdocs/luci-static/resources/view/webdav.js new file mode 100644 index 0000000..f5d0d87 --- /dev/null +++ b/htdocs/luci-static/resources/view/webdav.js @@ -0,0 +1,112 @@ +'use strict'; +'require form'; +'require poll'; +'require uci'; +'require view'; + +function renderStatus(isEnable, webport, protocol) { + var spanTemp = '%s %s'; + var renderHTML; + if (isEnable === '1') { + var button = String.format('', + _('Open Web Interface'), protocol, window.location.hostname, webport); + renderHTML = spanTemp.format('green', _('WebDAV'), _('RUNNING')) + button; + } else { + renderHTML = spanTemp.format('red', _('WebDAV'), _('NOT RUNNING')); + } + + return renderHTML; +} + +return view.extend({ + load: function() { + return Promise.all([ + uci.load('webdav') + ]); + }, + + handleDownloadReg: function (m, section_id, ev) { + const regContent = `Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\WebClient\\Parameters] +"BasicAuthLevel"=dword:00000002 +"FileSizeLimitInBytes"=dword:ffffffff +`; + const blob = new Blob([regContent], { type: 'text/plain' }); + const link = document.createElement('a'); + link.download = 'allow_http.reg'; + link.href = window.URL.createObjectURL(blob); + link.click(); + }, + + render: function(data) { + var m, s, o; + var webport = uci.get(data[0], 'config', 'listen_port'); + var isEnable = uci.get(data[0], 'config', 'enable'); + var ssl = uci.get(data[0], 'config', 'ssl') || '0'; + var protocol; + if (ssl === '0') { + protocol = 'http:'; + } else if (ssl === '1') { + protocol = 'https:'; + } + + m = new form.Map('webdav', _('WebDAV'), + _('A lightweight, simple, and fast WebDAV server based on NGINX.')); + + s = m.section(form.TypedSection); + s.anonymous = true; + s.render = function () { + setTimeout(function () { + poll.add(function () { + var view = document.getElementById('service_status'); + if (view) { + view.innerHTML = renderStatus(isEnable, webport, protocol); + } + }); + }, 100); + + return E('div', { class: 'cbi-section', id: 'status_bar' }, [ + E('p', { id: 'service_status' }, _('Collecting data...')) + ]); + } + + s = m.section(form.NamedSection, 'config', 'webdav'); + + o = s.option(form.Flag, 'enable', _('Enable')); + o.rmempty = false; + + o = s.option(form.Value, 'listen_port', _('Listen Port')); + o.default = 6086; + o.rmempty = false; + + o = s.option(form.Value, 'username', _('Username'), _("Leave blank to disable auth.")); + + o = s.option(form.Value, 'password', _('Password'), _("Leave blank to disable auth.")); + + o = s.option(form.Value, 'root_dir', _('Root Directory')); + o.default = '/mnt'; + o.rmempty = false; + + o = s.option(form.Flag, 'allow_wan', _('Allow Access From Internet')); + o.rmempty = false; + + o = s.option(form.Flag, 'ssl', _('Enable SSL')); + o.rmempty = false; + + o = s.option(form.Value, 'cert_cer', _('Path to Certificate')); + o.depends('ssl', '1'); + + o = s.option(form.Value, 'cert_key', _('Path to Certificate Key')); + o.depends('ssl', '1'); + + o = s.option(form.Button, '_downloadreg', null, + _('Windows doesn\'t allow HTTP auth by default, you need to import this reg key to enable it (Reboot needed).')); + o.title = _('Download Reg File'); + o.inputtitle = _('Click Download'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleDownloadReg, this, m); + + return m.render(); + } +}); diff --git a/po/zh_Hans/webdav.po b/po/zh_Hans/webdav.po new file mode 100644 index 0000000..72ef05a --- /dev/null +++ b/po/zh_Hans/webdav.po @@ -0,0 +1,47 @@ +msgid "WebDav" +msgstr "WebDav" + +msgid "A lightweight, simple, and fast WebDAV server based on NGINX." +msgstr "基于 NGINX 实现的一个轻巧、简单、快速的 WebDav 服务端。" + +msgid "Open Web Interface" +msgstr "打开 Web 界面" + +msgid "Enable" +msgstr "启用" + +msgid "Listen Port" +msgstr "监听端口" + +msgid "Username" +msgstr "用户名" + +msgid "Password" +msgstr "密码" + +msgid "Leave blank to disable auth." +msgstr "留空以禁用身份验证。" + +msgid "Root Directory" +msgstr "开放目录" + +msgid "Allow Access From Internet" +msgstr "允许从外网访问" + +msgid "Enable SSL" +msgstr "启用 SSL" + +msgid "Path to Certificate" +msgstr "证书位置" + +msgid "Path to Certificate Key" +msgstr "密钥位置" + +msgid "Download Reg File" +msgstr "下载注册表文件" + +msgid "Click Download" +msgstr "点击下载" + +msgid "Windows doesn't allow HTTP auth by default, you need to import this reg key to enable it (Reboot needed)." +msgstr "Windows 系统默认不允许 HTTP 鉴权,您需要手动导入注册表文件以开启此功能(需重启)。" diff --git a/root/etc/config/webdav b/root/etc/config/webdav new file mode 100644 index 0000000..a56ec5d --- /dev/null +++ b/root/etc/config/webdav @@ -0,0 +1,8 @@ + +config webdav 'config' + option allow_wan '0' + option enable '0' + option listen_port '5005' + option root_dir '/mnt' + option ssl '0' + diff --git a/root/etc/init.d/webdav b/root/etc/init.d/webdav new file mode 100755 index 0000000..2f1bf51 --- /dev/null +++ b/root/etc/init.d/webdav @@ -0,0 +1,125 @@ +#!/bin/sh /etc/rc.common + +START=90 + +NGINX="/usr/sbin/nginx" +NGINX_CONF="/etc/nginx/uci.conf" +NGINX_DAV_CONF="/etc/nginx/conf.d/webdav.conf" +NGINX_DAV_PASSWORD="/etc/nginx/webdav.password" + +get_config() { + config_load webdav + config_get "enable" "config" "enable" "0" + config_get "listen_port" "config" "listen_port" "5005" + config_get "username" "config" "username" + config_get "password" "config" "password" + config_get "root_dir" "config" "root_dir" "/mnt" + config_get "allow_wan" "config" "allow_wan" "0" + config_get "ssl" "config" "ssl" "0" + config_get "cert_cer" "config" "cert_cer" "" + config_get "cert_key" "config" "cert_key" "" + config_load network + config_get lan_addr lan ipaddr "0.0.0.0" + if echo "${lan_addr}" | grep -Fq ' '; then + lan_addr="0.0.0.0" + else + lan_addr=${lan_addr%%/*} + fi +} + +set_firewall() { + if [ "$external_access" = "allow" ]; then + uci -q delete firewall.webdav + uci set firewall.webdav=rule + uci set firewall.webdav.name="webdav" + uci set firewall.webdav.target="ACCEPT" + uci set firewall.webdav.src="wan" + uci set firewall.webdav.proto="tcp" + uci set firewall.webdav.dest_port="$listen_port" + uci set firewall.webdav.enabled="1" + uci commit firewall + /etc/init.d/firewall reload >/dev/null 2>&1 + elif [ "$external_access" = "deny" ]; then + uci -q delete firewall.webdav + uci commit firewall + /etc/init.d/firewall reload >/dev/null 2>&1 + fi +} + +start() { + get_config + [ "$enable" -ne "1" ] && return 1 + [ ! -d "$root_dir" ] && mkdir -p "$root_dir" + if [ "$allow_wan" -eq "1" ]; then + listen_addr="0.0.0.0" + external_access="allow" + else + listen_addr="$lan_addr" + external_access="deny" + fi + set_firewall + { + printf "server {" + if [ "$ssl" -eq "1" ]; then + printf "\n\tlisten ${listen_addr}:${listen_port} ssl;" + printf "\n\thttp2 on;" + else + printf "\n\tlisten ${listen_addr}:${listen_port};" + fi + + printf "\n\tserver_name _;" + printf "\n\tcharset utf-8,gbk;" + printf "\n\troot ${root_dir};" + printf "\n\taccess_log off;" + printf "\n\terror_log off;" + if [ "$ssl" -eq "1" ]; then + # SSL Certificate + printf "\n\tssl_certificate ${cert_cer};" + printf "\n\tssl_certificate_key ${cert_key};" + printf "\n\tssl_session_timeout 1d;" + printf "\n\tssl_session_tickets on;" + printf "\n\tssl_session_cache shared:SSL:10m;" + # modern configuration + printf "\n\tssl_protocols TLSv1.2 TLSv1.3;" + printf "\n\tssl_prefer_server_ciphers off;" + printf "\n\tssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;" + fi + printf "\n\tlocation / {" + printf "\n\t\tautoindex on;" + printf "\n\t\tautoindex_exact_size off;" + printf "\n\t\tautoindex_localtime on;" + if [ -n "$username" ] && [ -n "$password" ]; then + printf "$username:$(openssl passwd -apr1 $password)" > "$NGINX_DAV_PASSWORD" + printf "\n\t\tauth_basic "Restricted";" + printf "\n\t\tauth_basic_user_file ${NGINX_DAV_PASSWORD};" + fi + printf "\n\t\tclient_max_body_size 0;" + printf "\n\t\tcreate_full_put_path on;" + printf "\n\t\tdav_access user:rw group:rw all:r;" + printf "\n\t\tdav_ext_methods PROPFIND OPTIONS;" + printf "\n\t\tdav_methods PUT DELETE MKCOL COPY MOVE;" + printf "\n\t}" + printf "\n}\n" + } > "${NGINX_DAV_CONF}" + local message + message="$(${NGINX} -t -c "${NGINX_CONF}" 2>&1)" || + { + echo -e "${message}" | logger -t "nginx_dav" -p "daemon.err" + logger -s -t "nginx_dav" -p "daemon.err" "configuration file ${NGINX_CONF} test failed!" + echo "show config to be used by: nginx -T -c '${NGINX_CONF}'" >&2 + exit 1 + } + /etc/init.d/nginx reload +} + +stop() { + rm -f "${NGINX_DAV_CONF}" "${NGINX_DAV_PASSWORD}" + /etc/init.d/nginx reload + external_access="deny" + set_firewall +} + +restart() { + stop + start +} diff --git a/root/usr/share/luci/menu.d/luci-app-webdav.json b/root/usr/share/luci/menu.d/luci-app-webdav.json new file mode 100644 index 0000000..73c6b60 --- /dev/null +++ b/root/usr/share/luci/menu.d/luci-app-webdav.json @@ -0,0 +1,21 @@ +{ + "admin/nas": { + "title": "NAS", + "order": 44, + "action": { + "type": "firstchild" + } + }, + "admin/nas/webdav": { + "title": "WebDAV", + "order": 90, + "action": { + "type": "view", + "path": "webdav" + }, + "depends": { + "acl": [ "luci-app-webdav" ], + "uci": { "webdav": true } + } + } +} diff --git a/root/usr/share/rpcd/acl.d/luci-app-webdav.json b/root/usr/share/rpcd/acl.d/luci-app-webdav.json new file mode 100644 index 0000000..eba5b41 --- /dev/null +++ b/root/usr/share/rpcd/acl.d/luci-app-webdav.json @@ -0,0 +1,11 @@ +{ + "luci-app-webdav": { + "description": "Grant UCI access for luci-app-webdav", + "read": { + "uci": [ "webdav" ] + }, + "write": { + "uci": [ "webdav" ] + } + } +} diff --git a/root/usr/share/ucitrack/luci-app-webdav.json b/root/usr/share/ucitrack/luci-app-webdav.json new file mode 100644 index 0000000..829b9b3 --- /dev/null +++ b/root/usr/share/ucitrack/luci-app-webdav.json @@ -0,0 +1,4 @@ +{ + "config": "webdav", + "init": "webdav" +}