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 .
|
# 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
|
# Version == major.minor.patch
|
||||||
# increase "minor" on new functionality and "patch" on patches/optimization
|
# increase "minor" on new functionality and "patch" on patches/optimization
|
||||||
PKG_VERSION:=1.0.2
|
PKG_VERSION:=1.1.0
|
||||||
|
|
||||||
# Release == build
|
# Release == build
|
||||||
# increase on changes of translation files
|
# increase on changes of translation files
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
-- 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
|
-- Licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
module("luci.controller.radicale", package.seeall)
|
module("luci.controller.radicale", package.seeall)
|
||||||
|
|
||||||
local NX = require("nixio")
|
local NX = require("nixio")
|
||||||
local NXFS = require("nixio.fs")
|
local NXFS = require("nixio.fs")
|
||||||
local DISP = require "luci.dispatcher"
|
local DISP = require("luci.dispatcher")
|
||||||
local HTTP = require("luci.http")
|
local HTTP = require("luci.http")
|
||||||
local I18N = require("luci.i18n") -- not globally avalible here
|
local I18N = require("luci.i18n") -- not globally avalible here
|
||||||
|
local IPKG = require("luci.model.ipkg")
|
||||||
local UTIL = require("luci.util")
|
local UTIL = require("luci.util")
|
||||||
local SYS = require("luci.sys")
|
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()
|
function index()
|
||||||
entry( {"admin", "services", "radicale"}, alias("admin", "services", "radicale", "edit"), _("CalDAV/CardDAV"), 58)
|
entry( {"admin", "services", "radicale"}, alias("admin", "services", "radicale", "edit"), _("CalDAV/CardDAV"), 58)
|
||||||
entry( {"admin", "services", "radicale", "edit"}, cbi("radicale") ).leaf = true
|
entry( {"admin", "services", "radicale", "edit"}, cbi("radicale") ).leaf = true
|
||||||
|
@ -19,6 +27,75 @@ function index()
|
||||||
entry( {"admin", "services", "radicale", "status"}, call("_status") ).leaf = true
|
entry( {"admin", "services", "radicale", "status"}, call("_status") ).leaf = true
|
||||||
end
|
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
|
-- called by XHR.get from detail_logview.htm
|
||||||
function _logread()
|
function _logread()
|
||||||
-- read application settings
|
-- read application settings
|
||||||
|
@ -60,138 +137,103 @@ function _status()
|
||||||
HTTP.write(tostring(pid)) -- HTTP needs string not number
|
HTTP.write(tostring(pid)) -- HTTP needs string not number
|
||||||
end
|
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
|
--return pid of running process
|
||||||
function get_pid()
|
function get_pid()
|
||||||
return tonumber(SYS.exec([[ps | grep "[p]ython.*[r]adicale" 2>/dev/null | awk '{print $1}']])) or 0
|
return tonumber(SYS.exec([[ps | grep "[p]ython.*[r]adicale" 2>/dev/null | awk '{print $1}']])) or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- compare versions using "<=" "<" ">" ">=" "=" "<<" ">>"
|
-- replacement of build-in parse of "Value"
|
||||||
function ipkg_ver_compare(ver1, comp, ver2)
|
-- modified AbstractValue.parse(self, section, novld) from cbi.lua
|
||||||
if not ver1 or not ver2
|
-- validate is called if rmempty/optional true or false
|
||||||
or not comp or not (#comp > 0) then return nil end
|
-- before write check if forcewrite, value eq default, and more
|
||||||
-- correct compare string
|
function value_parse(self, section, novld)
|
||||||
if comp == "<>" or comp == "><" or comp == "!=" or comp == "~=" then comp = "~="
|
local fvalue = self:formvalue(section)
|
||||||
elseif comp == "<=" or comp == "<" or comp == "=<" then comp = "<="
|
local fexist = ( fvalue and (#fvalue > 0) ) -- not "nil" and "not empty"
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
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)
|
local cvalue = self:cfgvalue(section)
|
||||||
if fvalue ~= self.default or (not self.optional and not self.rmempty) then
|
local rm_opt = ( self.rmempty or self.optional )
|
||||||
self:write(section, fvalue)
|
local eq_cfg -- flag: equal cfgvalue
|
||||||
else
|
|
||||||
self:remove(section)
|
-- 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
|
||||||
if (fvalue ~= cvalue) then self.section.changed = true end
|
end
|
||||||
else
|
end
|
||||||
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
|
self.section.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
-- 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
|
-- Licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
local NXFS = require("nixio.fs")
|
local NXFS = require("nixio.fs")
|
||||||
|
@ -8,7 +8,36 @@ local HTTP = require("luci.http")
|
||||||
local UTIL = require("luci.util")
|
local UTIL = require("luci.util")
|
||||||
local UCI = require("luci.model.uci")
|
local UCI = require("luci.model.uci")
|
||||||
local SYS = require("luci.sys")
|
local SYS = require("luci.sys")
|
||||||
local TOOLS = require("luci.controller.radicale") -- this application's controller and multiused functions
|
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 -- ################################################
|
-- takeover arguments if any -- ################################################
|
||||||
|
@ -19,8 +48,8 @@ if arg[1] then
|
||||||
|
|
||||||
-- SimpleForm ------------------------------------------------
|
-- SimpleForm ------------------------------------------------
|
||||||
local ft = SimpleForm("_text")
|
local ft = SimpleForm("_text")
|
||||||
ft.title = TOOLS.app_title_back()
|
ft.title = CTRL.app_title_back()
|
||||||
ft.description = TOOLS.app_description()
|
ft.description = CTRL.app_description()
|
||||||
ft.redirect = DISP.build_url("admin", "services", "radicale") .. "#cbi-radicale-" .. argument
|
ft.redirect = DISP.build_url("admin", "services", "radicale") .. "#cbi-radicale-" .. argument
|
||||||
if argument == "logger" then
|
if argument == "logger" then
|
||||||
ft.reset = false
|
ft.reset = false
|
||||||
|
@ -95,54 +124,12 @@ if arg[1] then
|
||||||
|
|
||||||
end
|
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 -- ##################################################################
|
-- cbi-map -- ##################################################################
|
||||||
local m = Map("radicale")
|
local m = Map("radicale")
|
||||||
m.title = TOOLS.app_title_main()
|
m.title = CTRL.app_title_main()
|
||||||
m.description = TOOLS.app_description()
|
m.description = CTRL.app_description()
|
||||||
|
m.template = "radicale/tabmap_nsections"
|
||||||
|
m.tabbed = true
|
||||||
function m.commit_handler(self)
|
function m.commit_handler(self)
|
||||||
if self.changed then -- changes ?
|
if self.changed then -- changes ?
|
||||||
os.execute("/etc/init.d/radicale reload &") -- reload configuration
|
os.execute("/etc/init.d/radicale reload &") -- reload configuration
|
||||||
|
@ -150,11 +137,14 @@ function m.commit_handler(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- cbi-section "System" -- #####################################################
|
-- cbi-section "System" -- #####################################################
|
||||||
local sys = m:section( NamedSection, "_system" )
|
local sys = m:section( NamedSection, "system", "system" )
|
||||||
sys.title = translate("System")
|
sys.title = translate("System")
|
||||||
sys.description = nil
|
sys.description = nil
|
||||||
function sys.cfgvalue(self, section)
|
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
|
end
|
||||||
|
|
||||||
-- start/stop button -----------------------------------------------------------
|
-- start/stop button -----------------------------------------------------------
|
||||||
|
@ -165,7 +155,7 @@ btn.rmempty = true
|
||||||
btn.title = translate("Start / Stop")
|
btn.title = translate("Start / Stop")
|
||||||
btn.description = translate("Start/Stop Radicale server")
|
btn.description = translate("Start/Stop Radicale server")
|
||||||
function btn.cfgvalue(self, section)
|
function btn.cfgvalue(self, section)
|
||||||
local pid = TOOLS.get_pid(true)
|
local pid = CTRL.get_pid(true)
|
||||||
if pid > 0 then
|
if pid > 0 then
|
||||||
btn.inputtitle = "PID: " .. pid
|
btn.inputtitle = "PID: " .. pid
|
||||||
btn.inputstyle = "reset"
|
btn.inputstyle = "reset"
|
||||||
|
@ -183,18 +173,39 @@ local ena = sys:option(Flag, "_enabled")
|
||||||
ena.title = translate("Auto-start")
|
ena.title = translate("Auto-start")
|
||||||
ena.description = translate("Enable/Disable auto-start of Radicale on system start-up and interface events")
|
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.orientation = "horizontal" -- put description under the checkbox
|
||||||
ena.rmempty = false -- we need write
|
ena.rmempty = false -- force write() function
|
||||||
function ena.cfgvalue(self, section)
|
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
|
end
|
||||||
function ena.write(self, section, value)
|
function ena.write(self, section, value)
|
||||||
if value == "1" then
|
if value == self.enabled then
|
||||||
return SYS.init.enable("radicale")
|
return SYS.init.enable("radicale")
|
||||||
else
|
else
|
||||||
return SYS.init.disable("radicale")
|
return SYS.init.disable("radicale")
|
||||||
end
|
end
|
||||||
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" -- #####################################################
|
-- cbi-section "Server" -- #####################################################
|
||||||
local srv = m:section( NamedSection, "server", "setting" )
|
local srv = m:section( NamedSection, "server", "setting" )
|
||||||
srv.title = translate("Server")
|
srv.title = translate("Server")
|
||||||
|
@ -215,15 +226,17 @@ sh.description = translate("'Hostname:Port' or 'IPv4:Port' or '[IPv6]:Port' Radi
|
||||||
.. [[</strong>]]
|
.. [[</strong>]]
|
||||||
sh.placeholder = "0.0.0.0:5232"
|
sh.placeholder = "0.0.0.0:5232"
|
||||||
sh.rmempty = true
|
sh.rmempty = true
|
||||||
|
function sh.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- realm -----------------------------------------------------------------------
|
-- realm -----------------------------------------------------------------------
|
||||||
local alm = srv:option( Value, "realm" )
|
local alm = srv:option( Value, "realm" )
|
||||||
alm.title = translate("Logon message")
|
alm.title = translate("Logon message")
|
||||||
alm.description = translate("Message displayed in the client when a password is needed.")
|
alm.description = translate("Message displayed in the client when a password is needed.")
|
||||||
alm.default = "Radicale - Password Required"
|
alm.default = "Radicale - Password Required"
|
||||||
alm.rmempty = false
|
function alm.parse(self, section, novld)
|
||||||
function alm.parse(self, section)
|
CTRL.value_parse(self, section, novld)
|
||||||
AbstractValue.parse(self, section, "true") -- otherwise unspecific validate error
|
|
||||||
end
|
end
|
||||||
function alm.validate(self, value)
|
function alm.validate(self, value)
|
||||||
if value then
|
if value then
|
||||||
|
@ -232,22 +245,11 @@ function alm.validate(self, value)
|
||||||
return self.default
|
return self.default
|
||||||
end
|
end
|
||||||
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 -------------------------------------------------------------------------
|
-- ssl -------------------------------------------------------------------------
|
||||||
local ssl = srv:option( Flag, "ssl" )
|
local ssl = srv:option( Flag, "ssl" )
|
||||||
ssl.title = translate("Enable HTTPS")
|
ssl.title = translate("Enable HTTPS")
|
||||||
ssl.description = nil
|
ssl.description = nil
|
||||||
ssl.rmempty = false
|
|
||||||
function ssl.parse(self, section)
|
|
||||||
TOOLS.flag_parse(self, section)
|
|
||||||
end
|
|
||||||
function ssl.write(self, section, value)
|
function ssl.write(self, section, value)
|
||||||
if value == "0" then -- delete all if not https enabled
|
if value == "0" then -- delete all if not https enabled
|
||||||
self.map:del(section, "protocol") -- protocol
|
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", "TLS v1")
|
||||||
prt:value ("PROTOCOL_TLSv1_1", "TLS v1.1")
|
prt:value ("PROTOCOL_TLSv1_1", "TLS v1.1")
|
||||||
prt:value ("PROTOCOL_TLSv1_2", "TLS v1.2")
|
prt:value ("PROTOCOL_TLSv1_2", "TLS v1.2")
|
||||||
|
function prt.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- certificate -----------------------------------------------------------------
|
-- certificate -----------------------------------------------------------------
|
||||||
local crt = srv:option( Value, "certificate" )
|
local crt = srv:option( Value, "certificate" )
|
||||||
crt.title = translate("Certificate file")
|
crt.title = translate("Certificate file")
|
||||||
crt.description = translate("Full path and file name of certificate")
|
crt.description = translate("Full path and file name of certificate")
|
||||||
crt.placeholder = "/etc/radicale/ssl/server.crt"
|
crt.placeholder = "/etc/radicale/ssl/server.crt"
|
||||||
crt.rmempty = false -- force validate/write
|
|
||||||
crt:depends ("ssl", "1")
|
crt:depends ("ssl", "1")
|
||||||
function crt.parse(self, section)
|
function crt.parse(self, section, novld)
|
||||||
local _ssl = ssl:formvalue(section) or "0"
|
CTRL.value_parse(self, section, novld)
|
||||||
local novld = (_ssl == "0")
|
|
||||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
|
||||||
end
|
end
|
||||||
function crt.validate(self, value)
|
function crt.validate(self, value)
|
||||||
local _ssl = ssl:formvalue(srv.section) or "0"
|
local _ssl = ssl:formvalue(srv.section) or "0"
|
||||||
|
@ -295,17 +297,10 @@ function crt.validate(self, value)
|
||||||
if DTYP.file(value) then
|
if DTYP.file(value) then
|
||||||
return value
|
return value
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("File not found !")
|
return nil, self.title .. ": " .. translate("File not found !")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Path/File required !")
|
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)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -314,12 +309,9 @@ local key = srv:option( Value, "key" )
|
||||||
key.title = translate("Private key file")
|
key.title = translate("Private key file")
|
||||||
key.description = translate("Full path and file name of private key")
|
key.description = translate("Full path and file name of private key")
|
||||||
key.placeholder = "/etc/radicale/ssl/server.key"
|
key.placeholder = "/etc/radicale/ssl/server.key"
|
||||||
key.rmempty = false -- force validate/write
|
|
||||||
key:depends ("ssl", "1")
|
key:depends ("ssl", "1")
|
||||||
function key.parse(self, section)
|
function key.parse(self, section, novld)
|
||||||
local _ssl = ssl:formvalue(section) or "0"
|
CTRL.value_parse(self, section, novld)
|
||||||
local novld = (_ssl == "0")
|
|
||||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
|
||||||
end
|
end
|
||||||
function key.validate(self, value)
|
function key.validate(self, value)
|
||||||
local _ssl = ssl:formvalue(srv.section) or "0"
|
local _ssl = ssl:formvalue(srv.section) or "0"
|
||||||
|
@ -330,17 +322,10 @@ function key.validate(self, value)
|
||||||
if DTYP.file(value) then
|
if DTYP.file(value) then
|
||||||
return value
|
return value
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("File not found !")
|
return nil, self.title .. ": " .. translate("File not found !")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Path/File required !")
|
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)
|
|
||||||
end
|
end
|
||||||
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 ("HTTP", "HTTP") -- The HTTP authentication module relies on the requests module
|
||||||
--aty:value ("remote_user", "remote_user")
|
--aty:value ("remote_user", "remote_user")
|
||||||
--aty:value ("custom", translate("custom"))
|
--aty:value ("custom", translate("custom"))
|
||||||
|
function aty.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function aty.write(self, section, value)
|
function aty.write(self, section, value)
|
||||||
if value ~= "htpasswd" then
|
if value ~= "htpasswd" then
|
||||||
self.map:del(section, "htpasswd_encryption")
|
self.map:del(section, "htpasswd_encryption")
|
||||||
|
@ -403,9 +391,12 @@ hte:value ("crypt", translate("crypt"))
|
||||||
hte:value ("plain", translate("plain"))
|
hte:value ("plain", translate("plain"))
|
||||||
hte:value ("sha1", translate("SHA-1"))
|
hte:value ("sha1", translate("SHA-1"))
|
||||||
hte:value ("ssha", translate("salted 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) -------------------------------------------------------
|
-- htpasswd_file (dummy) -------------------------------------------------------
|
||||||
local htf = aut:option( DummyValue, "_htf" )
|
local htf = aut:option( Value, "_htf" )
|
||||||
htf.title = translate("htpasswd file")
|
htf.title = translate("htpasswd file")
|
||||||
htf.description = [[<strong>]]
|
htf.description = [[<strong>]]
|
||||||
.. translate("Read only!")
|
.. translate("Read only!")
|
||||||
|
@ -416,9 +407,6 @@ htf.description = [[<strong>]]
|
||||||
.. [[">]]
|
.. [[">]]
|
||||||
.. translate("To edit the file follow this link!")
|
.. translate("To edit the file follow this link!")
|
||||||
.. [[</a>]]
|
.. [[</a>]]
|
||||||
htf.keylist = {} -- required by template
|
|
||||||
htf.vallist = {} -- required by template
|
|
||||||
htf.template = "radicale/ro_value"
|
|
||||||
htf.readonly = true
|
htf.readonly = true
|
||||||
htf:depends ("type", "htpasswd")
|
htf:depends ("type", "htpasswd")
|
||||||
function htf.cfgvalue()
|
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 ("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 ("from_file", translate("Rights are based on a regexp-based file") )
|
||||||
--rty:value ("custom", "Custom handler")
|
--rty:value ("custom", "Custom handler")
|
||||||
|
function rty.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function rty.write(self, section, value)
|
function rty.write(self, section, value)
|
||||||
if value ~= "custom" then
|
if value ~= "custom" then
|
||||||
self.map:del(section, "custom_handler")
|
self.map:del(section, "custom_handler")
|
||||||
|
@ -460,7 +451,7 @@ function rty.write(self, section, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- from_file (dummy) -----------------------------------------------------------
|
-- from_file (dummy) -----------------------------------------------------------
|
||||||
local rtf = rig:option( DummyValue, "_rtf" )
|
local rtf = rig:option( Value, "_rtf" )
|
||||||
rtf.title = translate("RegExp file")
|
rtf.title = translate("RegExp file")
|
||||||
rtf.description = [[<strong>]]
|
rtf.description = [[<strong>]]
|
||||||
.. translate("Read only!")
|
.. translate("Read only!")
|
||||||
|
@ -471,9 +462,6 @@ rtf.description = [[<strong>]]
|
||||||
.. [[">]]
|
.. [[">]]
|
||||||
.. translate("To edit the file follow this link!")
|
.. translate("To edit the file follow this link!")
|
||||||
.. [[</a>]]
|
.. [[</a>]]
|
||||||
rtf.keylist = {} -- required by template
|
|
||||||
rtf.vallist = {} -- required by template
|
|
||||||
rtf.template = "radicale/ro_value"
|
|
||||||
rtf.readonly = true
|
rtf.readonly = true
|
||||||
rtf:depends ("type", "from_file")
|
rtf:depends ("type", "from_file")
|
||||||
function rtf.cfgvalue()
|
function rtf.cfgvalue()
|
||||||
|
@ -501,6 +489,9 @@ sty:value ("filesystem", translate("File-system"))
|
||||||
--sty:value ("multifilesystem", translate("") )
|
--sty:value ("multifilesystem", translate("") )
|
||||||
--sty:value ("database", translate("Database") )
|
--sty:value ("database", translate("Database") )
|
||||||
--sty:value ("custom", translate("Custom") )
|
--sty:value ("custom", translate("Custom") )
|
||||||
|
function sty.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function sty.write(self, section, value)
|
function sty.write(self, section, value)
|
||||||
if value ~= "filesystem" then
|
if value ~= "filesystem" then
|
||||||
self.map:del(section, "filesystem_folder")
|
self.map:del(section, "filesystem_folder")
|
||||||
|
@ -516,13 +507,10 @@ end
|
||||||
local sfi = sto:option( Value, "filesystem_folder" )
|
local sfi = sto:option( Value, "filesystem_folder" )
|
||||||
sfi.title = translate("Directory")
|
sfi.title = translate("Directory")
|
||||||
sfi.description = nil
|
sfi.description = nil
|
||||||
sfi.default = "/srv/radicale"
|
sfi.placeholder = "/srv/radicale"
|
||||||
sfi.rmempty = false -- force validate/write
|
|
||||||
sfi:depends ("type", "filesystem")
|
sfi:depends ("type", "filesystem")
|
||||||
function sfi.parse(self, section)
|
function sfi.parse(self, section, novld)
|
||||||
local _typ = sty:formvalue(sto.section) or ""
|
CTRL.value_parse(self, section, novld)
|
||||||
local novld = (_typ ~= "filesystem")
|
|
||||||
AbstractValue.parse(self, section, novld) -- otherwise unspecific validate error
|
|
||||||
end
|
end
|
||||||
function sfi.validate(self, value)
|
function sfi.validate(self, value)
|
||||||
local _typ = sty:formvalue(sto.section) or ""
|
local _typ = sty:formvalue(sto.section) or ""
|
||||||
|
@ -533,10 +521,10 @@ function sfi.validate(self, value)
|
||||||
if DTYP.directory(value) then
|
if DTYP.directory(value) then
|
||||||
return value
|
return value
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Directory not exists/found !")
|
return nil, self.title .. ": " .. translate("Directory not exists/found !")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Directory required !")
|
return nil, self.title .. ": " .. translate("Directory required !")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -562,6 +550,9 @@ lco:value ("INFO", translate("Info") )
|
||||||
lco:value ("WARNING", translate("Warning") )
|
lco:value ("WARNING", translate("Warning") )
|
||||||
lco:value ("ERROR", translate("Error") )
|
lco:value ("ERROR", translate("Error") )
|
||||||
lco:value ("CRITICAL", translate("Critical") )
|
lco:value ("CRITICAL", translate("Critical") )
|
||||||
|
function lco.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function lco.write(self, section, value)
|
function lco.write(self, section, value)
|
||||||
if value ~= self.default then
|
if value ~= self.default then
|
||||||
return self.map:set(section, self.option, value)
|
return self.map:set(section, self.option, value)
|
||||||
|
@ -581,6 +572,9 @@ lsl:value ("INFO", translate("Info") )
|
||||||
lsl:value ("WARNING", translate("Warning") )
|
lsl:value ("WARNING", translate("Warning") )
|
||||||
lsl:value ("ERROR", translate("Error") )
|
lsl:value ("ERROR", translate("Error") )
|
||||||
lsl:value ("CRITICAL", translate("Critical") )
|
lsl:value ("CRITICAL", translate("Critical") )
|
||||||
|
function lsl.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function lsl.write(self, section, value)
|
function lsl.write(self, section, value)
|
||||||
if value ~= self.default then
|
if value ~= self.default then
|
||||||
return self.map:set(section, self.option, value)
|
return self.map:set(section, self.option, value)
|
||||||
|
@ -600,6 +594,9 @@ lfi:value ("INFO", translate("Info") )
|
||||||
lfi:value ("WARNING", translate("Warning") )
|
lfi:value ("WARNING", translate("Warning") )
|
||||||
lfi:value ("ERROR", translate("Error") )
|
lfi:value ("ERROR", translate("Error") )
|
||||||
lfi:value ("CRITICAL", translate("Critical") )
|
lfi:value ("CRITICAL", translate("Critical") )
|
||||||
|
function lfi.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function lfi.write(self, section, value)
|
function lfi.write(self, section, value)
|
||||||
if value ~= self.default then
|
if value ~= self.default then
|
||||||
return self.map:set(section, self.option, value)
|
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!")
|
.. translate("To view latest log file follow this link!")
|
||||||
.. [[</a>]]
|
.. [[</a>]]
|
||||||
lfp.default = "/var/log/radicale"
|
lfp.default = "/var/log/radicale"
|
||||||
function lfp.write(self, section, value)
|
function lfp.parse(self, section, novld)
|
||||||
if value ~= self.default then
|
CTRL.value_parse(self, section, novld)
|
||||||
return self.map:set(section, self.option, value)
|
end
|
||||||
else
|
function lfp.validate(self, value)
|
||||||
return self.map:del(section, self.option)
|
if not value or (#value < 1) or (value:find("/") ~= 1) then
|
||||||
|
return nil, self.title .. ": " .. translate("no valid path given!")
|
||||||
end
|
end
|
||||||
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
-- file_maxbytes ---------------------------------------------------------------
|
-- 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.")
|
.. translate("Setting this parameter to '0' will disable rotation of log-file.")
|
||||||
.. [[</strong>]]
|
.. [[</strong>]]
|
||||||
lmb.default = "8196"
|
lmb.default = "8196"
|
||||||
lmb.rmempty = false
|
function lmb.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function lmb.validate(self, value)
|
function lmb.validate(self, value)
|
||||||
if value then -- otherwise errors in datatype check
|
if value then -- otherwise errors in datatype check
|
||||||
if DTYP.uinteger(value) then
|
if DTYP.uinteger(value) then
|
||||||
return value
|
return value
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Value is not an Integer >= 0 !")
|
return nil, self.title .. ": " .. translate("Value is not an Integer >= 0 !")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Value required ! Integer >= 0 !")
|
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)
|
|
||||||
end
|
end
|
||||||
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.")
|
.. translate("Setting this parameter to '0' will disable rotation of log-file.")
|
||||||
.. [[</strong>]]
|
.. [[</strong>]]
|
||||||
lbc.default = "1"
|
lbc.default = "1"
|
||||||
lbc.rmempty = false
|
function lbc.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
function lbc.validate(self, value)
|
function lbc.validate(self, value)
|
||||||
if value then -- otherwise errors in datatype check
|
if value then -- otherwise errors in datatype check
|
||||||
if DTYP.uinteger(value) then
|
if DTYP.uinteger(value) then
|
||||||
return value
|
return value
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Value is not an Integer >= 0 !")
|
return nil, self.title .. ": " .. translate("Value is not an Integer >= 0 !")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return nil, self.title .. " - " .. translate("Value required ! Integer >= 0 !")
|
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)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -699,14 +688,18 @@ local enr = enc:option( Value, "request" )
|
||||||
enr.title = translate("Response Encoding")
|
enr.title = translate("Response Encoding")
|
||||||
enr.description = translate("Encoding for responding requests.")
|
enr.description = translate("Encoding for responding requests.")
|
||||||
enr.default = "utf-8"
|
enr.default = "utf-8"
|
||||||
enr.optional = true
|
function enr.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- stock -----------------------------------------------------------------------
|
-- stock -----------------------------------------------------------------------
|
||||||
local ens = enc:option( Value, "stock" )
|
local ens = enc:option( Value, "stock" )
|
||||||
ens.title = translate("Storage Encoding")
|
ens.title = translate("Storage Encoding")
|
||||||
ens.description = translate("Encoding for storing local collections.")
|
ens.description = translate("Encoding for storing local collections.")
|
||||||
ens.default = "utf-8"
|
ens.default = "utf-8"
|
||||||
ens.optional = true
|
function ens.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- cbi-section "Headers" -- ####################################################
|
-- cbi-section "Headers" -- ####################################################
|
||||||
local hea = m:section( NamedSection, "headers", "setting" )
|
local hea = m:section( NamedSection, "headers", "setting" )
|
||||||
|
@ -724,25 +717,32 @@ end
|
||||||
local heo = hea:option( DynamicList, "Access_Control_Allow_Origin" )
|
local heo = hea:option( DynamicList, "Access_Control_Allow_Origin" )
|
||||||
heo.title = translate("Access-Control-Allow-Origin")
|
heo.title = translate("Access-Control-Allow-Origin")
|
||||||
heo.description = nil
|
heo.description = nil
|
||||||
heo.default = "*"
|
function heo.parse(self, section, novld)
|
||||||
heo.optional = true
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- Access_Control_Allow_Methods ------------------------------------------------
|
-- Access_Control_Allow_Methods ------------------------------------------------
|
||||||
local hem = hea:option( DynamicList, "Access_Control_Allow_Methods" )
|
local hem = hea:option( DynamicList, "Access_Control_Allow_Methods" )
|
||||||
hem.title = translate("Access-Control-Allow-Methods")
|
hem.title = translate("Access-Control-Allow-Methods")
|
||||||
hem.description = nil
|
hem.description = nil
|
||||||
hem.optional = true
|
function hem.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- Access_Control_Allow_Headers ------------------------------------------------
|
-- Access_Control_Allow_Headers ------------------------------------------------
|
||||||
local heh = hea:option( DynamicList, "Access_Control_Allow_Headers" )
|
local heh = hea:option( DynamicList, "Access_Control_Allow_Headers" )
|
||||||
heh.title = translate("Access-Control-Allow-Headers")
|
heh.title = translate("Access-Control-Allow-Headers")
|
||||||
heh.description = nil
|
heh.description = nil
|
||||||
heh.optional = true
|
function heh.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
-- Access_Control_Expose_Headers -----------------------------------------------
|
-- Access_Control_Expose_Headers -----------------------------------------------
|
||||||
local hee = hea:option( DynamicList, "Access_Control_Expose_Headers" )
|
local hee = hea:option( DynamicList, "Access_Control_Expose_Headers" )
|
||||||
hee.title = translate("Access-Control-Expose-Headers")
|
hee.title = translate("Access-Control-Expose-Headers")
|
||||||
hee.description = nil
|
hee.description = nil
|
||||||
hee.optional = true
|
function hee.parse(self, section, novld)
|
||||||
|
CTRL.value_parse(self, section, novld)
|
||||||
|
end
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// show XHR.poll/XHR.get response on button
|
// show XHR.poll/XHR.get response on button
|
||||||
function _data2elements(x) {
|
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 ( ! btn ) { return; } // security check
|
||||||
if (x.responseText == "0") {
|
if (x.responseText == "0") {
|
||||||
btn.value = "<%:Start%>";
|
btn.value = "<%:Start%>";
|
||||||
|
@ -21,12 +21,12 @@
|
||||||
function onclick_startstop(id) {
|
function onclick_startstop(id) {
|
||||||
// do start/stop
|
// do start/stop
|
||||||
var btnXHR = new XHR();
|
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); }
|
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); }
|
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 ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: luci-app-radicale\n"
|
"Project-Id-Version: luci-app-radicale 1.1.0-1\n"
|
||||||
"POT-Creation-Date: 2015-05-02 19:32+0100\n"
|
"POT-Creation-Date: 2016-01-30 20:34+0100\n"
|
||||||
"PO-Revision-Date: 2015-05-02 22:43+0100\n"
|
"PO-Revision-Date: 2016-01-31 20:49+0100\n"
|
||||||
"Last-Translator: Christian Schoenebeck <christian.schoenebeck@gmail.com>\n"
|
"Last-Translator: Christian Schönebeck <christian.schoenebeck@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\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"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Poedit-SourceCharset: UTF-8\n"
|
"X-Poedit-SourceCharset: UTF-8\n"
|
||||||
|
|
||||||
|
@ -72,6 +72,9 @@ msgstr ""
|
||||||
msgid "Auto-start"
|
msgid "Auto-start"
|
||||||
msgstr "Autostart"
|
msgstr "Autostart"
|
||||||
|
|
||||||
|
msgid "Boot delay"
|
||||||
|
msgstr "Systemstart-Verzögerung"
|
||||||
|
|
||||||
msgid "CalDAV/CardDAV"
|
msgid "CalDAV/CardDAV"
|
||||||
msgstr "CalDAV/CardDAV"
|
msgstr "CalDAV/CardDAV"
|
||||||
|
|
||||||
|
@ -122,6 +125,10 @@ msgstr "Datenbank"
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr "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"
|
msgid "Directory"
|
||||||
msgstr "Verzeichnis"
|
msgstr "Verzeichnis"
|
||||||
|
|
||||||
|
@ -135,6 +142,9 @@ msgid "Directory where the rotating log-files are stored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Verzeichnis in dem die rollierenden Protokolldateien gespeichert werden"
|
"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"
|
msgid "Enable HTTPS"
|
||||||
msgstr "Verwende 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"
|
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||||
msgstr "OPTIONAL: Siehe Python SSL-Modul Dokumentation"
|
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"
|
msgid "Owner allow write, authenticated users allow read"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Besitzer haben Schreibrechte, Authentifizierten Benutzer dürfen nur lesen."
|
"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 "
|
"Wenn dieser Parameter auf '0' gesetzt wird, wird die Protokolldatei nicht "
|
||||||
"mehr rolliert!"
|
"mehr rolliert!"
|
||||||
|
|
||||||
msgid "Software package '"
|
msgid "Software package '%s' is not installed."
|
||||||
msgstr "Software Packet '"
|
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"
|
msgid "Start"
|
||||||
msgstr "Start"
|
msgstr "Start"
|
||||||
|
@ -372,9 +391,15 @@ msgid "To view latest log file follow this link!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Zur Anzeige der letzten Protokolldatei, folgen Sie dieser Verknüpfung !"
|
"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 !"
|
msgid "Value is not an Integer >= 0 !"
|
||||||
msgstr "Eingabe ist keine Ganzzahl >= 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 !"
|
msgid "Value required ! Integer >= 0 !"
|
||||||
msgstr "Eingabe erforderlich ! Ganzzahl >= 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}, "
|
"You can also get groups from the user regex in the collection with {0}, {1}, "
|
||||||
"etc."
|
"etc."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Sie können auch Gruppen aus der Benutzer regex in der Sammlung mit {0}, {1} "
|
||||||
|
"usw. bekommen."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"You can use Python's ConfigParser interpolation values %(login)s and "
|
"You can use Python's ConfigParser interpolation values %(login)s and "
|
||||||
|
@ -416,6 +443,9 @@ msgstr "htpasswd Datei"
|
||||||
msgid "installed"
|
msgid "installed"
|
||||||
msgstr "installiert"
|
msgstr "installiert"
|
||||||
|
|
||||||
|
msgid "no valid path given!"
|
||||||
|
msgstr "Keine gültige Pfadangabe!"
|
||||||
|
|
||||||
msgid "or higher"
|
msgid "or higher"
|
||||||
msgstr "oder höher"
|
msgstr "oder höher"
|
||||||
|
|
||||||
|
@ -427,9 +457,3 @@ msgstr "erforderlich"
|
||||||
|
|
||||||
msgid "salted SHA-1"
|
msgid "salted SHA-1"
|
||||||
msgstr "Salted SHA-1"
|
msgstr "Salted SHA-1"
|
||||||
|
|
||||||
#~ msgid "File"
|
|
||||||
#~ msgstr "Datei"
|
|
||||||
|
|
||||||
#~ msgid "not found !"
|
|
||||||
#~ msgstr "nicht gefunden !"
|
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
msgid ""
|
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 ""
|
msgid ""
|
||||||
"'AUTO' selects the highest protocol version that client and server support."
|
"'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"
|
msgid "Auto-start"
|
||||||
msgstr "Starta automatiskt"
|
msgstr "Starta automatiskt"
|
||||||
|
|
||||||
|
msgid "Boot delay"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "CalDAV/CardDAV"
|
msgid "CalDAV/CardDAV"
|
||||||
msgstr "CalDAV/CardDAV"
|
msgstr "CalDAV/CardDAV"
|
||||||
|
|
||||||
|
@ -98,6 +111,9 @@ msgstr "Databas"
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr "Felsök"
|
msgstr "Felsök"
|
||||||
|
|
||||||
|
msgid "Delay (in seconds) during system boot before Radicale start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Directory"
|
msgid "Directory"
|
||||||
msgstr "Mapp"
|
msgstr "Mapp"
|
||||||
|
|
||||||
|
@ -110,6 +126,9 @@ msgstr "Mapp krävs !"
|
||||||
msgid "Directory where the rotating log-files are stored"
|
msgid "Directory where the rotating log-files are stored"
|
||||||
msgstr "Mappen där de roterade logg-filerna lagras"
|
msgstr "Mappen där de roterade logg-filerna lagras"
|
||||||
|
|
||||||
|
msgid "During delay ifup-events are not monitored !"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable HTTPS"
|
msgid "Enable HTTPS"
|
||||||
msgstr "Aktivera HTTPS"
|
msgstr "Aktivera HTTPS"
|
||||||
|
|
||||||
|
@ -209,6 +228,9 @@ msgstr ""
|
||||||
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||||
msgstr "VALFRITT: Kolla in python's ssl-modul för tillgängliga chiffer"
|
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"
|
msgid "Owner allow write, authenticated users allow read"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -289,8 +311,14 @@ msgstr ""
|
||||||
"Genom att ställa in den här parametern till '0' så kommer du att stänga av "
|
"Genom att ställa in den här parametern till '0' så kommer du att stänga av "
|
||||||
"rotering av logg-fil."
|
"rotering av logg-fil."
|
||||||
|
|
||||||
msgid "Software package '"
|
msgid "Software package '%s' is not installed."
|
||||||
msgstr "Mjukvaru-paket '"
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Software package '%s' is outdated."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Software update required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Start"
|
msgid "Start"
|
||||||
msgstr "Starta"
|
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!"
|
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"
|
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 !"
|
msgid "Value is not an Integer >= 0 !"
|
||||||
msgstr "Värdet är inte ett heltal >= 0 !"
|
msgstr "Värdet är inte ett heltal >= 0 !"
|
||||||
|
|
||||||
|
msgid "Value not between 0 and 300"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Value required ! Integer >= 0 !"
|
msgid "Value required ! Integer >= 0 !"
|
||||||
msgstr "Värde krävs ! Heltal >= 0 !"
|
msgstr "Värde krävs ! Heltal >= 0 !"
|
||||||
|
|
||||||
|
@ -375,6 +409,9 @@ msgstr "htpasswd-fil"
|
||||||
msgid "installed"
|
msgid "installed"
|
||||||
msgstr "installerad"
|
msgstr "installerad"
|
||||||
|
|
||||||
|
msgid "no valid path given!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "or higher"
|
msgid "or higher"
|
||||||
msgstr "eller högre"
|
msgstr "eller högre"
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ msgstr ""
|
||||||
msgid "Auto-start"
|
msgid "Auto-start"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Boot delay"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "CalDAV/CardDAV"
|
msgid "CalDAV/CardDAV"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -96,6 +99,9 @@ msgstr ""
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Delay (in seconds) during system boot before Radicale start"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Directory"
|
msgid "Directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -108,6 +114,9 @@ msgstr ""
|
||||||
msgid "Directory where the rotating log-files are stored"
|
msgid "Directory where the rotating log-files are stored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "During delay ifup-events are not monitored !"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable HTTPS"
|
msgid "Enable HTTPS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -207,6 +216,9 @@ msgstr ""
|
||||||
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
msgid "OPTIONAL: See python's ssl module for available ciphers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "One or more missing/invalid fields on tab"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Owner allow write, authenticated users allow read"
|
msgid "Owner allow write, authenticated users allow read"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -284,7 +296,13 @@ msgstr ""
|
||||||
msgid "Setting this parameter to '0' will disable rotation of log-file."
|
msgid "Setting this parameter to '0' will disable rotation of log-file."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Software package '"
|
msgid "Software package '%s' is not installed."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Software package '%s' is outdated."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Software update required"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Start"
|
msgid "Start"
|
||||||
|
@ -327,9 +345,15 @@ msgstr ""
|
||||||
msgid "To view latest log file follow this link!"
|
msgid "To view latest log file follow this link!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Value is not a number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Value is not an Integer >= 0 !"
|
msgid "Value is not an Integer >= 0 !"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Value not between 0 and 300"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Value required ! Integer >= 0 !"
|
msgid "Value required ! Integer >= 0 !"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -368,6 +392,9 @@ msgstr ""
|
||||||
msgid "installed"
|
msgid "installed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "no valid path given!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "or higher"
|
msgid "or higher"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue