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:
Christian Schoenebeck 2016-02-07 09:30:29 +01:00
parent 26d009aff9
commit 026ac8d033
9 changed files with 485 additions and 341 deletions

View file

@ -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

View file

@ -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">&nbsp;&nbsp;&nbsp;&nbsp;]]
.. I18N.translate("Software package '%s' is not installed." % srv_name)
.. [[</font><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. I18N.translate("required") .. [[: ]] .. srv_name .. [[ ]] .. srv_ver_min
.. [[<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;]]
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
.. I18N.translate("Please install current version !")
.. [[</a><br />&nbsp;</strong></h3>]]
else
return [[<h3><strong><br /><font color="red">&nbsp;&nbsp;&nbsp;&nbsp;]]
.. I18N.translate("Software package '%s' is outdated." % srv_name)
.. [[</font><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. I18N.translate("installed") .. [[: ]] .. srv_name .. [[ ]] .. service_version()
.. [[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. I18N.translate("required") .. [[: ]] .. srv_name .. [[ ]] .. srv_ver_min
.. [[<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;]]
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
.. I18N.translate("Please update to current version !")
.. [[</a><br />&nbsp;</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

View file

@ -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">&nbsp;&nbsp;&nbsp;&nbsp;]]
.. translate("Software package '" .. TOOLS.service_name() .. "' is not installed.")
.. [[</font><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
.. [[<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;]]
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
.. translate("Please install current version !")
.. [[</a><br />&nbsp;</strong></h3>]]
else
v.value = [[<h3><strong><br /><font color="red">&nbsp;&nbsp;&nbsp;&nbsp;]]
.. translate("Software package '" .. TOOLS.service_name() .. "' is outdated.")
.. [[</font><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. translate("installed") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_installed()
.. [[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]
.. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
.. [[<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;]]
.. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
.. translate("Please update to current version !")
.. [[</a><br />&nbsp;</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

View file

@ -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); }
);

View file

@ -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%>

View file

@ -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%>:&nbsp;<%=section.title or section.section or section.sectiontype%>
</li></ul>
<%- end %>
<% end %>
</div>
<%- end %>
<br />
</div>

View file

@ -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 !"

View file

@ -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"

View file

@ -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 ""