luci-app-radicale: bump to version 1.1.0
- support Radicale > v1.1 - modified version detection - adaption to new function version_compare() in ipkg.lua - adaption to fixed Flag.parse() in cbi.lua - adaption to new property map.tabbed in cbi.lua using map template with extensions - change optional values to non optional - add support new option "system.boot_delay" Signed-off-by: Christian Schoenebeck <christian.schoenebeck@gmail.com>
This commit is contained in:
parent
26d009aff9
commit
026ac8d033
9 changed files with 485 additions and 341 deletions
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (C) 2008-2015 The LuCI Team <luci@lists.subsignal.org>
|
||||
# Copyright (C) 2008-2016 The LuCI Team <luci@lists.subsignal.org>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
@ -10,7 +10,7 @@ PKG_NAME:=luci-app-radicale
|
|||
|
||||
# Version == major.minor.patch
|
||||
# increase "minor" on new functionality and "patch" on patches/optimization
|
||||
PKG_VERSION:=1.0.2
|
||||
PKG_VERSION:=1.1.0
|
||||
|
||||
# Release == build
|
||||
# increase on changes of translation files
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
-- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
|
||||
-- Copyright 2014-2016 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
|
||||
-- Licensed under the Apache License, Version 2.0
|
||||
|
||||
module("luci.controller.radicale", package.seeall)
|
||||
|
||||
local NX = require("nixio")
|
||||
local NXFS = require("nixio.fs")
|
||||
local DISP = require "luci.dispatcher"
|
||||
local HTTP = require("luci.http")
|
||||
local NX = require("nixio")
|
||||
local NXFS = require("nixio.fs")
|
||||
local DISP = require("luci.dispatcher")
|
||||
local HTTP = require("luci.http")
|
||||
local I18N = require("luci.i18n") -- not globally avalible here
|
||||
local UTIL = require("luci.util")
|
||||
local SYS = require("luci.sys")
|
||||
local IPKG = require("luci.model.ipkg")
|
||||
local UTIL = require("luci.util")
|
||||
local SYS = require("luci.sys")
|
||||
|
||||
local srv_name = "radicale"
|
||||
local srv_ver_min = "1.1" -- minimum version of service required
|
||||
local srv_ver_cmd = [[/usr/bin/radicale --version]]
|
||||
local app_name = "luci-app-radicale"
|
||||
local app_title = I18N.translate("Radicale CalDAV/CardDAV Server")
|
||||
local app_version = "1.1.0-1"
|
||||
|
||||
function index()
|
||||
entry( {"admin", "services", "radicale"}, alias("admin", "services", "radicale", "edit"), _("CalDAV/CardDAV"), 58)
|
||||
|
@ -19,6 +27,75 @@ function index()
|
|||
entry( {"admin", "services", "radicale", "status"}, call("_status") ).leaf = true
|
||||
end
|
||||
|
||||
-- Application / Service specific information functions
|
||||
function app_description()
|
||||
return I18N.translate("The Radicale Project is a complete CalDAV (calendar) and CardDAV (contact) server solution.") .. [[<br />]]
|
||||
.. I18N.translate("Calendars and address books are available for both local and remote access, possibly limited through authentication policies.") .. [[<br />]]
|
||||
.. I18N.translate("They can be viewed and edited by calendar and contact clients on mobile phones or computers.")
|
||||
end
|
||||
function app_title_main()
|
||||
return [[<a href="javascript:alert(']]
|
||||
.. I18N.translate("Version Information")
|
||||
.. [[\n\n]] .. app_name
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]] .. app_version
|
||||
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("required") .. [[:]]
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
|
||||
.. srv_ver_min .. [[ ]] .. I18N.translate("or higher")
|
||||
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("installed") .. [[:]]
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
|
||||
.. (service_version() or I18N.translate("NOT installed"))
|
||||
.. [[\n\n]]
|
||||
.. [[')">]]
|
||||
.. I18N.translate(app_title)
|
||||
.. [[</a>]]
|
||||
end
|
||||
function app_title_back()
|
||||
return [[<a href="]]
|
||||
.. DISP.build_url("admin", "services", "radicale")
|
||||
.. [[">]]
|
||||
.. I18N.translate(app_title)
|
||||
.. [[</a>]]
|
||||
end
|
||||
function app_err_value()
|
||||
if not service_version() then
|
||||
return [[<h3><strong><br /><font color="red"> ]]
|
||||
.. I18N.translate("Software package '%s' is not installed." % srv_name)
|
||||
.. [[</font><br /><br /> ]]
|
||||
.. I18N.translate("required") .. [[: ]] .. srv_name .. [[ ]] .. srv_ver_min
|
||||
.. [[<br /><br /> ]]
|
||||
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
|
||||
.. I18N.translate("Please install current version !")
|
||||
.. [[</a><br /> </strong></h3>]]
|
||||
else
|
||||
return [[<h3><strong><br /><font color="red"> ]]
|
||||
.. I18N.translate("Software package '%s' is outdated." % srv_name)
|
||||
.. [[</font><br /><br /> ]]
|
||||
.. I18N.translate("installed") .. [[: ]] .. srv_name .. [[ ]] .. service_version()
|
||||
.. [[<br /> ]]
|
||||
.. I18N.translate("required") .. [[: ]] .. srv_name .. [[ ]] .. srv_ver_min
|
||||
.. [[<br /><br /> ]]
|
||||
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
|
||||
.. I18N.translate("Please update to current version !")
|
||||
.. [[</a><br /> </strong></h3>]]
|
||||
end
|
||||
end
|
||||
|
||||
function service_version()
|
||||
local ver = nil
|
||||
IPKG.list_installed(srv_name, function(n, v, d)
|
||||
if v and (#v > 0) then ver = v end
|
||||
end
|
||||
)
|
||||
if not ver or (#ver == 0) then
|
||||
ver = UTIL.exec(srv_ver_cmd)
|
||||
if #ver == 0 then ver = nil end
|
||||
end
|
||||
return ver
|
||||
end
|
||||
function service_ok()
|
||||
return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min)
|
||||
end
|
||||
|
||||
-- called by XHR.get from detail_logview.htm
|
||||
function _logread()
|
||||
-- read application settings
|
||||
|
@ -60,138 +137,103 @@ function _status()
|
|||
HTTP.write(tostring(pid)) -- HTTP needs string not number
|
||||
end
|
||||
|
||||
-- Application / Service specific information functions ########################
|
||||
function luci_app_name()
|
||||
return "luci-app-radicale"
|
||||
end
|
||||
|
||||
function service_name()
|
||||
return "radicale"
|
||||
end
|
||||
function service_required()
|
||||
return "0.10-1"
|
||||
end
|
||||
function service_installed()
|
||||
local v = ipkg_ver_installed("radicale-py2")
|
||||
if not v or #v == 0 then v = ipkg_ver_installed("radicale-py3") end
|
||||
if not v or #v == 0 then v = "0" end
|
||||
return v
|
||||
end
|
||||
function service_ok()
|
||||
return ipkg_ver_compare(service_installed(),">=",service_required())
|
||||
end
|
||||
|
||||
function app_title_main()
|
||||
return [[<a href="javascript:alert(']]
|
||||
.. I18N.translate("Version Information")
|
||||
.. [[\n\n]] .. luci_app_name()
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
|
||||
.. (ipkg_ver_installed(luci_app_name()) == ""
|
||||
and I18N.translate("NOT installed")
|
||||
or ipkg_ver_installed(luci_app_name()) )
|
||||
.. [[\n\n]] .. service_name() .. [[ ]] .. I18N.translate("required") .. [[:]]
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
|
||||
.. service_required() .. [[ ]] .. I18N.translate("or higher")
|
||||
.. [[\n\n]] .. service_name() .. [[ ]] .. I18N.translate("installed") .. [[:]]
|
||||
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]]
|
||||
.. (service_installed() == "0"
|
||||
and I18N.translate("NOT installed")
|
||||
or service_installed())
|
||||
.. [[\n\n]]
|
||||
.. [[')">]]
|
||||
.. I18N.translate("Radicale CalDAV/CardDAV Server")
|
||||
.. [[</a>]]
|
||||
end
|
||||
function app_title_back()
|
||||
return [[<a href="]]
|
||||
.. DISP.build_url("admin", "services", "radicale")
|
||||
.. [[">]]
|
||||
.. I18N.translate("Radicale CalDAV/CardDAV Server")
|
||||
.. [[</a>]]
|
||||
end
|
||||
function app_description()
|
||||
return I18N.translate("The Radicale Project is a complete CalDAV (calendar) and CardDAV (contact) server solution.") .. [[<br />]]
|
||||
.. I18N.translate("Calendars and address books are available for both local and remote access, possibly limited through authentication policies.") .. [[<br />]]
|
||||
.. I18N.translate("They can be viewed and edited by calendar and contact clients on mobile phones or computers.")
|
||||
end
|
||||
|
||||
-- other multiused functions ###################################################
|
||||
|
||||
--return pid of running process
|
||||
function get_pid()
|
||||
return tonumber(SYS.exec([[ps | grep "[p]ython.*[r]adicale" 2>/dev/null | awk '{print $1}']])) or 0
|
||||
end
|
||||
|
||||
-- compare versions using "<=" "<" ">" ">=" "=" "<<" ">>"
|
||||
function ipkg_ver_compare(ver1, comp, ver2)
|
||||
if not ver1 or not ver2
|
||||
or not comp or not (#comp > 0) then return nil end
|
||||
-- correct compare string
|
||||
if comp == "<>" or comp == "><" or comp == "!=" or comp == "~=" then comp = "~="
|
||||
elseif comp == "<=" or comp == "<" or comp == "=<" then comp = "<="
|
||||
elseif comp == ">=" or comp == ">" or comp == "=>" then comp = ">="
|
||||
elseif comp == "=" or comp == "==" then comp = "=="
|
||||
elseif comp == "<<" then comp = "<"
|
||||
elseif comp == ">>" then comp = ">"
|
||||
else return nil end
|
||||
-- replacement of build-in parse of "Value"
|
||||
-- modified AbstractValue.parse(self, section, novld) from cbi.lua
|
||||
-- validate is called if rmempty/optional true or false
|
||||
-- before write check if forcewrite, value eq default, and more
|
||||
function value_parse(self, section, novld)
|
||||
local fvalue = self:formvalue(section)
|
||||
local fexist = ( fvalue and (#fvalue > 0) ) -- not "nil" and "not empty"
|
||||
local cvalue = self:cfgvalue(section)
|
||||
local rm_opt = ( self.rmempty or self.optional )
|
||||
local eq_cfg -- flag: equal cfgvalue
|
||||
|
||||
local av1 = UTIL.split(ver1, "[%.%-]", nil, true)
|
||||
local av2 = UTIL.split(ver2, "[%.%-]", nil, true)
|
||||
|
||||
for i = 1, math.max(table.getn(av1),table.getn(av2)), 1 do
|
||||
local s1 = av1[i] or ""
|
||||
local s2 = av2[i] or ""
|
||||
|
||||
-- first "not equal" found return true
|
||||
if comp == "~=" and (s1 ~= s2) then return true end
|
||||
-- first "lower" found return true
|
||||
if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
|
||||
-- first "greater" found return true
|
||||
if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
|
||||
-- not equal then return false
|
||||
if (s1 ~= s2) then return false end
|
||||
end
|
||||
|
||||
-- all equal and not compare greater or lower then true
|
||||
return not (comp == "<" or comp == ">")
|
||||
end
|
||||
|
||||
-- read version information for given package if installed
|
||||
function ipkg_ver_installed(pkg)
|
||||
local version = ""
|
||||
local control = io.open("/usr/lib/opkg/info/%s.control" % pkg, "r")
|
||||
if control then
|
||||
local ln
|
||||
repeat
|
||||
ln = control:read("*l")
|
||||
if ln and ln:match("^Version: ") then
|
||||
version = ln:gsub("^Version: ", "")
|
||||
break
|
||||
-- If favlue and cvalue are both tables and have the same content
|
||||
-- make them identical
|
||||
if type(fvalue) == "table" and type(cvalue) == "table" then
|
||||
eq_cfg = (#fvalue == #cvalue)
|
||||
if eq_cfg then
|
||||
for i=1, #fvalue do
|
||||
if cvalue[i] ~= fvalue[i] then
|
||||
eq_cfg = false
|
||||
end
|
||||
end
|
||||
until not ln
|
||||
control:close()
|
||||
end
|
||||
return version
|
||||
end
|
||||
|
||||
-- replacement of build-in Flag.parse of cbi.lua
|
||||
-- modified to mark section as changed if value changes
|
||||
-- current parse did not do this, but it is done AbstaractValue.parse()
|
||||
function flag_parse(self, section)
|
||||
local fexists = self.map:formvalue(
|
||||
luci.cbi.FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
|
||||
|
||||
if fexists then
|
||||
local fvalue = self:formvalue(section) and self.enabled or self.disabled
|
||||
local cvalue = self:cfgvalue(section)
|
||||
if fvalue ~= self.default or (not self.optional and not self.rmempty) then
|
||||
self:write(section, fvalue)
|
||||
else
|
||||
self:remove(section)
|
||||
end
|
||||
if (fvalue ~= cvalue) then self.section.changed = true end
|
||||
else
|
||||
self:remove(section)
|
||||
if eq_cfg then
|
||||
fvalue = cvalue
|
||||
end
|
||||
end
|
||||
|
||||
-- removed parameter "section" from function call because used/accepted nowhere
|
||||
-- also removed call to function "transfer"
|
||||
local vvalue, errtxt = self:validate(fvalue)
|
||||
|
||||
-- error handling; validate return "nil"
|
||||
if not vvalue then
|
||||
if novld then -- and "novld" set
|
||||
return -- then exit without raising an error
|
||||
end
|
||||
|
||||
if fexist then -- and there is a formvalue
|
||||
self:add_error(section, "invalid", errtxt)
|
||||
return -- so data are invalid
|
||||
elseif not rm_opt then -- and empty formvalue but NOT (rmempty or optional) set
|
||||
self:add_error(section, "missing", errtxt)
|
||||
return -- so data is missing
|
||||
elseif errtxt then
|
||||
self:add_error(section, "invalid", errtxt)
|
||||
return
|
||||
end
|
||||
-- error ("\n option: " .. self.option ..
|
||||
-- "\n fvalue: " .. tostring(fvalue) ..
|
||||
-- "\n fexist: " .. tostring(fexist) ..
|
||||
-- "\n cvalue: " .. tostring(cvalue) ..
|
||||
-- "\n vvalue: " .. tostring(vvalue) ..
|
||||
-- "\n vexist: " .. tostring(vexist) ..
|
||||
-- "\n rm_opt: " .. tostring(rm_opt) ..
|
||||
-- "\n eq_cfg: " .. tostring(eq_cfg) ..
|
||||
-- "\n eq_def: " .. tostring(eq_def) ..
|
||||
-- "\n novld : " .. tostring(novld) ..
|
||||
-- "\n errtxt: " .. tostring(errtxt) )
|
||||
end
|
||||
|
||||
-- lets continue with value returned from validate
|
||||
eq_cfg = ( vvalue == cvalue ) -- update equal_config flag
|
||||
local vexist = ( vvalue and (#vvalue > 0) ) and true or false -- not "nil" and "not empty"
|
||||
local eq_def = ( vvalue == self.default ) -- equal_default flag
|
||||
|
||||
-- (rmempty or optional) and (no data or equal_default)
|
||||
if rm_opt and (not vexist or eq_def) then
|
||||
if self:remove(section) then -- remove data from UCI
|
||||
self.section.changed = true -- and push events
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- not forcewrite and no changes, so nothing to write
|
||||
if not self.forcewrite and eq_cfg then
|
||||
return
|
||||
end
|
||||
|
||||
-- we should have a valid value here
|
||||
assert (vvalue, "\n option: " .. self.option ..
|
||||
"\n fvalue: " .. tostring(fvalue) ..
|
||||
"\n fexist: " .. tostring(fexist) ..
|
||||
"\n cvalue: " .. tostring(cvalue) ..
|
||||
"\n vvalue: " .. tostring(vvalue) ..
|
||||
"\n vexist: " .. tostring(vexist) ..
|
||||
"\n rm_opt: " .. tostring(rm_opt) ..
|
||||
"\n eq_cfg: " .. tostring(eq_cfg) ..
|
||||
"\n eq_def: " .. tostring(eq_def) ..
|
||||
"\n errtxt: " .. tostring(errtxt) )
|
||||
|
||||
-- write data to UCI; raise event only on changes
|
||||
if self:write(section, vvalue) and not eq_cfg then
|
||||
self.section.changed = true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,43 @@
|
|||
-- Copyright 2015 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
|
||||
-- Copyright 2015-2016 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
|
||||
-- Licensed under the Apache License, Version 2.0
|
||||
|
||||
local NXFS = require("nixio.fs")
|
||||
local DISP = require("luci.dispatcher")
|
||||
local DTYP = require("luci.cbi.datatypes")
|
||||
local HTTP = require("luci.http")
|
||||
local UTIL = require("luci.util")
|
||||
local UCI = require("luci.model.uci")
|
||||
local SYS = require("luci.sys")
|
||||
local TOOLS = require("luci.controller.radicale") -- this application's controller and multiused functions
|
||||
local NXFS = require("nixio.fs")
|
||||
local DISP = require("luci.dispatcher")
|
||||
local DTYP = require("luci.cbi.datatypes")
|
||||
local HTTP = require("luci.http")
|
||||
local UTIL = require("luci.util")
|
||||
local UCI = require("luci.model.uci")
|
||||
local SYS = require("luci.sys")
|
||||
local WADM = require("luci.tools.webadmin")
|
||||
local CTRL = require("luci.controller.radicale") -- this application's controller and multiused functions
|
||||
|
||||
-- #################################################################################################
|
||||
-- Error handling if not installed or wrong version -- #########################
|
||||
if not CTRL.service_ok() then
|
||||
local f = SimpleForm("__sf")
|
||||
f.title = CTRL.app_title_main()
|
||||
f.description = CTRL.app_description()
|
||||
f.embedded = true
|
||||
f.submit = false
|
||||
f.reset = false
|
||||
|
||||
local s = f:section(SimpleSection)
|
||||
s.title = [[<font color="red">]] .. [[<strong>]]
|
||||
.. translate("Software update required")
|
||||
.. [[</strong>]] .. [[</font>]]
|
||||
|
||||
local v = s:option(DummyValue, "_dv")
|
||||
v.rawhtml = true
|
||||
v.value = CTRL.app_err_value
|
||||
|
||||
return f
|
||||
end
|
||||
|
||||
-- #################################################################################################
|
||||
-- Error handling if no config, create an empty one -- #########################
|
||||
if not NXFS.access("/etc/config/radicale") then
|
||||
NXFS.writefile("/etc/config/radicale", "")
|
||||
end
|
||||
|
||||
-- #################################################################################################
|
||||
-- takeover arguments if any -- ################################################
|
||||
|
@ -19,8 +48,8 @@ if arg[1] then
|
|||
|
||||
-- SimpleForm ------------------------------------------------
|
||||
local ft = SimpleForm("_text")
|
||||
ft.title = TOOLS.app_title_back()
|
||||
ft.description = TOOLS.app_description()
|
||||
ft.title = CTRL.app_title_back()
|
||||
ft.description = CTRL.app_description()
|
||||
ft.redirect = DISP.build_url("admin", "services", "radicale") .. "#cbi-radicale-" .. argument
|
||||
if argument == "logger" then
|
||||
ft.reset = false
|
||||
|
@ -95,54 +124,12 @@ if arg[1] then
|
|||
|
||||
end
|
||||
|
||||
-- #################################################################################################
|
||||
-- Error handling if not installed or wrong version -- #########################
|
||||
if not TOOLS.service_ok() then
|
||||
local f = SimpleForm("_no_config")
|
||||
f.title = TOOLS.app_title_main()
|
||||
f.description = TOOLS.app_description()
|
||||
f.submit = false
|
||||
f.reset = false
|
||||
|
||||
local s = f:section(SimpleSection)
|
||||
|
||||
local v = s:option(DummyValue, "_update_needed")
|
||||
v.rawhtml = true
|
||||
if TOOLS.service_installed() == "0" then
|
||||
v.value = [[<h3><strong><br /><font color="red"> ]]
|
||||
.. translate("Software package '" .. TOOLS.service_name() .. "' is not installed.")
|
||||
.. [[</font><br /><br /> ]]
|
||||
.. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
|
||||
.. [[<br /><br /> ]]
|
||||
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
|
||||
.. translate("Please install current version !")
|
||||
.. [[</a><br /> </strong></h3>]]
|
||||
else
|
||||
v.value = [[<h3><strong><br /><font color="red"> ]]
|
||||
.. translate("Software package '" .. TOOLS.service_name() .. "' is outdated.")
|
||||
.. [[</font><br /><br /> ]]
|
||||
.. translate("installed") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_installed()
|
||||
.. [[<br /> ]]
|
||||
.. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
|
||||
.. [[<br /><br /> ]]
|
||||
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
|
||||
.. translate("Please update to current version !")
|
||||
.. [[</a><br /> </strong></h3>]]
|
||||
end
|
||||
|
||||
return f
|
||||
end
|
||||
|
||||
-- #################################################################################################
|
||||
-- Error handling if no config, create an empty one -- #########################
|
||||
if not NXFS.access("/etc/config/radicale") then
|
||||
NXFS.writefile("/etc/config/radicale", "")
|
||||
end
|
||||
|
||||
-- cbi-map -- ##################################################################
|
||||
local m = Map("radicale")
|
||||
m.title = TOOLS.app_title_main()
|
||||
m.description = TOOLS.app_description()
|
||||
m.title = CTRL.app_title_main()
|
||||
m.description = CTRL.app_description()
|
||||
m.template = "radicale/tabmap_nsections"
|
||||
m.tabbed = true
|
||||
function m.commit_handler(self)
|
||||
if self.changed then -- changes ?
|
||||
os.execute("/etc/init.d/radicale reload &") -- reload configuration
|
||||
|
@ -150,11 +137,14 @@ function m.commit_handler(self)
|
|||
end
|
||||
|
||||
-- cbi-section "System" -- #####################################################
|
||||
local sys = m:section( NamedSection, "_system" )
|
||||
local sys = m:section( NamedSection, "system", "system" )
|
||||
sys.title = translate("System")
|
||||
sys.description = nil
|
||||
function sys.cfgvalue(self, section)
|
||||
return "_dummysection"
|
||||
if not self.map:get(section) then -- section might not exist
|
||||
self.map:set(section, nil, self.sectiontype)
|
||||
end
|
||||
return self.map:get(section)
|
||||
end
|
||||
|
||||
-- start/stop button -----------------------------------------------------------
|
||||
|
@ -165,7 +155,7 @@ btn.rmempty = true
|
|||
btn.title = translate("Start / Stop")
|
||||
btn.description = translate("Start/Stop Radicale server")
|
||||
function btn.cfgvalue(self, section)
|
||||
local pid = TOOLS.get_pid(true)
|
||||
local pid = CTRL.get_pid(true)
|
||||
if pid > 0 then
|
||||
btn.inputtitle = "PID: " .. pid
|
||||
btn.inputstyle = "reset"
|
||||
|
@ -183,18 +173,39 @@ local ena = sys:option(Flag, "_enabled")
|
|||
ena.title = translate("Auto-start")
|
||||
ena.description = translate("Enable/Disable auto-start of Radicale on system start-up and interface events")
|
||||
ena.orientation = "horizontal" -- put description under the checkbox
|
||||
ena.rmempty = false -- we need write
|
||||
ena.rmempty = false -- force write() function
|
||||
function ena.cfgvalue(self, section)
|
||||
return (SYS.init.enabled("radicale")) and "1" or "0"
|
||||
return (SYS.init.enabled("radicale")) and self.enabled or self.disabled
|
||||
end
|
||||
function ena.write(self, section, value)
|
||||
if value == "1" then
|
||||
if value == self.enabled then
|
||||
return SYS.init.enable("radicale")
|
||||
else
|
||||
return SYS.init.disable("radicale")
|
||||
end
|
||||
end
|
||||
|
||||
-- boot_delay ------------------------------------------------------------------
|
||||
local bd = sys:option(Value, "boot_delay")
|
||||
bd.title = translate("Boot delay")
|
||||
bd.description = translate("Delay (in seconds) during system boot before Radicale start")
|
||||
.. [[<br />]]
|
||||
.. translate("During delay ifup-events are not monitored !")
|
||||
bd.default = "10"
|
||||
function bd.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function bd.validate(self, value)
|
||||
local val = tonumber(value)
|
||||
if not val then
|
||||
return nil, self.title .. ": " .. translate("Value is not a number")
|
||||
elseif val < 0 or val > 300 then
|
||||
return nil, self.title .. ": " .. translate("Value not between 0 and 300")
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
|
||||
-- cbi-section "Server" -- #####################################################
|
||||
local srv = m:section( NamedSection, "server", "setting" )
|
||||
srv.title = translate("Server")
|
||||
|
@ -215,15 +226,17 @@ sh.description = translate("'Hostname:Port' or 'IPv4:Port' or '[IPv6]:Port' Radi
|
|||
.. [[</strong>]]
|
||||
sh.placeholder = "0.0.0.0:5232"
|
||||
sh.rmempty = true
|
||||
function sh.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- realm -----------------------------------------------------------------------
|
||||
local alm = srv:option( Value, "realm" )
|
||||
alm.title = translate("Logon message")
|
||||
alm.description = translate("Message displayed in the client when a password is needed.")
|
||||
alm.default = "Radicale - Password Required"
|
||||
alm.rmempty = false
|
||||
function alm.parse(self, section)
|
||||
AbstractValue.parse(self, section, "true") -- otherwise unspecific validate error
|
||||
function alm.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function alm.validate(self, value)
|
||||
if value then
|
||||
|
@ -232,22 +245,11 @@ function alm.validate(self, value)
|
|||
return self.default
|
||||
end
|
||||
end
|
||||
function alm.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
else
|
||||
return self.map:del(section, self.option)
|
||||
end
|
||||
end
|
||||
|
||||
-- ssl -------------------------------------------------------------------------
|
||||
local ssl = srv:option( Flag, "ssl" )
|
||||
ssl.title = translate("Enable HTTPS")
|
||||
ssl.description = nil
|
||||
ssl.rmempty = false
|
||||
function ssl.parse(self, section)
|
||||
TOOLS.flag_parse(self, section)
|
||||
end
|
||||
function ssl.write(self, section, value)
|
||||
if value == "0" then -- delete all if not https enabled
|
||||
self.map:del(section, "protocol") -- protocol
|
||||
|
@ -273,18 +275,18 @@ prt:value ("PROTOCOL_SSLv3", "SSL v3")
|
|||
prt:value ("PROTOCOL_TLSv1", "TLS v1")
|
||||
prt:value ("PROTOCOL_TLSv1_1", "TLS v1.1")
|
||||
prt:value ("PROTOCOL_TLSv1_2", "TLS v1.2")
|
||||
function prt.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- certificate -----------------------------------------------------------------
|
||||
local crt = srv:option( Value, "certificate" )
|
||||
crt.title = translate("Certificate file")
|
||||
crt.description = translate("Full path and file name of certificate")
|
||||
crt.placeholder = "/etc/radicale/ssl/server.crt"
|
||||
crt.rmempty = false -- force validate/write
|
||||
crt:depends ("ssl", "1")
|
||||
function crt.parse(self, section)
|
||||
local _ssl = ssl:formvalue(section) or "0"
|
||||
local novld = (_ssl == "0")
|
||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
||||
function crt.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function crt.validate(self, value)
|
||||
local _ssl = ssl:formvalue(srv.section) or "0"
|
||||
|
@ -295,17 +297,10 @@ function crt.validate(self, value)
|
|||
if DTYP.file(value) then
|
||||
return value
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("File not found !")
|
||||
return nil, self.title .. ": " .. translate("File not found !")
|
||||
end
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Path/File required !")
|
||||
end
|
||||
end
|
||||
function crt.write(self, section, value)
|
||||
if not value or #value == 0 then
|
||||
return self.map:del(section, self.option)
|
||||
else
|
||||
return self.map:set(section, self.option, value)
|
||||
return nil, self.title .. ": " .. translate("Path/File required !")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -314,12 +309,9 @@ local key = srv:option( Value, "key" )
|
|||
key.title = translate("Private key file")
|
||||
key.description = translate("Full path and file name of private key")
|
||||
key.placeholder = "/etc/radicale/ssl/server.key"
|
||||
key.rmempty = false -- force validate/write
|
||||
key:depends ("ssl", "1")
|
||||
function key.parse(self, section)
|
||||
local _ssl = ssl:formvalue(section) or "0"
|
||||
local novld = (_ssl == "0")
|
||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
||||
function key.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function key.validate(self, value)
|
||||
local _ssl = ssl:formvalue(srv.section) or "0"
|
||||
|
@ -330,17 +322,10 @@ function key.validate(self, value)
|
|||
if DTYP.file(value) then
|
||||
return value
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("File not found !")
|
||||
return nil, self.title .. ": " .. translate("File not found !")
|
||||
end
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Path/File required !")
|
||||
end
|
||||
end
|
||||
function key.write(self, section, value)
|
||||
if not value or #value == 0 then
|
||||
return self.map:del(section, self.option)
|
||||
else
|
||||
return self.map:set(section, self.option, value)
|
||||
return nil, self.title .. ": " .. translate("Path/File required !")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -377,6 +362,9 @@ aty:value ("htpasswd", translate("htpasswd file"))
|
|||
--aty:value ("HTTP", "HTTP") -- The HTTP authentication module relies on the requests module
|
||||
--aty:value ("remote_user", "remote_user")
|
||||
--aty:value ("custom", translate("custom"))
|
||||
function aty.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function aty.write(self, section, value)
|
||||
if value ~= "htpasswd" then
|
||||
self.map:del(section, "htpasswd_encryption")
|
||||
|
@ -403,9 +391,12 @@ hte:value ("crypt", translate("crypt"))
|
|||
hte:value ("plain", translate("plain"))
|
||||
hte:value ("sha1", translate("SHA-1"))
|
||||
hte:value ("ssha", translate("salted SHA-1"))
|
||||
function hte.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- htpasswd_file (dummy) -------------------------------------------------------
|
||||
local htf = aut:option( DummyValue, "_htf" )
|
||||
local htf = aut:option( Value, "_htf" )
|
||||
htf.title = translate("htpasswd file")
|
||||
htf.description = [[<strong>]]
|
||||
.. translate("Read only!")
|
||||
|
@ -416,9 +407,6 @@ htf.description = [[<strong>]]
|
|||
.. [[">]]
|
||||
.. translate("To edit the file follow this link!")
|
||||
.. [[</a>]]
|
||||
htf.keylist = {} -- required by template
|
||||
htf.vallist = {} -- required by template
|
||||
htf.template = "radicale/ro_value"
|
||||
htf.readonly = true
|
||||
htf:depends ("type", "htpasswd")
|
||||
function htf.cfgvalue()
|
||||
|
@ -448,6 +436,9 @@ rty:value ("owner_only", translate("Full access for Owner only") )
|
|||
rty:value ("owner_write", translate("Owner allow write, authenticated users allow read") )
|
||||
rty:value ("from_file", translate("Rights are based on a regexp-based file") )
|
||||
--rty:value ("custom", "Custom handler")
|
||||
function rty.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function rty.write(self, section, value)
|
||||
if value ~= "custom" then
|
||||
self.map:del(section, "custom_handler")
|
||||
|
@ -460,7 +451,7 @@ function rty.write(self, section, value)
|
|||
end
|
||||
|
||||
-- from_file (dummy) -----------------------------------------------------------
|
||||
local rtf = rig:option( DummyValue, "_rtf" )
|
||||
local rtf = rig:option( Value, "_rtf" )
|
||||
rtf.title = translate("RegExp file")
|
||||
rtf.description = [[<strong>]]
|
||||
.. translate("Read only!")
|
||||
|
@ -471,9 +462,6 @@ rtf.description = [[<strong>]]
|
|||
.. [[">]]
|
||||
.. translate("To edit the file follow this link!")
|
||||
.. [[</a>]]
|
||||
rtf.keylist = {} -- required by template
|
||||
rtf.vallist = {} -- required by template
|
||||
rtf.template = "radicale/ro_value"
|
||||
rtf.readonly = true
|
||||
rtf:depends ("type", "from_file")
|
||||
function rtf.cfgvalue()
|
||||
|
@ -501,6 +489,9 @@ sty:value ("filesystem", translate("File-system"))
|
|||
--sty:value ("multifilesystem", translate("") )
|
||||
--sty:value ("database", translate("Database") )
|
||||
--sty:value ("custom", translate("Custom") )
|
||||
function sty.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function sty.write(self, section, value)
|
||||
if value ~= "filesystem" then
|
||||
self.map:del(section, "filesystem_folder")
|
||||
|
@ -516,13 +507,10 @@ end
|
|||
local sfi = sto:option( Value, "filesystem_folder" )
|
||||
sfi.title = translate("Directory")
|
||||
sfi.description = nil
|
||||
sfi.default = "/srv/radicale"
|
||||
sfi.rmempty = false -- force validate/write
|
||||
sfi.placeholder = "/srv/radicale"
|
||||
sfi:depends ("type", "filesystem")
|
||||
function sfi.parse(self, section)
|
||||
local _typ = sty:formvalue(sto.section) or ""
|
||||
local novld = (_typ ~= "filesystem")
|
||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
||||
function sfi.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function sfi.validate(self, value)
|
||||
local _typ = sty:formvalue(sto.section) or ""
|
||||
|
@ -533,10 +521,10 @@ function sfi.validate(self, value)
|
|||
if DTYP.directory(value) then
|
||||
return value
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Directory not exists/found !")
|
||||
return nil, self.title .. ": " .. translate("Directory not exists/found !")
|
||||
end
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Directory required !")
|
||||
return nil, self.title .. ": " .. translate("Directory required !")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -562,6 +550,9 @@ lco:value ("INFO", translate("Info") )
|
|||
lco:value ("WARNING", translate("Warning") )
|
||||
lco:value ("ERROR", translate("Error") )
|
||||
lco:value ("CRITICAL", translate("Critical") )
|
||||
function lco.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lco.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
|
@ -581,6 +572,9 @@ lsl:value ("INFO", translate("Info") )
|
|||
lsl:value ("WARNING", translate("Warning") )
|
||||
lsl:value ("ERROR", translate("Error") )
|
||||
lsl:value ("CRITICAL", translate("Critical") )
|
||||
function lsl.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lsl.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
|
@ -600,6 +594,9 @@ lfi:value ("INFO", translate("Info") )
|
|||
lfi:value ("WARNING", translate("Warning") )
|
||||
lfi:value ("ERROR", translate("Error") )
|
||||
lfi:value ("CRITICAL", translate("Critical") )
|
||||
function lfi.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lfi.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
|
@ -618,12 +615,14 @@ lfp.description = translate("Directory where the rotating log-files are stored")
|
|||
.. translate("To view latest log file follow this link!")
|
||||
.. [[</a>]]
|
||||
lfp.default = "/var/log/radicale"
|
||||
function lfp.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
else
|
||||
return self.map:del(section, self.option)
|
||||
function lfp.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lfp.validate(self, value)
|
||||
if not value or (#value < 1) or (value:find("/") ~= 1) then
|
||||
return nil, self.title .. ": " .. translate("no valid path given!")
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
-- file_maxbytes ---------------------------------------------------------------
|
||||
|
@ -634,23 +633,18 @@ lmb.description = translate("Maximum size of each rotation log-file.")
|
|||
.. translate("Setting this parameter to '0' will disable rotation of log-file.")
|
||||
.. [[</strong>]]
|
||||
lmb.default = "8196"
|
||||
lmb.rmempty = false
|
||||
function lmb.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lmb.validate(self, value)
|
||||
if value then -- otherwise errors in datatype check
|
||||
if DTYP.uinteger(value) then
|
||||
return value
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Value is not an Integer >= 0 !")
|
||||
return nil, self.title .. ": " .. translate("Value is not an Integer >= 0 !")
|
||||
end
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Value required ! Integer >= 0 !")
|
||||
end
|
||||
end
|
||||
function lmb.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
else
|
||||
return self.map:del(section, self.option)
|
||||
return nil, self.title .. ": " .. translate("Value required ! Integer >= 0 !")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -662,23 +656,18 @@ lbc.description = translate("Number of backup files of log to create.")
|
|||
.. translate("Setting this parameter to '0' will disable rotation of log-file.")
|
||||
.. [[</strong>]]
|
||||
lbc.default = "1"
|
||||
lbc.rmempty = false
|
||||
function lbc.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
function lbc.validate(self, value)
|
||||
if value then -- otherwise errors in datatype check
|
||||
if DTYP.uinteger(value) then
|
||||
return value
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Value is not an Integer >= 0 !")
|
||||
return nil, self.title .. ": " .. translate("Value is not an Integer >= 0 !")
|
||||
end
|
||||
else
|
||||
return nil, self.title .. " - " .. translate("Value required ! Integer >= 0 !")
|
||||
end
|
||||
end
|
||||
function lbc.write(self, section, value)
|
||||
if value ~= self.default then
|
||||
return self.map:set(section, self.option, value)
|
||||
else
|
||||
return self.map:del(section, self.option)
|
||||
return nil, self.title .. ": " .. translate("Value required ! Integer >= 0 !")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -699,14 +688,18 @@ local enr = enc:option( Value, "request" )
|
|||
enr.title = translate("Response Encoding")
|
||||
enr.description = translate("Encoding for responding requests.")
|
||||
enr.default = "utf-8"
|
||||
enr.optional = true
|
||||
function enr.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- stock -----------------------------------------------------------------------
|
||||
local ens = enc:option( Value, "stock" )
|
||||
ens.title = translate("Storage Encoding")
|
||||
ens.description = translate("Encoding for storing local collections.")
|
||||
ens.default = "utf-8"
|
||||
ens.optional = true
|
||||
function ens.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- cbi-section "Headers" -- ####################################################
|
||||
local hea = m:section( NamedSection, "headers", "setting" )
|
||||
|
@ -724,25 +717,32 @@ end
|
|||
local heo = hea:option( DynamicList, "Access_Control_Allow_Origin" )
|
||||
heo.title = translate("Access-Control-Allow-Origin")
|
||||
heo.description = nil
|
||||
heo.default = "*"
|
||||
heo.optional = true
|
||||
function heo.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- Access_Control_Allow_Methods ------------------------------------------------
|
||||
local hem = hea:option( DynamicList, "Access_Control_Allow_Methods" )
|
||||
hem.title = translate("Access-Control-Allow-Methods")
|
||||
hem.description = nil
|
||||
hem.optional = true
|
||||
function hem.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- Access_Control_Allow_Headers ------------------------------------------------
|
||||
local heh = hea:option( DynamicList, "Access_Control_Allow_Headers" )
|
||||
heh.title = translate("Access-Control-Allow-Headers")
|
||||
heh.description = nil
|
||||
heh.optional = true
|
||||
function heh.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
-- Access_Control_Expose_Headers -----------------------------------------------
|
||||
local hee = hea:option( DynamicList, "Access_Control_Expose_Headers" )
|
||||
hee.title = translate("Access-Control-Expose-Headers")
|
||||
hee.description = nil
|
||||
hee.optional = true
|
||||
function hee.parse(self, section, novld)
|
||||
CTRL.value_parse(self, section, novld)
|
||||
end
|
||||
|
||||
return m
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// show XHR.poll/XHR.get response on button
|
||||
function _data2elements(x) {
|
||||
var btn = document.getElementById("cbid.radicale._system._startstop");
|
||||
var btn = document.getElementById("cbid.radicale.<%=section%>._startstop");
|
||||
if ( ! btn ) { return; } // security check
|
||||
if (x.responseText == "0") {
|
||||
btn.value = "<%:Start%>";
|
||||
|
@ -21,12 +21,12 @@
|
|||
function onclick_startstop(id) {
|
||||
// do start/stop
|
||||
var btnXHR = new XHR();
|
||||
btnXHR.post('<%=url('admin/services/radicale/startstop')%>', { token: '<%=token%>' },
|
||||
btnXHR.post('<%=url([[admin/services/radicale/startstop]])%>', { token: '<%=token%>' },
|
||||
function(x) { _data2elements(x); }
|
||||
);
|
||||
}
|
||||
|
||||
XHR.poll(5, '<%=url('admin/services/radicale/status')%>', null,
|
||||
XHR.poll(5, '<%=url([[admin/services/radicale/status]])%>', null,
|
||||
function(x, data) { _data2elements(x); }
|
||||
);
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
<%+cbi/valueheader%>
|
||||
<input type="<%=self.password and 'password" class="cbi-input-password' or 'text" class="cbi-input-text' %>" onchange="cbi_d_update(this.id)"<%=
|
||||
attr("name", cbid) .. attr("id", cbid) .. attr("value", self:cfgvalue(section) or self.default) ..
|
||||
ifattr(self.size, "size") .. ifattr(self.placeholder, "placeholder") .. ifattr(self.readonly, "readonly")
|
||||
%> />
|
||||
<% if self.password then %><img src="<%=resource%>/cbi/reload.gif" style="vertical-align:middle" title="<%:Reveal/hide password%>" onclick="var e = document.getElementById('<%=cbid%>'); e.type = (e.type=='password') ? 'text' : 'password';" /><% end %>
|
||||
<% if #self.keylist > 0 or self.datatype then -%>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
<% if #self.keylist > 0 then -%>
|
||||
cbi_combobox_init('<%=cbid%>', {
|
||||
<%-
|
||||
for i, k in ipairs(self.keylist) do
|
||||
-%>
|
||||
<%-=string.format("%q", k) .. ":" .. string.format("%q", self.vallist[i])-%>
|
||||
<%-if i<#self.keylist then-%>,<%-end-%>
|
||||
<%-
|
||||
end
|
||||
-%>
|
||||
}, '<%- if not self.rmempty and not self.optional then -%>
|
||||
<%-: -- Please choose -- -%>
|
||||
<%- elseif self.placeholder then -%>
|
||||
<%-= pcdata(self.placeholder) -%>
|
||||
<%- end -%>', '
|
||||
<%- if self.combobox_manual then -%>
|
||||
<%-=self.combobox_manual-%>
|
||||
<%- else -%>
|
||||
<%-: -- custom -- -%>
|
||||
<%- end -%>');
|
||||
<%- end %>
|
||||
<% if self.datatype then -%>
|
||||
cbi_validate_field('<%=cbid%>', <%=tostring((self.optional or self.rmempty) == true)%>, '<%=self.datatype:gsub("'", "\\'")%>');
|
||||
<%- end %>
|
||||
//]]></script>
|
||||
<% end -%>
|
||||
<%+cbi/valuefooter%>
|
|
@ -0,0 +1,49 @@
|
|||
<%- if firstmap and messages then local msg; for _, msg in ipairs(messages) do -%>
|
||||
<div class="errorbox"><%=pcdata(msg)%></div>
|
||||
<%- end end -%>
|
||||
|
||||
<%-+cbi/apply_xhr-%>
|
||||
|
||||
<div class="cbi-map" id="cbi-<%=self.config%>">
|
||||
<% if self.title and #self.title > 0 then %><h2 name="content"><%=self.title%></h2><% end %>
|
||||
<% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %>
|
||||
<%- if firstmap and applymap then cbi_apply_xhr(self.config, parsechain, redirect) end -%>
|
||||
|
||||
<% if self.tabbed then %>
|
||||
<ul class="cbi-tabmenu map">
|
||||
<%- self.selected_tab = luci.http.formvalue("tab.m-" .. self.config) %>
|
||||
<% for i, section in ipairs(self.children) do %>
|
||||
<%- if not self.selected_tab then self.selected_tab = section.sectiontype end %>
|
||||
<li id="tab.m-<%=self.config%>.<%=section.section or section.sectiontype%>" class="cbi-tab<%=(section.sectiontype == self.selected_tab) and '' or '-disabled'%>">
|
||||
<a onclick="this.blur(); return cbi_t_switch('m-<%=self.config%>', '<%=section.section or section.sectiontype%>')" href="<%=REQUEST_URI%>?tab.m-<%=self.config%>=<%=section.section or section.sectiontype%>"><%=section.title or section.section or section.sectiontype %></a>
|
||||
<% if section.sectiontype == self.selected_tab then %><input type="hidden" id="tab.m-<%=self.config%>" name="tab.m-<%=self.config%>" value="<%=section.section or section.sectiontype%>" /><% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<br />
|
||||
<% for i, section in ipairs(self.children) do %>
|
||||
<div class="cbi-tabcontainer" id="container.m-<%=self.config%>.<%=section.section or section.sectiontype%>"<% if section.sectiontype ~= self.selected_tab then %> style="display:none"<% end %>>
|
||||
<% section:render() %>
|
||||
</div>
|
||||
<script type="text/javascript">cbi_t_add('m-<%=self.config%>', '<%=section.section or section.sectiontype%>')</script>
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
<%- self:render_children() %>
|
||||
<% end %>
|
||||
|
||||
<% if not self.save then -%>
|
||||
<div class="cbi-section-error">
|
||||
<% for _, section in ipairs(self.children) do %>
|
||||
<% if section.error and section.error[section.section] then -%>
|
||||
<ul><li>
|
||||
<%:One or more missing/invalid fields on tab%>: <%=section.title or section.section or section.sectiontype%>
|
||||
</li></ul>
|
||||
<%- end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%- end %>
|
||||
|
||||
<br />
|
||||
|
||||
</div>
|
|
@ -1,15 +1,15 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: luci-app-radicale\n"
|
||||
"POT-Creation-Date: 2015-05-02 19:32+0100\n"
|
||||
"PO-Revision-Date: 2015-05-02 22:43+0100\n"
|
||||
"Last-Translator: Christian Schoenebeck <christian.schoenebeck@gmail.com>\n"
|
||||
"Project-Id-Version: luci-app-radicale 1.1.0-1\n"
|
||||
"POT-Creation-Date: 2016-01-30 20:34+0100\n"
|
||||
"PO-Revision-Date: 2016-01-31 20:49+0100\n"
|
||||
"Last-Translator: Christian Schönebeck <christian.schoenebeck@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.7.5\n"
|
||||
"X-Generator: Poedit 1.8.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
|
@ -72,6 +72,9 @@ msgstr ""
|
|||
msgid "Auto-start"
|
||||
msgstr "Autostart"
|
||||
|
||||
msgid "Boot delay"
|
||||
msgstr "Systemstart-Verzögerung"
|
||||
|
||||
msgid "CalDAV/CardDAV"
|
||||
msgstr "CalDAV/CardDAV"
|
||||
|
||||
|
@ -122,6 +125,10 @@ msgstr "Datenbank"
|
|||
msgid "Debug"
|
||||
msgstr "Debug"
|
||||
|
||||
msgid "Delay (in seconds) during system boot before Radicale start"
|
||||
msgstr ""
|
||||
"Verzögerung (in Sekunden) während des Systemstarts, bevor Radicale startet"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Verzeichnis"
|
||||
|
||||
|
@ -135,6 +142,9 @@ msgid "Directory where the rotating log-files are stored"
|
|||
msgstr ""
|
||||
"Verzeichnis in dem die rollierenden Protokolldateien gespeichert werden"
|
||||
|
||||
msgid "During delay ifup-events are not monitored !"
|
||||
msgstr "Während der Verzögerung werden 'ifup'-Ereignisse nicht überwacht!"
|
||||
|
||||
msgid "Enable HTTPS"
|
||||
msgstr "Verwende HTTPS"
|
||||
|
||||
|
@ -240,6 +250,9 @@ msgstr "Anzahl der Protokoll Backup Dateien, die angelegt werden."
|
|||
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||
msgstr "OPTIONAL: Siehe Python SSL-Modul Dokumentation"
|
||||
|
||||
msgid "One or more missing/invalid fields on tab"
|
||||
msgstr "Ein oder mehrere fehlende/ungültige Felder auf der Registerkarte"
|
||||
|
||||
msgid "Owner allow write, authenticated users allow read"
|
||||
msgstr ""
|
||||
"Besitzer haben Schreibrechte, Authentifizierten Benutzer dürfen nur lesen."
|
||||
|
@ -324,8 +337,14 @@ msgstr ""
|
|||
"Wenn dieser Parameter auf '0' gesetzt wird, wird die Protokolldatei nicht "
|
||||
"mehr rolliert!"
|
||||
|
||||
msgid "Software package '"
|
||||
msgstr "Software Packet '"
|
||||
msgid "Software package '%s' is not installed."
|
||||
msgstr "Software Paket '%s' ist nicht installiert."
|
||||
|
||||
msgid "Software package '%s' is outdated."
|
||||
msgstr "Software Paket '%s' ist nicht aktuell."
|
||||
|
||||
msgid "Software update required"
|
||||
msgstr "Software-Update erforderlich"
|
||||
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
@ -372,9 +391,15 @@ msgid "To view latest log file follow this link!"
|
|||
msgstr ""
|
||||
"Zur Anzeige der letzten Protokolldatei, folgen Sie dieser Verknüpfung !"
|
||||
|
||||
msgid "Value is not a number"
|
||||
msgstr "Wert ist keine Zahl"
|
||||
|
||||
msgid "Value is not an Integer >= 0 !"
|
||||
msgstr "Eingabe ist keine Ganzzahl >= 0 !"
|
||||
|
||||
msgid "Value not between 0 and 300"
|
||||
msgstr "Wert nicht zwischen 0 und 300"
|
||||
|
||||
msgid "Value required ! Integer >= 0 !"
|
||||
msgstr "Eingabe erforderlich ! Ganzzahl >= 0 !"
|
||||
|
||||
|
@ -397,6 +422,8 @@ msgid ""
|
|||
"You can also get groups from the user regex in the collection with {0}, {1}, "
|
||||
"etc."
|
||||
msgstr ""
|
||||
"Sie können auch Gruppen aus der Benutzer regex in der Sammlung mit {0}, {1} "
|
||||
"usw. bekommen."
|
||||
|
||||
msgid ""
|
||||
"You can use Python's ConfigParser interpolation values %(login)s and "
|
||||
|
@ -416,6 +443,9 @@ msgstr "htpasswd Datei"
|
|||
msgid "installed"
|
||||
msgstr "installiert"
|
||||
|
||||
msgid "no valid path given!"
|
||||
msgstr "Keine gültige Pfadangabe!"
|
||||
|
||||
msgid "or higher"
|
||||
msgstr "oder höher"
|
||||
|
||||
|
@ -427,9 +457,3 @@ msgstr "erforderlich"
|
|||
|
||||
msgid "salted SHA-1"
|
||||
msgstr "Salted SHA-1"
|
||||
|
||||
#~ msgid "File"
|
||||
#~ msgstr "Datei"
|
||||
|
||||
#~ msgid "not found !"
|
||||
#~ msgstr "nicht gefunden !"
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
msgstr ""
|
||||
"Project-Id-Version: luci-app-radicale 1.1.0-1\n"
|
||||
"POT-Creation-Date: 2016-01-30 20:34+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.8.4\n"
|
||||
|
||||
msgid ""
|
||||
"'AUTO' selects the highest protocol version that client and server support."
|
||||
|
@ -53,6 +63,9 @@ msgstr "Autentiseringsmetod för att tillåta åtkomst till Radicale-servern."
|
|||
msgid "Auto-start"
|
||||
msgstr "Starta automatiskt"
|
||||
|
||||
msgid "Boot delay"
|
||||
msgstr ""
|
||||
|
||||
msgid "CalDAV/CardDAV"
|
||||
msgstr "CalDAV/CardDAV"
|
||||
|
||||
|
@ -98,6 +111,9 @@ msgstr "Databas"
|
|||
msgid "Debug"
|
||||
msgstr "Felsök"
|
||||
|
||||
msgid "Delay (in seconds) during system boot before Radicale start"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Mapp"
|
||||
|
||||
|
@ -110,6 +126,9 @@ msgstr "Mapp krävs !"
|
|||
msgid "Directory where the rotating log-files are stored"
|
||||
msgstr "Mappen där de roterade logg-filerna lagras"
|
||||
|
||||
msgid "During delay ifup-events are not monitored !"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable HTTPS"
|
||||
msgstr "Aktivera HTTPS"
|
||||
|
||||
|
@ -209,6 +228,9 @@ msgstr ""
|
|||
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||
msgstr "VALFRITT: Kolla in python's ssl-modul för tillgängliga chiffer"
|
||||
|
||||
msgid "One or more missing/invalid fields on tab"
|
||||
msgstr ""
|
||||
|
||||
msgid "Owner allow write, authenticated users allow read"
|
||||
msgstr ""
|
||||
|
||||
|
@ -289,8 +311,14 @@ msgstr ""
|
|||
"Genom att ställa in den här parametern till '0' så kommer du att stänga av "
|
||||
"rotering av logg-fil."
|
||||
|
||||
msgid "Software package '"
|
||||
msgstr "Mjukvaru-paket '"
|
||||
msgid "Software package '%s' is not installed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software package '%s' is outdated."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software update required"
|
||||
msgstr ""
|
||||
|
||||
msgid "Start"
|
||||
msgstr "Starta"
|
||||
|
@ -332,9 +360,15 @@ msgstr "Följ den här länken för att redigera den här filen!"
|
|||
msgid "To view latest log file follow this link!"
|
||||
msgstr "Följ den här länken för att visa den senaste logg-filen"
|
||||
|
||||
msgid "Value is not a number"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value is not an Integer >= 0 !"
|
||||
msgstr "Värdet är inte ett heltal >= 0 !"
|
||||
|
||||
msgid "Value not between 0 and 300"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value required ! Integer >= 0 !"
|
||||
msgstr "Värde krävs ! Heltal >= 0 !"
|
||||
|
||||
|
@ -375,6 +409,9 @@ msgstr "htpasswd-fil"
|
|||
msgid "installed"
|
||||
msgstr "installerad"
|
||||
|
||||
msgid "no valid path given!"
|
||||
msgstr ""
|
||||
|
||||
msgid "or higher"
|
||||
msgstr "eller högre"
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ msgstr ""
|
|||
msgid "Auto-start"
|
||||
msgstr ""
|
||||
|
||||
msgid "Boot delay"
|
||||
msgstr ""
|
||||
|
||||
msgid "CalDAV/CardDAV"
|
||||
msgstr ""
|
||||
|
||||
|
@ -96,6 +99,9 @@ msgstr ""
|
|||
msgid "Debug"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delay (in seconds) during system boot before Radicale start"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
|
@ -108,6 +114,9 @@ msgstr ""
|
|||
msgid "Directory where the rotating log-files are stored"
|
||||
msgstr ""
|
||||
|
||||
msgid "During delay ifup-events are not monitored !"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable HTTPS"
|
||||
msgstr ""
|
||||
|
||||
|
@ -207,6 +216,9 @@ msgstr ""
|
|||
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||
msgstr ""
|
||||
|
||||
msgid "One or more missing/invalid fields on tab"
|
||||
msgstr ""
|
||||
|
||||
msgid "Owner allow write, authenticated users allow read"
|
||||
msgstr ""
|
||||
|
||||
|
@ -284,7 +296,13 @@ msgstr ""
|
|||
msgid "Setting this parameter to '0' will disable rotation of log-file."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software package '"
|
||||
msgid "Software package '%s' is not installed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software package '%s' is outdated."
|
||||
msgstr ""
|
||||
|
||||
msgid "Software update required"
|
||||
msgstr ""
|
||||
|
||||
msgid "Start"
|
||||
|
@ -327,9 +345,15 @@ msgstr ""
|
|||
msgid "To view latest log file follow this link!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value is not a number"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value is not an Integer >= 0 !"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value not between 0 and 300"
|
||||
msgstr ""
|
||||
|
||||
msgid "Value required ! Integer >= 0 !"
|
||||
msgstr ""
|
||||
|
||||
|
@ -368,6 +392,9 @@ msgstr ""
|
|||
msgid "installed"
|
||||
msgstr ""
|
||||
|
||||
msgid "no valid path given!"
|
||||
msgstr ""
|
||||
|
||||
msgid "or higher"
|
||||
msgstr ""
|
||||
|
||||
|
|
Loading…
Reference in a new issue