1 -- Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
2 -- Licensed under the Apache License, Version 2.0
4 local NXFS = require "nixio.fs"
5 local SYS = require "luci.sys"
6 local UTIL = require "luci.util"
7 local DTYP = require "luci.cbi.datatypes"
8 local CTRL = require "luci.controller.privoxy" -- this application's controller
10 -- Bootstrap theme needs 2 or 3 additional linefeeds for tab description for better optic
11 local LFLF = (CTRL.get_theme() == "Bootstrap") and [[<br /><br /><br />]] or [[]]
12 local HELP = [[<a href="http://www.privoxy.org/user-manual/config.html#%s" target="_blank">%s</a>]]
14 -- cbi-map -- ##################################################################
15 local m = Map("privoxy")
16 m.title = [[</a><a href="javascript:alert(']]
17 .. translate("Version Information")
18 .. [[\n\nluci-app-privoxy]]
19 .. [[\n\t]] .. translate("Version") .. [[:\t]]
20 .. SYS.exec([[opkg list-installed ]] .. [[luci-app-privoxy]] .. [[ | cut -d " " -f 3 ]])
21 .. [[\n\nprivoxy ]] .. translate("required") .. [[:]]
22 .. [[\n\t]] .. translate("Version") .. [[:\t]] .. CTRL.PRIVOXY_MIN .. [[ ]] .. translate("or higher")
23 .. [[\n\nprivoxy ]] .. translate("installed") .. [[:]]
24 .. [[\n\t]] .. translate("Version") .. [[:\t]]
25 .. SYS.exec([[opkg list-installed ]] .. [[privoxy]] .. [[ | cut -d " " -f 3 ]])
28 .. translate("Privoxy WEB proxy")
29 m.description = translate("Privoxy is a non-caching web proxy with advanced filtering "
30 .. "capabilities for enhancing privacy, modifying web page data and HTTP headers, "
31 .. "controlling access, and removing ads and other obnoxious Internet junk.")
33 .. translate("For help use link at the relevant option")
35 function m.commit_handler(self)
36 if self.changed then -- changes ?
37 os.execute("/etc/init.d/privoxy reload &") -- reload configuration
41 -- cbi-section -- ##############################################################
42 local ns = m:section( NamedSection, "privoxy", "privoxy")
45 translate("Local Set-up"),
46 translate("If you intend to operate Privoxy for more users than just yourself, "
47 .. "it might be a good idea to let them know how to reach you, what you block "
48 .. "and why you do that, your policies, etc.")
50 local function err_tab_local(title, msg)
51 return string.format(translate("Local Set-up") .. " - %s: %s", title, msg )
55 translate("Files and Directories"),
56 translate("Privoxy can (and normally does) use a number of other files "
57 .. "for additional configuration, help and logging. This section of "
58 .. "the configuration file tells Privoxy where to find those other files.")
60 local function err_tab_filter(title, msg)
61 return string.format(translate("Files and Directories") .. " - %s: %s", title, msg )
65 translate("Access Control"),
66 translate("This tab controls the security-relevant aspects of Privoxy's configuration.")
68 local function err_tab_access(title, msg)
69 return string.format(translate("Access Control") .. " - %s: %s", title, msg )
73 translate("Forwarding"),
74 translate("Configure here the routing of HTTP requests through a chain of multiple proxies. "
75 .. "Note that parent proxies can severely decrease your privacy level. "
76 .. "Also specified here are SOCKS proxies.")
80 translate("Miscellaneous"),
82 local function err_tab_misc(self, msg)
83 return string.format(translate("Miscellaneous") .. " - %s: %s", self.title_base, msg )
91 translate("Log File Viewer"),
94 -- tab: local -- ###############################################################
96 -- start/stop button -----------------------------------------------------------
97 local btn = ns:taboption("local", Button, "_startstop")
98 btn.title = translate("Start / Stop")
99 btn.description = translate("Start/Stop Privoxy WEB Proxy")
100 btn.template = "privoxy/detail_startstop"
101 function btn.cfgvalue(self, section)
102 local pid = CTRL.get_pid(true)
104 btn.inputtitle = "PID: " .. pid
105 btn.inputstyle = "reset"
108 btn.inputtitle = translate("Start")
109 btn.inputstyle = "apply"
115 -- enabled ---------------------------------------------------------------------
116 local ena = ns:taboption("local", Flag, "_enabled")
117 ena.title = translate("Enabled")
118 ena.description = translate("Enable/Disable autostart of Privoxy on system startup and interface events")
119 ena.orientation = "horizontal" -- put description under the checkbox
121 function ena.cfgvalue(self, section)
122 return (SYS.init.enabled("privoxy")) and "1" or "0"
124 function ena.validate(self, value)
125 error("Validate " .. value)
127 function ena.write(self, section, value)
128 --error("Write " .. value)
130 return SYS.init.enable("privoxy")
132 return SYS.init.disable("privoxy")
136 -- hostname --------------------------------------------------------------------
137 local hn = ns:taboption("local", Value, "hostname")
138 hn.title = string.format(HELP, "HOSTNAME", "Hostname" )
139 hn.description = translate("The hostname shown on the CGI pages.")
140 hn.placeholder = SYS.hostname()
144 -- user-manual -----------------------------------------------------------------
145 local um = ns:taboption("local", Value, "user_manual")
146 um.title = string.format(HELP, "USER-MANUAL", "User Manual" )
147 um.description = translate("Location of the Privoxy User Manual.")
148 um.placeholder = "http://www.privoxy.org/user-manual/"
152 -- admin-address ---------------------------------------------------------------
153 local aa = ns:taboption("local", Value, "admin_address")
154 aa.title_base = "Admin Email"
155 aa.title = string.format(HELP, "ADMIN-ADDRESS", aa.title_base )
156 aa.description = translate("An email address to reach the Privoxy administrator.")
157 aa.placeholder = "privoxy.admin@example.com"
160 function aa.validate(self, value)
161 if not value or #value == 0 then
164 if not (value:match("[A-Za-z0-9%.%%%+%-]+@[A-Za-z0-9%.%%%+%-]+%.%w%w%w?%w?")) then
165 return nil, err_tab_local(self.title_base, translate("Invalid email address") )
170 -- proxy-info-url --------------------------------------------------------------
171 local piu = ns:taboption("local", Value, "proxy_info_url")
172 piu.title = string.format(HELP, "PROXY-INFO-URL", "Proxy Info URL" )
173 piu.description = translate("A URL to documentation about the local Privoxy setup, configuration or policies.")
177 -- trust-info-url --------------------------------------------------------------
178 local tiu = ns:taboption("local", DynamicList, "trust_info_url")
179 tiu.title = string.format(HELP, "TRUST-INFO-URL", "Trust Info URLs" )
180 tiu.description = translate("A URL to be displayed in the error page that users will see if access to an untrusted page is denied.")
181 .. [[<br /><strong>]]
182 .. translate("The value of this option only matters if the experimental trust mechanism has been activated.")
187 -- tab: filter -- ##############################################################
189 -- logdir ----------------------------------------------------------------------
190 local ld = ns:taboption("filter", Value, "logdir")
191 ld.title_base = "Log Directory"
192 ld.title = string.format(HELP, "LOGDIR", ld.title_base )
193 ld.description = translate("The directory where all logging takes place (i.e. where the logfile is located).")
195 .. translate("No trailing '/', please.")
196 ld.default = "/var/log"
198 function ld.validate(self, value)
199 if not value or #value == 0 then
200 return nil, err_tab_filter(self.title_base, translate("Mandatory Input: No Directory given!") )
201 elseif not NXFS.access(value) then
202 return nil, err_tab_filter(self.title_base, translate("Directory does not exist!") )
208 -- logfile ---------------------------------------------------------------------
209 local lf = ns:taboption("filter", Value, "logfile")
210 lf.title_base = "Log File"
211 lf.title = string.format(HELP, "LOGFILE", lf.title_base )
212 lf.description = translate("The log file to use. File name, relative to log directory.")
213 lf.default = "privoxy.log"
215 function lf.validate(self, value)
216 if not value or #value == 0 then
217 return nil, err_tab_filter(self.title_base, translate("Mandatory Input: No File given!") )
223 -- confdir ---------------------------------------------------------------------
224 local cd = ns:taboption("filter", Value, "confdir")
225 cd.title_base = "Configuration Directory"
226 cd.title = string.format(HELP, "CONFDIR", cd.title_base )
227 cd.description = translate("The directory where the other configuration files are located.")
229 .. translate("No trailing '/', please.")
230 cd.default = "/etc/privoxy"
232 function cd.validate(self, value)
233 if not value or #value == 0 then
234 return nil, err_tab_filter(self.title_base, translate("Mandatory Input: No Directory given!") )
235 elseif not NXFS.access(value) then
236 return nil, err_tab_filter(self.title_base, translate("Directory does not exist!") )
242 -- templdir --------------------------------------------------------------------
243 local td = ns:taboption("filter", Value, "templdir")
244 td.title_base = "Template Directory"
245 td.title = string.format(HELP, "TEMPLDIR", td.title_base )
246 td.description = translate("An alternative directory where the templates are loaded from.")
248 .. translate("No trailing '/', please.")
249 td.placeholder = "/etc/privoxy/templates"
251 function td.validate(self, value)
252 if not NXFS.access(value) then
253 return nil, err_tab_filter(self.title_base, translate("Directory does not exist!") )
259 -- actionsfile -----------------------------------------------------------------
260 local af = ns:taboption("filter", DynamicList, "actionsfile")
261 af.title_base = "Action Files"
262 af.title = string.format(HELP, "ACTIONSFILE", af.title_base)
263 af.description = translate("The actions file(s) to use. Multiple actionsfile lines are permitted, and are in fact recommended!")
264 .. [[<br /><strong>match-all.action := </strong>]]
265 .. translate("Actions that are applied to all sites and maybe overruled later on.")
266 .. [[<br /><strong>default.action := </strong>]]
267 .. translate("Main actions file")
268 .. [[<br /><strong>user.action := </strong>]]
269 .. translate("User customizations")
271 function af.validate(self, value)
272 if not value or #value == 0 then
273 return nil, err_tab_access(self.title_base, translate("Mandatory Input: No files given!") )
275 local confdir = cd:formvalue(ns.section)
278 if type(value) == "table" then
280 for _, x in ipairs(value) do
282 if not NXFS.access(confdir .."/".. x) then
285 break -- break/leave for on error
290 if not NXFS.access(confdir .."/".. value) then
296 return nil, string.format(err_tab_filter(self.title_base, translate("File '%s' not found inside Configuration Directory") ), file)
301 -- filterfile ------------------------------------------------------------------
302 local ff = ns:taboption("filter", DynamicList, "filterfile")
303 ff.title_base = "Filter files"
304 ff.title = string.format(HELP, "FILTERFILE", ff.title_base )
305 ff.description = translate("The filter files contain content modification rules that use regular expressions.")
307 function ff.validate(self, value)
308 if not value or #value == 0 then
309 return nil, err_tab_access(self.title_base, translate("Mandatory Input: No files given!") )
311 local confdir = cd:formvalue(ns.section)
314 if type(value) == "table" then
316 for _, x in ipairs(value) do
318 if not NXFS.access(confdir .."/".. x) then
321 break -- break/leave for on error
326 if not NXFS.access(confdir .."/".. value) then
332 return nil, string.format(err_tab_filter(self.title_base, translate("File '%s' not found inside Configuration Directory") ), file )
337 -- trustfile -------------------------------------------------------------------
338 local tf = ns:taboption("filter", Value, "trustfile")
339 tf.title_base = "Trust file"
340 tf.title = string.format(HELP, "TRUSTFILE", tf.title_base )
341 tf.description = translate("The trust mechanism is an experimental feature for building white-lists "
342 .."and should be used with care.")
343 .. [[<br /><strong>]]
344 .. translate("It is NOT recommended for the casual user.")
346 tf.placeholder = "sites.trust"
348 function tf.validate(self, value)
349 local confdir = cd:formvalue(ns.section)
352 if type(value) == "table" then
354 for _, x in ipairs(value) do
356 if not NCFS.access(confdir .."/".. x) then
359 break -- break/leave for on error
364 if not NXFS.access(confdir .."/".. value) then
370 return nil, string.format(err_tab_filter(self.title_base, translate("File '%s' not found inside Configuration Directory") ), file )
375 -- tab: access -- ##############################################################
377 -- listen-address --------------------------------------------------------------
378 local la = ns:taboption("access", DynamicList, "listen_address")
379 la.title_base = "Listen addresses"
380 la.title = string.format(HELP, "LISTEN-ADDRESS", la.title_base )
381 la.description = translate("The address and TCP port on which Privoxy will listen for client requests.")
383 .. translate("Syntax: ")
384 .. "IPv4:Port / [IPv6]:Port / Host:Port"
385 la.default = "127.0.0.1:8118"
387 function la.validate(self, value)
388 if not value or #value == 0 then
389 return nil, err_tab_access(self.title_base, translate("Mandatory Input: No Data given!") )
392 local function check_value(v)
393 local _ret = UTIL.split(v, "]:")
395 if _ret[2] then -- ip6 with port
396 _ip = string.gsub(_ret[1], "%[", "") -- remove "[" at beginning
397 if not DTYP.ip6addr(_ip) then
398 return translate("Mandatory Input: No valid IPv6 address given!")
399 elseif not DTYP.port(_ret[2]) then
400 return translate("Mandatory Input: No valid Port given!")
405 _ret = UTIL.split(v, ":")
407 return translate("Mandatory Input: No Port given!")
409 if #_ret[1] > 0 and not DTYP.host(_ret[1]) then -- :8118 is valid address
410 return translate("Mandatory Input: No valid IPv4 address or host given!")
411 elseif not DTYP.port(_ret[2]) then
412 return translate("Mandatory Input: No valid Port given!")
420 if type(value) == "table" then
422 for _, x in ipairs(value) do
432 err = check_value(value)
436 return nil, string.format(err_tab_access(self.title_base, err .. " - %s"), entry )
441 -- permit-access ---------------------------------------------------------------
442 local pa = ns:taboption("access", DynamicList, "permit_access")
443 pa.title = string.format(HELP, "ACLS", "Permit access" )
444 pa.description = translate("Who can access what.")
445 .. [[<br /><strong>]]
446 .. translate("Please read Privoxy manual for details!")
450 -- deny-access -----------------------------------------------------------------
451 local da = ns:taboption("access", DynamicList, "deny_access")
452 da.title = string.format(HELP, "ACLS", "Deny Access" )
453 da.description = translate("Who can access what.")
454 .. [[<br /><strong>]]
455 .. translate("Please read Privoxy manual for details!")
459 -- buffer-limit ----------------------------------------------------------------
460 local bl = ns:taboption("access", Value, "buffer_limit")
461 bl.title_base = "Buffer Limit"
462 bl.title = string.format(HELP, "BUFFER-LIMIT", bl.title_base )
463 bl.description = translate("Maximum size (in KB) of the buffer for content filtering.")
465 .. translate("Value range 1 to 4096, no entry defaults to 4096")
468 function bl.validate(self, value)
469 local v = tonumber(value)
471 return nil, err_tab_access(self.title_base, translate("Value is not a number") )
472 elseif v < 1 or v > 4096 then
473 return nil, err_tab_access(self.title_base, translate("Value not between 1 and 4096") )
474 elseif v == self.default then
475 return "" -- dont need to save default
480 -- toggle ----------------------------------------------------------------------
481 local tgl = ns:taboption("access", Flag, "toggle")
482 tgl.title = string.format(HELP, "TOGGLE", "Toggle Status" )
483 tgl.description = translate("Enable/Disable filtering when Privoxy starts.")
485 .. translate("Disabled == Transparent Proxy Mode")
486 tgl.orientation = "horizontal"
489 function tgl.parse(self, section)
490 CTRL.flag_parse(self, section)
493 -- enable-remote-toggle --------------------------------------------------------
494 local ert = ns:taboption("access", Flag, "enable_remote_toggle")
495 ert.title = string.format(HELP, "ENABLE-REMOTE-TOGGLE", "Enable remote toggle" )
496 ert.description = translate("Whether or not the web-based toggle feature may be used.")
497 ert.orientation = "horizontal"
499 function ert.parse(self, section)
500 CTRL.flag_parse(self, section)
503 -- enable-remote-http-toggle ---------------------------------------------------
504 local eht = ns:taboption("access", Flag, "enable_remote_http_toggle")
505 eht.title = string.format(HELP, "ENABLE-REMOTE-HTTP-TOGGLE", "Enable remote toggle via HTTP" )
506 eht.description = translate("Whether or not Privoxy recognizes special HTTP headers to change toggle state.")
507 .. [[<br /><strong>]]
508 .. translate("This option will be removed in future releases as it has been obsoleted by the more general header taggers.")
510 eht.orientation = "horizontal"
512 function eht.parse(self, section)
513 CTRL.flag_parse(self, section)
516 -- enable-edit-actions ---------------------------------------------------------
517 local eea = ns:taboption("access", Flag, "enable_edit_actions")
518 eea.title = string.format(HELP, "ENABLE-EDIT-ACTIONS", "Enable action file editor" )
519 eea.description = translate("Whether or not the web-based actions file editor may be used.")
520 eea.orientation = "horizontal"
522 function eea.parse(self, section)
523 CTRL.flag_parse(self, section)
526 -- enforce-blocks --------------------------------------------------------------
527 local eb = ns:taboption("access", Flag, "enforce_blocks")
528 eb.title = string.format(HELP, "ENFORCE-BLOCKS", "Enforce page blocking" )
529 eb.description = translate("If enabled, Privoxy hides the 'go there anyway' link. "
530 .. "The user obviously should not be able to bypass any blocks.")
531 eb.orientation = "horizontal"
533 function eb.parse(self, section)
534 CTRL.flag_parse(self, section)
537 -- tab: forward -- #############################################################
539 -- enable-proxy-authentication-forwarding --------------------------------------
540 local paf = ns:taboption("forward", Flag, "enable_proxy_authentication_forwarding")
541 paf.title = string.format(HELP, "ENABLE-PROXY-AUTHENTICATION-FORWARDING",
542 translate("Enable proxy authentication forwarding") )
543 paf.description = translate("Whether or not proxy authentication through Privoxy should work.")
544 .. [[<br /><strong>]]
545 .. translate("Enabling this option is NOT recommended if there is no parent proxy that requires authentication!")
547 --paf.orientation = "horizontal"
549 function paf.parse(self, section)
550 CTRL.flag_parse(self, section)
553 -- forward ---------------------------------------------------------------------
554 local fwd = ns:taboption("forward", DynamicList, "forward")
555 fwd.title = string.format(HELP, "FORWARD", "Forward HTTP" )
556 fwd.description = translate("To which parent HTTP proxy specific requests should be routed.")
558 .. translate("Syntax: target_pattern http_parent[:port]")
561 -- forward-socks4 --------------------------------------------------------------
562 local fs4 = ns:taboption("forward", DynamicList, "forward_socks4")
563 fs4.title = string.format(HELP, "SOCKS", "Forward SOCKS 4" )
564 fs4.description = translate("Through which SOCKS proxy (and optionally to which parent HTTP proxy) specific requests should be routed.")
566 .. translate("Syntax: target_pattern socks_proxy[:port] http_parent[:port]")
569 -- forward-socks4a -------------------------------------------------------------
570 local f4a = ns:taboption("forward", DynamicList, "forward_socks4a")
571 f4a.title = string.format(HELP, "SOCKS", "Forward SOCKS 4A" )
572 f4a.description = fs4.description
575 -- forward-socks5 --------------------------------------------------------------
576 local fs5 = ns:taboption("forward", DynamicList, "forward_socks5")
577 fs5.title = string.format(HELP, "SOCKS", "Forward SOCKS 5" )
578 fs5.description = fs4.description
581 -- forward-socks5t -------------------------------------------------------------
582 local f5t = ns:taboption("forward", DynamicList, "forward_socks5t")
583 f5t.title = string.format(HELP, "SOCKS", "Forward SOCKS 5t" )
584 f5t.description = fs4.description
587 -- tab: misc -- ################################################################
589 -- accept-intercepted-requests -------------------------------------------------
590 local air = ns:taboption("misc", Flag, "accept_intercepted_requests")
591 air.title = string.format(HELP, "ACCEPT-INTERCEPTED-REQUESTS", "Accept intercepted requests" )
592 air.description = translate("Whether intercepted requests should be treated as valid.")
593 air.orientation = "horizontal"
595 function air.parse(self, section)
596 CTRL.flag_parse(self, section)
599 -- allow-cgi-request-crunching -------------------------------------------------
600 local crc = ns:taboption("misc", Flag, "allow_cgi_request_crunching")
601 crc.title = string.format(HELP, "ALLOW-CGI-REQUEST-CRUNCHING", "Allow CGI request crunching" )
602 crc.description = translate("Whether requests to Privoxy's CGI pages can be blocked or redirected.")
603 crc.orientation = "horizontal"
605 function crc.parse(self, section)
606 CTRL.flag_parse(self, section)
609 -- split-large-forms -----------------------------------------------------------
610 local slf = ns:taboption("misc", Flag, "split_large_forms")
611 slf.title = string.format(HELP, "SPLIT-LARGE-FORMS", "Split large forms" )
612 slf.description = translate("Whether the CGI interface should stay compatible with broken HTTP clients.")
613 slf.orientation = "horizontal"
615 function slf.parse(self, section)
616 CTRL.flag_parse(self, section)
619 -- keep-alive-timeout ----------------------------------------------------------
620 local kat = ns:taboption("misc", Value, "keep_alive_timeout")
621 kat.title_base = "Keep-alive timeout"
622 kat.title = string.format(HELP, "KEEP-ALIVE-TIMEOUT", kat.title_base)
623 kat.description = translate("Number of seconds after which an open connection will no longer be reused.")
625 function kat.validate(self, value)
626 local v = tonumber(value)
628 return nil, err_tab_misc(self.title_base, translate("Value is not a number") )
630 return nil, err_tab_misc(self.title_base, translate("Value not greater 0 or empty") )
635 -- tolerate-pipelining ---------------------------------------------------------
636 local tp = ns:taboption("misc", Flag, "tolerate_pipelining")
637 tp.title = string.format(HELP, "TOLERATE-PIPELINING", "Tolerate pipelining" )
638 tp.description = translate("Whether or not pipelined requests should be served.")
639 tp.orientation = "horizontal"
641 function tp.parse(self, section)
642 CTRL.flag_parse(self, section)
645 -- default-server-timeout ------------------------------------------------------
646 local dst = ns:taboption("misc", Value, "default_server_timeout")
647 dst.title_base = "Default server timeout"
648 dst.title = string.format(HELP, "DEFAULT-SERVER-TIMEOUT", dst.title_base)
649 dst.description = translate("Assumed server-side keep-alive timeout (in seconds) if not specified by the server.")
651 function dst.validate(self, value)
652 local v = tonumber(value)
654 return nil, err_tab_misc(self.title_base, translate("Value is not a number") )
656 return nil, err_tab_misc(self.title_base, translate("Value not greater 0 or empty") )
661 -- connection-sharing ----------------------------------------------------------
662 local cs = ns:taboption("misc", Flag, "connection_sharing")
663 cs.title = string.format(HELP, "CONNECTION-SHARING", "Connection sharing" )
664 cs.description = translate("Whether or not outgoing connections that have been kept alive should be shared between different incoming connections.")
665 cs.orientation = "horizontal"
667 function cs.parse(self, section)
668 CTRL.flag_parse(self, section)
671 -- socket-timeout --------------------------------------------------------------
672 local st = ns:taboption("misc", Value, "socket_timeout")
673 st.title_base = "Socket timeout"
674 st.title = string.format(HELP, "SOCKET-TIMEOUT", st.title_base )
675 st.description = translate("Number of seconds after which a socket times out if no data is received.")
678 function st.validate(self, value)
679 local v = tonumber(value)
681 return nil, err_tab_misc(self.title_base, translate("Value is not a number") )
683 return nil, err_tab_misc(self.title_base, translate("Value not greater 0 or empty") )
684 elseif v == self.default then
685 return "" -- dont need to save default
690 -- max-client-connections ------------------------------------------------------
691 local mcc = ns:taboption("misc", Value, "max_client_connections")
692 mcc.title_base = "Max. client connections"
693 mcc.title = string.format(HELP, "MAX-CLIENT-CONNECTIONS", mcc.title_base )
694 mcc.description = translate("Maximum number of client connections that will be served.")
697 function mcc.validate(self, value)
698 local v = tonumber(value)
700 return nil, err_tab_misc(self.title_base, translate("Value is not a number") )
702 return nil, err_tab_misc(self.title_base, translate("Value not greater 0 or empty") )
703 elseif v == self.default then
704 return "" -- dont need to save default
709 -- handle-as-empty-doc-returns-ok ----------------------------------------------
710 local her = ns:taboption("misc", Flag, "handle_as_empty_doc_returns_ok")
711 her.title = string.format(HELP, "HANDLE-AS-EMPTY-DOC-RETURNS-OK", "Handle as empty doc returns ok" )
712 her.description = translate("The status code Privoxy returns for pages blocked with +handle-as-empty-document.")
713 her.orientation = "horizontal"
715 function her.parse(self, section)
716 CTRL.flag_parse(self, section)
719 -- enable-compression ----------------------------------------------------------
720 local ec = ns:taboption("misc", Flag, "enable_compression")
721 ec.title = string.format(HELP, "ENABLE-COMPRESSION", "Enable compression" )
722 ec.description = translate("Whether or not buffered content is compressed before delivery.")
723 ec.orientation = "horizontal"
725 function ec.parse(self, section)
726 CTRL.flag_parse(self, section)
729 -- compression-level -----------------------------------------------------------
730 local cl = ns:taboption("misc", Value, "compression_level")
731 cl.title_base = "Compression level"
732 cl.title = string.format(HELP, "COMPRESSION-LEVEL", cl.title_base )
733 cl.description = translate("The compression level that is passed to the zlib library when compressing buffered content.")
736 function cl.validate(self, value)
737 local v = tonumber(value)
739 return nil, err_tab_misc(self.title_base, translate("Value is not a number") )
740 elseif v < 0 or v > 9 then
741 return nil, err_tab_misc(self.title_base, translate("Value not between 0 and 9") )
742 elseif v == self.default then
743 return "" -- don't need to save default
748 -- client-header-order ---------------------------------------------------------
749 local cho = ns:taboption("misc", Value, "client_header_order")
750 cho.title = string.format(HELP, "CLIENT-HEADER-ORDER", "Client header order" )
751 cho.description = translate("The order in which client headers are sorted before forwarding them.")
753 .. translate("Syntax: Client header names delimited by spaces.")
756 -- "debug"-tab definition -- ###################################################
758 -- single-threaded -------------------------------------------------------------
759 local st = ns:taboption("debug", Flag, "single_threaded")
760 st.title = string.format(HELP, "SINGLE-THREADED", "Single Threaded" )
761 st.description = translate("Whether to run only one server thread.")
762 .. [[<br /><strong>]]
763 .. translate("This option is only there for debugging purposes. It will drastically reduce performance.")
766 function st.parse(self, section)
767 CTRL.flag_parse(self, section)
770 -- debug -----------------------------------------------------------------------
771 local d1 = ns:taboption("debug", Flag, "debug_1")
772 d1.title = string.format(HELP, "DEBUG", "Debug 1" )
773 d1.description = translate("Log the destination for each request Privoxy let through. See also 'Debug 1024'.")
775 function d1.parse(self, section)
776 CTRL.flag_parse(self, section)
779 -- debug -----------------------------------------------------------------------
780 local d2 = ns:taboption("debug", Flag, "debug_2")
781 d2.title = string.format(HELP, "DEBUG", "Debug 2" )
782 d2.description = translate("Show each connection status")
784 function d2.parse(self, section)
785 CTRL.flag_parse(self, section)
788 -- debug -----------------------------------------------------------------------
789 local d3 = ns:taboption("debug", Flag, "debug_4")
790 d3.title = string.format(HELP, "DEBUG", "Debug 4" )
791 d3.description = translate("Show I/O status")
793 function d3.parse(self, section)
794 CTRL.flag_parse(self, section)
797 -- debug -----------------------------------------------------------------------
798 local d4 = ns:taboption("debug", Flag, "debug_8")
799 d4.title = string.format(HELP, "DEBUG", "Debug 8" )
800 d4.description = translate("Show header parsing")
802 function d4.parse(self, section)
803 CTRL.flag_parse(self, section)
806 -- debug -----------------------------------------------------------------------
807 local d5 = ns:taboption("debug", Flag, "debug_16")
808 d5.title = string.format(HELP, "DEBUG", "Debug 16" )
809 d5.description = translate("Log all data written to the network")
811 function d5.parse(self, section)
812 CTRL.flag_parse(self, section)
815 -- debug -----------------------------------------------------------------------
816 local d6 = ns:taboption("debug", Flag, "debug_32")
817 d6.title = string.format(HELP, "DEBUG", "Debug 32" )
818 d6.description = translate("Debug force feature")
820 function d6.parse(self, section)
821 CTRL.flag_parse(self, section)
824 -- debug -----------------------------------------------------------------------
825 local d7 = ns:taboption("debug", Flag, "debug_64")
826 d7.title = string.format(HELP, "DEBUG", "Debug 64" )
827 d7.description = translate("Debug regular expression filters")
829 function d7.parse(self, section)
830 CTRL.flag_parse(self, section)
833 -- debug -----------------------------------------------------------------------
834 local d8 = ns:taboption("debug", Flag, "debug_128")
835 d8.title = string.format(HELP, "DEBUG", "Debug 128" )
836 d8.description = translate("Debug redirects")
838 function d8.parse(self, section)
839 CTRL.flag_parse(self, section)
842 -- debug -----------------------------------------------------------------------
843 local d9 = ns:taboption("debug", Flag, "debug_256")
844 d9.title = string.format(HELP, "DEBUG", "Debug 256" )
845 d9.description = translate("Debug GIF de-animation")
847 function d9.parse(self, section)
848 CTRL.flag_parse(self, section)
851 -- debug -----------------------------------------------------------------------
852 local d10 = ns:taboption("debug", Flag, "debug_512")
853 d10.title = string.format(HELP, "DEBUG", "Debug 512" )
854 d10.description = translate("Common Log Format")
856 function d10.parse(self, section)
857 CTRL.flag_parse(self, section)
860 -- debug -----------------------------------------------------------------------
861 local d11 = ns:taboption("debug", Flag, "debug_1024")
862 d11.title = string.format(HELP, "DEBUG", "Debug 1024" )
863 d11.description = translate("Log the destination for requests Privoxy didn't let through, and the reason why.")
865 function d11.parse(self, section)
866 CTRL.flag_parse(self, section)
869 -- debug -----------------------------------------------------------------------
870 local d12 = ns:taboption("debug", Flag, "debug_2048")
871 d12.title = string.format(HELP, "DEBUG", "Debug 2048" )
872 d12.description = translate("CGI user interface")
874 function d12.parse(self, section)
875 CTRL.flag_parse(self, section)
878 -- debug -----------------------------------------------------------------------
879 local d13 = ns:taboption("debug", Flag, "debug_4096")
880 d13.title = string.format(HELP, "DEBUG", "Debug 4096" )
881 d13.description = translate("Startup banner and warnings.")
883 function d13.parse(self, section)
884 CTRL.flag_parse(self, section)
887 -- debug -----------------------------------------------------------------------
888 local d14 = ns:taboption("debug", Flag, "debug_8192")
889 d14.title = string.format(HELP, "DEBUG", "Debug 8192" )
890 d14.description = translate("Non-fatal errors - *we highly recommended enabling this*")
892 function d14.parse(self, section)
893 CTRL.flag_parse(self, section)
896 -- debug -----------------------------------------------------------------------
897 local d15 = ns:taboption("debug", Flag, "debug_32768")
898 d15.title = string.format(HELP, "DEBUG", "Debug 32768" )
899 d15.description = translate("Log all data read from the network")
901 function d15.parse(self, section)
902 CTRL.flag_parse(self, section)
905 -- debug -----------------------------------------------------------------------
906 local d16 = ns:taboption("debug", Flag, "debug_65536")
907 d16.title = string.format(HELP, "DEBUG", "Debug 65536" )
908 d16.description = translate("Log the applying actions")
910 function d16.parse(self, section)
911 CTRL.flag_parse(self, section)
914 -- tab: logview -- #############################################################
916 local lv = ns:taboption("logview", DummyValue, "_logview")
917 lv.template = "privoxy/detail_logview"
918 lv.inputtitle = translate("Read / Reread log file")
920 function lv.cfgvalue(self, section)
921 local lfile=self.map:get(ns.section, "logdir") .. "/" .. self.map:get(ns.section, "logfile")
922 if NXFS.access(lfile) then
923 return lfile .. "\n" .. translate("Please press [Read] button")
925 return lfile .. "\n" .. translate("File not found or empty")