123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- -- Copyright 2015 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
- -- #################################################################################################
- -- takeover arguments if any -- ################################################
- -- then show/edit selected file
- if arg[1] then
- local argument = arg[1]
- local filename = ""
- -- SimpleForm ------------------------------------------------
- local ft = SimpleForm("_text")
- ft.title = TOOLS.app_title_back()
- ft.description = TOOLS.app_description()
- ft.redirect = DISP.build_url("admin", "services", "radicale") .. "#cbi-radicale-" .. argument
- if argument == "logger" then
- ft.reset = false
- ft.submit = translate("Reload")
- local uci = UCI.cursor()
- filename = uci:get("radicale", "logger", "file_path") or "/var/log/radicale"
- uci:unload("radicale")
- filename = filename .. "/radicale"
- elseif argument == "auth" then
- ft.submit = translate("Save")
- filename = "/etc/radicale/users"
- elseif argument == "rights" then
- ft.submit = translate("Save")
- filename = "/etc/radicale/rights"
- else
- error("Invalid argument given as section")
- end
- if argument ~= "logger" and not NXFS.access(filename) then
- NXFS.writefile(filename, "")
- end
- -- SimpleSection ---------------------------------------------
- local fs = ft:section(SimpleSection)
- if argument == "logger" then
- fs.title = translate("Log-file Viewer")
- fs.description = translate("Please press [Reload] button below to reread the file.")
- elseif argument == "auth" then
- fs.title = translate("Authentication")
- fs.description = translate("Place here the 'user:password' pairs for your users which should have access to Radicale.")
- .. [[<br /><strong>]]
- .. translate("Keep in mind to use the correct hashing algorithm !")
- .. [[</strong>]]
- else -- rights
- fs.title = translate("Rights")
- fs.description = translate("Authentication login is matched against the 'user' key, "
- .. "and collection's path is matched against the 'collection' key.") .. " "
- .. translate("You can use Python's ConfigParser interpolation values %(login)s and %(path)s.") .. " "
- .. translate("You can also get groups from the user regex in the collection with {0}, {1}, etc.")
- .. [[<br />]]
- .. translate("For example, for the 'user' key, '.+' means 'authenticated user'" .. " "
- .. "and '.*' means 'anybody' (including anonymous users).")
- .. [[<br />]]
- .. translate("Section names are only used for naming the rule.")
- .. [[<br />]]
- .. translate("Leading or ending slashes are trimmed from collection's path.")
- end
- -- TextValue -------------------------------------------------
- local tt = fs:option(TextValue, "_textvalue")
- tt.rmempty = true
- if argument == "logger" then
- tt.readonly = true
- tt.rows = 30
- function tt.write()
- HTTP.redirect(DISP.build_url("admin", "services", "radicale", "edit", argument))
- end
- else
- tt.rows = 15
- function tt.write(self, section, value)
- if not value then value = "" end
- NXFS.writefile(filename, value:gsub("\r\n", "\n"))
- return true --HTTP.redirect(DISP.build_url("admin", "services", "radicale", "edit") .. "#cbi-radicale-" .. argument)
- end
- end
- function tt.cfgvalue()
- return NXFS.readfile(filename) or
- string.format(translate("File '%s' not found !"), filename)
- end
- return ft
- end
- -- #################################################################################################
- -- Error handling if not installed or wrong version -- #########################
- if not TOOLS.service_ok() then
- local f = SimpleForm("_no_config")
- f.title = TOOLS.app_title_main()
- f.description = TOOLS.app_description()
- f.submit = false
- f.reset = false
- local s = f:section(SimpleSection)
- local v = s:option(DummyValue, "_update_needed")
- v.rawhtml = true
- if TOOLS.service_installed() == "0" then
- v.value = [[<h3><strong><br /><font color="red"> ]]
- .. translate("Software package '" .. TOOLS.service_name() .. "' is not installed.")
- .. [[</font><br /><br /> ]]
- .. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
- .. [[<br /><br /> ]]
- .. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
- .. translate("Please install current version !")
- .. [[</a><br /> </strong></h3>]]
- else
- v.value = [[<h3><strong><br /><font color="red"> ]]
- .. translate("Software package '" .. TOOLS.service_name() .. "' is outdated.")
- .. [[</font><br /><br /> ]]
- .. translate("installed") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_installed()
- .. [[<br /> ]]
- .. translate("required") .. [[: ]] .. TOOLS.service_name() .. [[ ]] .. TOOLS.service_required()
- .. [[<br /><br /> ]]
- .. [[<a href="]] .. DISP.build_url("admin", "system", "packages") ..[[">]]
- .. translate("Please update to current version !")
- .. [[</a><br /> </strong></h3>]]
- end
- return f
- end
- -- #################################################################################################
- -- Error handling if no config, create an empty one -- #########################
- if not NXFS.access("/etc/config/radicale") then
- NXFS.writefile("/etc/config/radicale", "")
- end
- -- cbi-map -- ##################################################################
- local m = Map("radicale")
- m.title = TOOLS.app_title_main()
- m.description = TOOLS.app_description()
- function m.commit_handler(self)
- if self.changed then -- changes ?
- os.execute("/etc/init.d/radicale reload &") -- reload configuration
- end
- end
- -- cbi-section "System" -- #####################################################
- local sys = m:section( NamedSection, "_system" )
- sys.title = translate("System")
- sys.description = nil
- function sys.cfgvalue(self, section)
- return "_dummysection"
- end
- -- start/stop button -----------------------------------------------------------
- local btn = sys:option(DummyValue, "_startstop")
- btn.template = "radicale/btn_startstop"
- btn.inputstyle = nil
- 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)
- if pid > 0 then
- btn.inputtitle = "PID: " .. pid
- btn.inputstyle = "reset"
- btn.disabled = false
- else
- btn.inputtitle = translate("Start")
- btn.inputstyle = "apply"
- btn.disabled = false
- end
- return true
- end
- -- enabled ---------------------------------------------------------------------
- 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
- function ena.cfgvalue(self, section)
- return (SYS.init.enabled("radicale")) and "1" or "0"
- end
- function ena.write(self, section, value)
- if value == "1" then
- return SYS.init.enable("radicale")
- else
- return SYS.init.disable("radicale")
- end
- end
- -- cbi-section "Server" -- #####################################################
- local srv = m:section( NamedSection, "server", "setting" )
- srv.title = translate("Server")
- srv.description = nil
- function srv.cfgvalue(self, section)
- 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
- -- hosts -----------------------------------------------------------------------
- local sh = srv:option( DynamicList, "hosts" )
- sh.title = translate("Address:Port")
- sh.description = translate("'Hostname:Port' or 'IPv4:Port' or '[IPv6]:Port' Radicale should listen on")
- .. [[<br /><strong>]]
- .. translate("Port numbers below 1024 (Privileged ports) are not supported")
- .. [[</strong>]]
- sh.placeholder = "0.0.0.0:5232"
- sh.rmempty = true
- -- 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
- end
- function alm.validate(self, value)
- if value then
- return value
- else
- 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
- self.map:del(section, "certificate") -- certificate
- self.map:del(section, "key") -- private key
- self.map:del(section, "ciphers") -- ciphers
- return self.map:del(section, self.option)
- else
- return self.map:set(section, self.option, value)
- end
- end
- -- protocol --------------------------------------------------------------------
- local prt = srv:option( ListValue, "protocol" )
- prt.title = translate("SSL Protocol")
- prt.description = translate("'AUTO' selects the highest protocol version that client and server support.")
- prt.widget = "select"
- prt.default = "PROTOCOL_SSLv23"
- prt:depends ("ssl", "1")
- prt:value ("PROTOCOL_SSLv23", translate("AUTO"))
- prt:value ("PROTOCOL_SSLv2", "SSL v2")
- 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")
- -- 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
- end
- function crt.validate(self, value)
- local _ssl = ssl:formvalue(srv.section) or "0"
- if _ssl == "0" then
- return "" -- ignore if not https enabled
- end
- if value then -- otherwise errors in datatype check
- if DTYP.file(value) then
- return value
- else
- 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)
- end
- end
- -- key -------------------------------------------------------------------------
- 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
- end
- function key.validate(self, value)
- local _ssl = ssl:formvalue(srv.section) or "0"
- if _ssl == "0" then
- return "" -- ignore if not https enabled
- end
- if value then -- otherwise errors in datatype check
- if DTYP.file(value) then
- return value
- else
- 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)
- end
- end
- -- ciphers ---------------------------------------------------------------------
- --local cip = srv:option( Value, "ciphers" )
- --cip.title = translate("Ciphers")
- --cip.description = translate("OPTIONAL: See python's ssl module for available ciphers")
- --cip.rmempty = true
- --cip:depends ("ssl", "1")
- -- cbi-section "Authentication" -- #############################################
- local aut = m:section( NamedSection, "auth", "setting" )
- aut.title = translate("Authentication")
- aut.description = translate("Authentication method to allow access to Radicale server.")
- function aut.cfgvalue(self, section)
- 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
- -- type -----------------------------------------------------------------------
- local aty = aut:option( ListValue, "type" )
- aty.title = translate("Authentication method")
- aty.description = nil
- aty.widget = "select"
- aty.default = "None"
- aty:value ("None", translate("None"))
- aty:value ("htpasswd", translate("htpasswd file"))
- --aty:value ("IMAP", "IMAP") -- The IMAP authentication module relies on the imaplib module.
- --aty:value ("LDAP", "LDAP") -- The LDAP authentication module relies on the python-ldap module.
- --aty:value ("PAM", "PAM") -- The PAM authentication module relies on the python-pam module.
- --aty:value ("courier", "courier")
- --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.write(self, section, value)
- if value ~= "htpasswd" then
- self.map:del(section, "htpasswd_encryption")
- elseif value ~= "IMAP" then
- self.map:del(section, "imap_hostname")
- self.map:del(section, "imap_port")
- self.map:del(section, "imap_ssl")
- end
- if value ~= self.default then
- return self.map:set(section, self.option, value)
- else
- return self.map:del(section, self.option)
- end
- end
- -- htpasswd_encryption ---------------------------------------------------------
- local hte = aut:option( ListValue, "htpasswd_encryption" )
- hte.title = translate("Encryption method")
- hte.description = nil
- hte.widget = "select"
- hte.default = "crypt"
- hte:depends ("type", "htpasswd")
- hte:value ("crypt", translate("crypt"))
- hte:value ("plain", translate("plain"))
- hte:value ("sha1", translate("SHA-1"))
- hte:value ("ssha", translate("salted SHA-1"))
- -- htpasswd_file (dummy) -------------------------------------------------------
- local htf = aut:option( DummyValue, "_htf" )
- htf.title = translate("htpasswd file")
- htf.description = [[<strong>]]
- .. translate("Read only!")
- .. [[</strong> ]]
- .. translate("Radicale uses '/etc/radicale/users' as htpasswd file.")
- .. [[<br /><a href="]]
- .. DISP.build_url("admin", "services", "radicale", "edit") .. [[/auth]]
- .. [[">]]
- .. 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()
- return "/etc/radicale/users"
- end
- -- cbi-section "Rights" -- #####################################################
- local rig = m:section( NamedSection, "rights", "setting" )
- rig.title = translate("Rights")
- rig.description = translate("Control the access to data collections.")
- function rig.cfgvalue(self, section)
- 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
- -- type -----------------------------------------------------------------------
- local rty = rig:option( ListValue, "type" )
- rty.title = translate("Rights backend")
- rty.description = nil
- rty.widget = "select"
- rty.default = "None"
- rty:value ("None", translate("Full access for everybody (including anonymous)"))
- rty:value ("authenticated", translate("Full access for authenticated Users") )
- 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.write(self, section, value)
- if value ~= "custom" then
- self.map:del(section, "custom_handler")
- end
- if value ~= self.default then
- return self.map:set(section, self.option, value)
- else
- return self.map:del(section, self.option)
- end
- end
- -- from_file (dummy) -----------------------------------------------------------
- local rtf = rig:option( DummyValue, "_rtf" )
- rtf.title = translate("RegExp file")
- rtf.description = [[<strong>]]
- .. translate("Read only!")
- .. [[</strong> ]]
- .. translate("Radicale uses '/etc/radicale/rights' as regexp-based file.")
- .. [[<br /><a href="]]
- .. DISP.build_url("admin", "services", "radicale", "edit") .. [[/rights]]
- .. [[">]]
- .. 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()
- return "/etc/radicale/rights"
- end
- -- cbi-section "Storage" -- ####################################################
- local sto = m:section( NamedSection, "storage", "setting" )
- sto.title = translate("Storage")
- sto.description = nil
- function sto.cfgvalue(self, section)
- 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
- -- type -----------------------------------------------------------------------
- local sty = sto:option( ListValue, "type" )
- sty.title = translate("Storage backend")
- sty.description = translate("WARNING: Only 'File-system' is documented and tested by Radicale development")
- sty.widget = "select"
- sty.default = "filesystem"
- sty:value ("filesystem", translate("File-system"))
- --sty:value ("multifilesystem", translate("") )
- --sty:value ("database", translate("Database") )
- --sty:value ("custom", translate("Custom") )
- function sty.write(self, section, value)
- if value ~= "filesystem" then
- self.map:del(section, "filesystem_folder")
- end
- if value ~= self.default then
- return self.map:set(section, self.option, value)
- else
- return self.map:del(section, self.option)
- end
- end
- --filesystem_folder ------------------------------------------------------------
- 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: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
- end
- function sfi.validate(self, value)
- local _typ = sty:formvalue(sto.section) or ""
- if _typ ~= "filesystem" then
- return "" -- ignore if not htpasswd
- end
- if value then -- otherwise errors in datatype check
- if DTYP.directory(value) then
- return value
- else
- return nil, self.title .. " - " .. translate("Directory not exists/found !")
- end
- else
- return nil, self.title .. " - " .. translate("Directory required !")
- end
- end
- -- cbi-section "Logging" -- ####################################################
- local log = m:section( NamedSection, "logger", "logging" )
- log.title = translate("Logging")
- log.description = nil
- function log.cfgvalue(self, section)
- 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
- -- console_level ---------------------------------------------------------------
- local lco = log:option( ListValue, "console_level" )
- lco.title = translate("Console Log level")
- lco.description = nil
- lco.widget = "select"
- lco.default = "ERROR"
- lco:value ("DEBUG", translate("Debug"))
- lco:value ("INFO", translate("Info") )
- lco:value ("WARNING", translate("Warning") )
- lco:value ("ERROR", translate("Error") )
- lco:value ("CRITICAL", translate("Critical") )
- function lco.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
- -- syslog_level ----------------------------------------------------------------
- local lsl = log:option( ListValue, "syslog_level" )
- lsl.title = translate("Syslog Log level")
- lsl.description = nil
- lsl.widget = "select"
- lsl.default = "WARNING"
- lsl:value ("DEBUG", translate("Debug"))
- lsl:value ("INFO", translate("Info") )
- lsl:value ("WARNING", translate("Warning") )
- lsl:value ("ERROR", translate("Error") )
- lsl:value ("CRITICAL", translate("Critical") )
- function lsl.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
- -- file_level ------------------------------------------------------------------
- local lfi = log:option( ListValue, "file_level" )
- lfi.title = translate("File Log level")
- lfi.description = nil
- lfi.widget = "select"
- lfi.default = "INFO"
- lfi:value ("DEBUG", translate("Debug"))
- lfi:value ("INFO", translate("Info") )
- lfi:value ("WARNING", translate("Warning") )
- lfi:value ("ERROR", translate("Error") )
- lfi:value ("CRITICAL", translate("Critical") )
- function lfi.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
- -- file_path -------------------------------------------------------------------
- local lfp = log:option( Value, "file_path" )
- lfp.title = translate("Log-file directory")
- lfp.description = translate("Directory where the rotating log-files are stored")
- .. [[<br /><a href="]]
- .. DISP.build_url("admin", "services", "radicale", "edit") .. [[/logger]]
- .. [[">]]
- .. 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)
- end
- end
- -- file_maxbytes ---------------------------------------------------------------
- local lmb = log:option( Value, "file_maxbytes" )
- lmb.title = translate("Log-file size")
- lmb.description = translate("Maximum size of each rotation log-file.")
- .. [[<br /><strong>]]
- .. translate("Setting this parameter to '0' will disable rotation of log-file.")
- .. [[</strong>]]
- lmb.default = "8196"
- lmb.rmempty = false
- 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 !")
- 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)
- end
- end
- -- file_backupcount ------------------------------------------------------------
- local lbc = log:option( Value, "file_backupcount" )
- lbc.title = translate("Log-backup Count")
- lbc.description = translate("Number of backup files of log to create.")
- .. [[<br /><strong>]]
- .. translate("Setting this parameter to '0' will disable rotation of log-file.")
- .. [[</strong>]]
- lbc.default = "1"
- lbc.rmempty = false
- 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 !")
- 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)
- end
- end
- -- cbi-section "Encoding" -- ###################################################
- local enc = m:section( NamedSection, "encoding", "setting" )
- enc.title = translate("Encoding")
- enc.description = translate("Change here the encoding Radicale will use instead of 'UTF-8' "
- .. "for responses to the client and/or to store data inside collections.")
- function enc.cfgvalue(self, section)
- 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
- -- request ---------------------------------------------------------------------
- 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
- -- 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
- -- cbi-section "Headers" -- ####################################################
- local hea = m:section( NamedSection, "headers", "setting" )
- hea.title = translate("Additional HTTP headers")
- hea.description = translate("Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources (e.g. fonts, JavaScript, etc.) "
- .. "on a web page to be requested from another domain outside the domain from which the resource originated.")
- function hea.cfgvalue(self, section)
- 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
- -- Access_Control_Allow_Origin -------------------------------------------------
- local heo = hea:option( DynamicList, "Access_Control_Allow_Origin" )
- heo.title = translate("Access-Control-Allow-Origin")
- heo.description = nil
- heo.default = "*"
- heo.optional = true
- -- 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
- -- 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
- -- 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
- return m
|