diff options
Diffstat (limited to 'config/haproxy-devel/pkg')
-rw-r--r-- | config/haproxy-devel/pkg/haproxy.inc | 1087 | ||||
-rw-r--r-- | config/haproxy-devel/pkg/haproxy_htmllist.inc | 488 | ||||
-rw-r--r-- | config/haproxy-devel/pkg/haproxy_upgrade_config.inc | 73 | ||||
-rw-r--r-- | config/haproxy-devel/pkg/haproxy_utils.inc | 30 |
4 files changed, 1212 insertions, 466 deletions
diff --git a/config/haproxy-devel/pkg/haproxy.inc b/config/haproxy-devel/pkg/haproxy.inc index 1bc62cb9..7a07e9a7 100644 --- a/config/haproxy-devel/pkg/haproxy.inc +++ b/config/haproxy-devel/pkg/haproxy.inc @@ -37,7 +37,7 @@ require_once("haproxy_utils.inc"); require_once("haproxy_xmlrpcsyncclient.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; - +#region Global haproxy array item definitions.. global $a_frontendmode; $a_frontendmode = array(); $a_frontendmode['http'] = array('name' => "http / https(offloading)", 'shortname' => "http/https"); @@ -77,7 +77,10 @@ $a_acltypes["ssl_c_ca_commonname"] = array('name' => 'SSL Client issued by CA co $a_acltypes["source_ip"] = array('name' => 'Source IP matches IP or Alias:', 'mode' => '', 'syntax' => 'src %1$s'); $a_acltypes["backendservercount"] = array('name' => 'Minimum count usable servers:', - 'mode' => '', 'syntax' => 'nbsrv(%2$s) ge %1$d', 'parameters' => 'value,backendname'); + 'mode' => '', 'syntax' => 'nbsrv({backend}) ge %1$d', 'parameters' => 'value,backendname', + 'fields' => array( + 'backend' => array('name'=>"backend",'columnheader'=>"Backend",'type'=>"select",'size'=>"50",'mask'=>'backend') + )); $a_acltypes["traffic_is_http"] = array('name' => 'Traffic is http (no value needed):', 'inspect-delay' => '5', 'mode' => 'tcp', 'syntax' => 'req.proto_http', 'advancedoptions' => "tcp-request content accept if { req.proto_http }"); $a_acltypes["traffic_is_ssl"] = array('name' => 'Traffic is ssl (no value needed):', 'inspect-delay' => '5', @@ -224,7 +227,140 @@ $a_sysloglevel['notice'] = array('name' => "Notice"); $a_sysloglevel['info'] = array('name' => "Informational"); $a_sysloglevel['debug'] = array('name' => "Debugging"); -if(!function_exists('group_ports')){ +global $a_filestype; +$a_filestype = array(); +$a_filestype[''] = array('name' => "Errorfile"); +$a_filestype['luascript'] = array('name' => "Lua script"); +$a_filestype['writetodisk'] = array('name' => "Write to disk"); + +global $a_action; +$a_action = array(); +// +$a_action["use_backend"] = array('name' => "Use Backend", 'mode' => '', 'syntax' => 'use_backend {backend}', + 'fields' => array( + 'backend' => array('name'=>"backend",'columnheader'=>"Backend",'type'=>"select",'size'=>"50",'mask'=>'backend') + )); +// +$a_action["custom"] = array('name' => "Custom", 'mode' => '', + 'fields' => array( + array('name'=>"customaction",'columnheader'=>"Custom action",'type'=>"textbox",'size'=>"50",'mask'=>'freetext') + )); +// +$a_action["http-request_allow"] = array('name' => "http-request allow", 'mode'=> 'http', 'syntax' => 'http-request allow'); +$a_action["http-request_deny"] = array('name' => "http-request deny", 'mode'=> 'http', 'syntax' => 'http-request deny'); +$a_action["http-request_tarpit"] = array('name' => "http-request tarpit", 'mode'=> 'http', 'syntax' => 'http-request tarpit'); +$a_action["http-request_auth"] = array('name' => "http-request auth", 'mode'=> 'http', 'syntax' => 'http-request auth {realm}', + 'fields' => array( + array('name'=>"realm",'columnheader'=>"Realm",'type'=>"textbox",'size'=>"50",'mask'=>'freetext') + ) +); +$a_action["http-request_redirect"] = array('name' => "http-request redirect", 'mode'=> 'http', 'syntax' => 'http-request redirect {rule}', + 'fields' => array( + array('name'=>"rule",'columnheader'=>"Rule",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + ) +); +if (haproxy_version() >= '1.6') { + $a_action["http-request_lua"] = array('name' => "http-request lua action", 'mode'=> 'http', 'syntax' => 'http-request lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); + $a_action["http-request_use-service"] = array('name' => "http-request lua service", 'mode'=> 'http', 'syntax' => 'http-request use-service lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +$a_action["http-request_add-header"] = array('name' => "http-request header add", 'mode'=> 'http', 'syntax' => 'http-request add-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-request_set-header"] = array('name' => "http-request header set", 'mode'=> 'http', 'syntax' => 'http-request set-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-request_del-header"] = array('name' => "http-request header delete", 'mode'=> 'http', 'syntax' => 'http-request del-header {name}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername') + )); +$a_action["http-request_replace-header"] = array('name' => "http-request header replace", 'mode'=> 'http', 'syntax' => 'http-request replace-header {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +$a_action["http-request_replace-value"] = array('name' => "http-request header replace value", 'mode'=> 'http', 'syntax' => 'http-request replace-value {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +// +$a_action["http-response_allow"] = array('name' => "http-response allow", 'mode'=> 'http', 'syntax' => 'http-response allow'); +$a_action["http-response_deny"] = array('name' => "http-response deny", 'mode'=> 'http', 'syntax' => 'http-response deny'); +if (haproxy_version() >= '1.6') { + $a_action["http-response_lua"] = array('name' => "http-response lua script", 'mode'=> 'http', 'syntax' => 'http-response lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +$a_action["http-response_add-header"] = array('name' => "http-response header add", 'mode'=> 'http', 'syntax' => 'http-response add-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-response_set-header"] = array('name' => "http-response header set", 'mode'=> 'http', 'syntax' => 'http-response set-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-response_del-header"] = array('name' => "http-response header delete", 'mode'=> 'http', 'syntax' => 'http-response del-header {name}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername') + )); +$a_action["http-response_replace-header"] = array('name' => "http-response header replace", 'mode'=> 'http', 'syntax' => 'http-response replace-header {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +$a_action["http-response_replace-value"] = array('name' => "http-response header replace value", 'mode'=> 'http', 'syntax' => 'http-response replace-value {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +// +$a_action["tcp-request_connection_accept"] = array('name' => "tcp-request connection accept", 'mode'=> '', 'syntax' => 'tcp-request connection accept'); +$a_action["tcp-request_connection_reject"] = array('name' => "tcp-request connection reject", 'mode'=> '', 'syntax' => 'tcp-request connection reject'); +// +$a_action["tcp-request_content_accept"] = array('name' => "tcp-request content accept", 'mode'=> '', 'syntax' => 'tcp-request content accept'); +$a_action["tcp-request_content_reject"] = array('name' => "tcp-request content reject", 'mode'=> '', 'syntax' => 'tcp-request content reject'); +if (haproxy_version() >= '1.6') { + $a_action["tcp-request_content_lua"] = array('name' => "tcp-request content lua script", 'mode'=> '', 'syntax' => 'tcp-request content lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); + $a_action["tcp-request_content_use-service"] = array('name' => "tcp-request content use-service", 'mode'=> '', 'syntax' => 'tcp-request content use-service lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +// +$a_action["tcp-response_content_accept"] = array('name' => "tcp-response content accept", 'mode'=> '', 'syntax' => 'tcp-response content accept'); +$a_action["tcp-response_content_close"] = array('name' => "tcp-response content close", 'mode'=> '', 'syntax' => 'tcp-response content close'); +$a_action["tcp-response_content_reject"] = array('name' => "tcp-response content reject", 'mode'=> '', 'syntax' => 'tcp-response content reject'); +if (haproxy_version() >= '1.6') { + $a_action["tcp-response_content_lua"] = array('name' => "tcp-response content lua script", 'mode'=> '', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} + +#end + + +if (!function_exists('group_ports')) { // function group_ports() is present in pfSense 2.2 in util.inc /* create ranges of sequential port numbers (200:215) and remove duplicates */ function group_ports($ports) { @@ -243,7 +379,7 @@ function group_ports($ports) { for ($i = $begin; $i <= $end; $i++) if (!in_array($i, $uniq)) $uniq[] = $i; - } else if (is_port($port)) { + } elseif (is_port($port)) { if (!in_array($port, $uniq)) $uniq[] = $port; } @@ -276,7 +412,7 @@ function group_ports($ports) { } global $haproxy_version; -function haproxy_verion() { +function haproxy_version() { global $haproxy_version; if (empty($haproxy_version)) { $haproxy_version = shell_exec("haproxy -v | head -n 1 | awk '{ print $3 }'"); @@ -284,6 +420,89 @@ function haproxy_verion() { return $haproxy_version; } +function haproxy_css() { + if (!file_exists("/usr/local/www/bootstrap")) + return; + // quick fix to look a bit decent on bootstrapped pfSense.. + echo <<<EOD +<style type="text/css"> +.listtopic { + border-right: 1px solid #999999; + font-size: 11px; + background-color: #990000; + padding-right: 16px; + padding-left: 6px; + color: #FFFFFF; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; +} +.tabcont { + background-color: #DDDDDD; + padding-right: 12px; + padding-left: 12px; + padding-top: 12px; + padding-bottom: 12px; +} +.vtable { + border-bottom: 1px solid #999999; +} +.vncell { + background-color: #DDDDDD; + padding-right: 20px; + padding-left: 8px; + border-bottom: 1px solid #999999; +} +.vncellreq { + background-color: #DDDDDD; + padding-right: 20px; + padding-left: 8px; + font-weight: bold; + border-bottom: 1px solid #999999; +} +.listhdrr { + background-color: #BBBBBB; + padding-right: 6px; + padding-left: 6px; + font-weight: bold; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + font-size: 11px; + padding-top: 5px; + padding-bottom: 5px; +} +.listr { + background-color: #FFFFFF; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + font-size: 11px; + padding-right: 6px; + padding-left: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +.listlr { + background-color: #FFFFFF; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + border-left: 1px solid #999999; + font-size: 11px; + padding-right: 6px; + padding-left: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +.tabcont { + background-color: #DDDDDD; + padding-right: 12px; + padding-left: 12px; + padding-top: 12px; + padding-bottom: 12px; +} +</style> +EOD; +} + function haproxy_portoralias_to_list($port_or_alias) { // input: a port or aliasname: 80 https MyPortAlias // returns: a array of ports and portranges 80 443 8000:8010 @@ -298,7 +517,7 @@ function haproxy_portoralias_to_list($port_or_alias) { $portresult = array_merge($portresult, $portresults); } return $portresult; - } else if (is_portrange($port_or_alias)) { + } elseif (is_portrange($port_or_alias)) { return (array)$port_or_alias; } else { $ports = explode(",", $port_or_alias); @@ -420,7 +639,7 @@ haproxy_start () { require_once("haproxy.inc"); haproxy_configure(); ?> -ENDOFF +ENDOFF } haproxy_check () { @@ -504,10 +723,11 @@ function haproxy_find_backend($backendname) { function haproxy_find_acl($name) { global $a_acltypes; - if($a_acltypes) { + if ($a_acltypes) { foreach ($a_acltypes as $key => $acl) { - if ($key == $name) + if ($key == $name) { return $acl; + } } } } @@ -517,25 +737,29 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { $frontend = $backendsettings['frontend']; $ipversion = $backendsettings['ipversion']; $a_global = &$config['installedpackages']['haproxy']; - $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['items']; + $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['item']; + $a_resolvers = $config['installedpackages']['haproxy']['dns_resolvers']['item']; - if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') + if (!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') { return; + } global $a_checktypes, $a_cookiemode, $a_files_cache, $a_error; - + + $server_options = ""; $a_servers = &$pool['ha_servers']['item']; $frontendtype = $frontend['type']; fwrite ($fd, "backend " . $name . "\n"); // https is an alias for tcp for clarity purposes - if($frontendtype == "https") { + if ($frontendtype == "https") { $backend_mode = "tcp"; } else { $backend_mode = $frontendtype; } fwrite ($fd, "\tmode\t\t\t" . $backend_mode . "\n"); - if (haproxy_verion() >= '1.6') { + $use_haproxyresolvers = false; + if (haproxy_version() >= '1.6') { $use_mailers = is_array($a_mailers) && count($a_mailers) > 0; if ($use_mailers) { fwrite ($fd, "\t# use mailers\n"); @@ -562,6 +786,14 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } } + + $use_resolvers = is_array($a_resolvers) && count($a_resolvers) > 0; + if ($use_resolvers) { + $use_haproxyresolvers = true; + //server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6 + $resolverprefer = ($ipversion == "ipv4" || $ipversion == "ipv6") ? $resolverprefer = " resolve-prefer {$ipversion}" : ""; + $server_options .= " resolvers globalresolvers" . $resolverprefer; + } } if ($pool['log-health-checks'] == 'yes') @@ -586,39 +818,46 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { fwrite ($fd, "\trspirep ^(Set-Cookie:((?!;\\ secure).)*)$ \\1;\ secure if { ssl_fc }\n"); } - if($pool['stats_enabled']=='yes') { + if ($pool['stats_enabled'] == 'yes') { fwrite ($fd, "\tstats\t\t\tenable\n"); - if($pool['stats_uri']) + if ($pool['stats_uri']) { fwrite ($fd, "\tstats\t\t\turi ".$pool['stats_uri']."\n"); - if($pool['stats_realm']) + } + if ($pool['stats_realm']) { fwrite ($fd, "\tstats\t\t\trealm " . haproxy_escapestring($pool['stats_realm']) . "\n"); - else + } else { fwrite ($fd, "\tstats\t\t\trealm .\n"); + } - if ($pool['stats_username'] && $pool['stats_password']) + if ($pool['stats_username'] && $pool['stats_password']) { fwrite ($fd, "\tstats\t\t\tauth " . haproxy_escapestring($pool['stats_username']).":". haproxy_escapestring($pool['stats_password'])."\n"); - - if($pool['stats_admin']=='yes') + } + if ($pool['stats_admin'] == 'yes') { fwrite ($fd, "\tstats\t\t\tadmin if TRUE" . "\n"); - - if($pool['stats_node']) + } + if ($pool['stats_node']) { fwrite ($fd, "\tstats\t\t\tshow-node " . $pool['stats_node'] . "\n"); - if($pool['stats_desc']) + } + if ($pool['stats_desc']) { fwrite ($fd, "\tstats\t\t\tshow-desc " . haproxy_escapestring($pool['stats_desc']) . "\n"); - if($pool['stats_refresh']) + } + if ($pool['stats_refresh']) { fwrite ($fd, "\tstats\t\t\trefresh " . $pool['stats_refresh'] . "\n"); + } if ($pool['stats_scope']) { $scope_items = explode(",", $pool['stats_scope']); - foreach($scope_items as $scope_item) + foreach($scope_items as $scope_item) { fwrite ($fd, "\tstats\t\t\tscope " . $scope_item . "\n"); + } } } if (is_arrayset($pool,'errorfiles','item')) { foreach($pool['errorfiles']['item'] as $errorfile) { - if (!is_array($a_files_cache))// load only once + if (!is_array($a_files_cache)) {// load only once $a_files_cache = haproxy_get_fileslist(); + } $file = $errorfile['errorfile']; $errorcodes = explode(",",$errorfile['errorcode']); foreach($errorcodes as $errorcode) { @@ -688,19 +927,35 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } - if($pool['balance']) - fwrite ($fd, "\tbalance\t\t\t" . $pool['balance'] . "\n"); - - if(!$pool['connection_timeout']) + if ($pool['balance']) { + $parameters = ""; + if ($pool['balance'] == 'uri') { + if (!empty($pool['balance_urilen'])) { + $parameters .= " len {$pool['balance_urilen']}"; + } + if (!empty($pool['balance_uridepth'])) { + $parameters .= " depth {$pool['balance_uridepth']}"; + } + if ($pool['balance_uriwhole'] == 'yes') { + $parameters .= " whole"; + } + + } + fwrite ($fd, "\tbalance\t\t\t{$pool['balance']}{$parameters}\n"); + } + if (!$pool['connection_timeout']) { $pool['connection_timeout'] = 30000; + } fwrite ($fd, "\ttimeout connect\t\t" . $pool['connection_timeout'] . "\n"); - if(!$pool['server_timeout']) + if (!$pool['server_timeout']) { $pool['server_timeout'] = 30000; + } fwrite ($fd, "\ttimeout server\t\t" . $pool['server_timeout'] . "\n"); - if(!$pool['retries']) + if (!$pool['retries']) { $pool['retries'] = 3; + } fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n"); $addrprefix = ""; @@ -718,13 +973,15 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } $uri = $pool['monitor_uri']; - if ($pool['monitor_uri']) + if ($pool['monitor_uri']) { $uri = $pool['monitor_uri']; - else + } else { $uri = "/"; - - if ($optioncheck) + } + + if ($optioncheck) { fwrite ($fd, "\toption\t\t\t{$optioncheck}\n"); + } if ($pool['advanced_backend']) { $adv_be = explode("\n", base64_decode($pool['advanced_backend'])); @@ -735,7 +992,7 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } - if($pool['advanced']) { + if ($pool['advanced']) { $advanced = base64_decode($pool['advanced']); $advanced_txt = " " . $advanced; } else { @@ -743,28 +1000,33 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } if ($check_type != 'none') { - if($pool['checkinter']) + if ($pool['checkinter']) { $checkinter = " check inter {$pool['checkinter']}"; - else + } else { $checkinter = " check inter 1000"; + } } //agent-check requires at least haproxy v1.5dev20 - if ($pool['agent_check']) + if ($pool['agent_check']) { $agentcheck = " agent-check agent-inter {$pool['agent_inter']} agent-port {$pool['agent_port']}"; + } if (is_array($a_servers)) { foreach($a_servers as $be) { - if ($be['status'] == "inactive") + if ($be['status'] == "inactive") { continue; - if($be['cookie'] && $frontendtype == "http") + } + if ($be['cookie'] && $frontendtype == "http") { $cookie = " cookie {$be['cookie']}"; - else + } else { $cookie = ""; + } - if (!$be['name']) + if (!$be['name']) { $be['name'] = $be['address']; - if(!$be['status'] || $be['status'] != 'active') { + } + if (!$be['status'] || $be['status'] != 'active') { $isbackup = $be['status']; } else { $isbackup = ""; @@ -775,8 +1037,7 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { $crtfile = ""; $verifynone = ""; $verifyhost = ""; - if ($be['ssl'] == 'yes') - { + if ($be['ssl'] == 'yes') { $ssl = $frontendtype == "http" ? ' ssl' : ' check-ssl'; if ($be['sslserververify'] != 'yes') { @@ -803,24 +1064,25 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { haproxy_write_certificate_crt($filename, $server_clientcert, true); $crtfile = " crt $filename"; } - } $weight = ""; - if (is_numeric($be['weight'])){ + if (is_numeric($be['weight'])) { $weight = " weight " . $be['weight']; } $maxconn = ""; - if (is_numeric($be['maxconn'])){ + if (is_numeric($be['maxconn'])) { $maxconn = " maxconn " . $be['maxconn']; } + $unix_socket = false; $servers = array(); if ($be['forwardto'] && $be['forwardto'] != "") { + $unix_socket = true; $servers[] = "/{$be['forwardto']}.socket send-proxy-v2-ssl-cn"; } else { - if (is_ipaddr($be['address'])) { + if (is_ipaddr($be['address']) || $use_haproxyresolvers) { $servers[] = $be['address']; - } else if (is_hostname($be['address'])) { + } elseif (is_hostname($be['address'])) { $dnsresult_servers = haproxy_utils::query_dns($be['address'], $dnsquerytype); foreach($dnsresult_servers as $dnsresult_server){ $servers[] = $dnsresult_server['data']; @@ -831,18 +1093,26 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { foreach($servers as $server) { if (is_ipaddr($server)) { // skip ipv4 servers when using transparent client ip with ipv6 backend servers, and vice versa - if ($ipversion == "ipv4" && !is_ipaddrv4($server)) + if ($ipversion == "ipv4" && !is_ipaddrv4($server)) { continue; - if ($ipversion == "ipv6" && !is_ipaddrv6($server)) + } + if ($ipversion == "ipv6" && !is_ipaddrv6($server)) { continue; - if (isset($be['port'])) - $server = $server . ":" . $be['port']; + } + } else { + if (!$unix_socket) { + // place the ipv4@ or ipv6@ before the address, but not when using a unix socket + $server = $addrprefix . $server; + } + } + if (!empty($be['port'])) { + $server = $server . ":" . $be['port']; } $servername = $be['name']; if (count($servers) > 1) { $servername .= "_" . $counter; } - fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile{$advanced_txt} {$be['advanced']}\n"); + fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile$server_options{$advanced_txt} {$be['advanced']}\n"); $counter++; } } @@ -862,15 +1132,20 @@ function haproxy_check_and_run(&$messages, $reload) { haproxy_writeconf($testpath); $retval = exec("haproxy -c -V -f $testpath/haproxy.cfg 2>&1", $output, $err); $messages = ""; - if ($err > 1) + if ($err > 1) { $messages = "<h2><strong>FATAL ERROR CODE: $err while starting haproxy</strong></h2>"; - elseif ($err == 1) + } elseif ($err == 1) { $messages = "Errors found while starting haproxy"; + } if ((count($output) > 1) && $output[0] != "Configuration file is valid") { - foreach($output as $line) + $syslogmessage = ""; + foreach($output as $line) { $messages .= "<br/>" . htmlspecialchars($line) . "\n"; + $syslogmessage .= str_replace("\n"," ", $line) . " "; + } + syslog(LOG_NOTICE, "haproxy: check error output: {$syslogmessage}"); } $ok = strstr($retval, "Configuration file is valid"); if ($ok && $reload) { @@ -884,16 +1159,18 @@ function haproxy_check_and_run(&$messages, $reload) { function haproxy_lookup_cert($certid) { $res = lookup_ca($certid); - if (!$res) + if (!$res) { $res = lookup_cert($certid); + } return $res; } function haproxy_write_certificate_crt($filename, $certid, $include_psk = false, $append = false) { $cert = haproxy_lookup_cert($certid); $certcontent = base64_decode($cert['crt']); - if ($include_psk && isset($cert['prv'])) + if ($include_psk && isset($cert['prv'])) { $certcontent .= "\r\n".base64_decode($cert['prv']); + } $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $certcontent, $flags); unset($certcontent); @@ -902,6 +1179,7 @@ function haproxy_write_certificate_crt($filename, $certid, $include_psk = false, function haproxy_write_certificate_crl($filename, $crlid, $append = false) { $crl = lookup_crl($crlid); + crl_update($crl); $content = base64_decode($crl['text']); $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $content, $flags); @@ -913,18 +1191,21 @@ function haproxy_write_certificate_fullchain($filename, $certid, $append = false $cert = haproxy_lookup_cert($certid); $certcontent = base64_decode($cert['crt']); - if (isset($cert['prv'])) + if (isset($cert['prv'])) { $certcontent .= "\r\n".base64_decode($cert['prv']); + } $ca = $cert; while(!empty($ca['caref'])) { $ca = lookup_ca($ca['caref']); if ($ca) { - if ($skiproot && (cert_get_subject($ca['crt']) == cert_get_issuer($ca['crt']))) + if ($skiproot && (cert_get_subject($ca['crt']) == cert_get_issuer($ca['crt']))) { break; + } $certcontent .= "\r\n" . base64_decode($ca['crt']); - } else + } else { break; + } } $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $certcontent, $flags); @@ -947,8 +1228,9 @@ function haproxy_write_certificate_issuer($filename, $certid) { function haproxy_uses_ocsp() { global $config; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if (!is_array($a_frontends)) + if (!is_array($a_frontends)) { return false; + } $configpath = "{$g['varetc_path']}/haproxy"; foreach ($a_frontends as $frontend) { @@ -977,9 +1259,9 @@ function haproxy_updateocsp_one($socketupdate, $filename, $name) { if ($socketupdate) { $ocspresponse = base64_encode(file_get_contents("{$filename}.ocsp")); $r = haproxy_socket_command("set ssl ocsp-response $ocspresponse"); - if ($r[0] == "OCSP Response updated!\n") + if ($r[0] == "OCSP Response updated!\n") { syslog(LOG_NOTICE, "HAProxy OCSP socket update successful for frontend {$name}..result: ".$retval); - else { + } else { syslog(LOG_ERR, "HAProxy OCSP ERROR while performing haproxy socket update OCSP response for: {$name}"); } } else { @@ -992,8 +1274,9 @@ function haproxy_updateocsp_one($socketupdate, $filename, $name) { function haproxy_updateocsp($socketupdate = true) { global $config, $g; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if (!is_array($a_frontends)) + if (!is_array($a_frontends)) { return true; + } $configpath = "{$g['varetc_path']}/haproxy"; foreach ($a_frontends as $frontend) { @@ -1014,8 +1297,10 @@ function haproxy_updateocsp($socketupdate = true) { function haproxy_writeconf($configpath) { global $config; global $aliastable; - if (!isset($aliastable)) + global $a_action; + if (!isset($aliastable)) { alias_make_table($config); + } $chroot_dir = "/tmp/haproxy_chroot"; // can contain socket to forward connection from backend to frontend. "/var/empty" @mkdir($chroot_dir, 0755, true); @@ -1027,38 +1312,52 @@ function haproxy_writeconf($configpath) { $a_global = &$config['installedpackages']['haproxy']; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; - $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['items']; + $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['item']; + $a_resolvers = &$config['installedpackages']['haproxy']['dns_resolvers']['item']; + $a_files = &$config['installedpackages']['haproxy']['files']['item']; $fd = fopen($configfile, "w"); - if(is_array($a_global)) { + if (is_array($a_global)) { fwrite ($fd, "global\n"); - if ($a_global['maxconn']) + if ($a_global['maxconn']) { fwrite ($fd, "\tmaxconn\t\t\t".$a_global['maxconn']."\n"); - if($a_global['remotesyslog']) + } + if ($a_global['remotesyslog']) { fwrite ($fd, "\tlog\t\t\t{$a_global['remotesyslog']}\t{$a_global['logfacility']}\t{$a_global['loglevel']}\n"); + } fwrite ($fd, "\tstats socket /tmp/haproxy.socket level admin\n"); - if(!use_transparent_clientip_proxying()) + if(!use_transparent_clientip_proxying()) { fwrite ($fd, "\tuid\t\t\t80\n"); - + } + fwrite ($fd, "\tgid\t\t\t80\n"); // Set numprocs if defined or use system default (#cores) - if($a_global['nbproc']) - $numprocs = $a_global['nbproc']; - else - $numprocs ="1"; + $numprocs = $a_global['nbproc'] ? $a_global['nbproc'] : "1"; fwrite ($fd, "\tnbproc\t\t\t$numprocs\n"); fwrite ($fd, "\tchroot\t\t\t$chroot_dir\n"); fwrite ($fd, "\tdaemon\n"); - //fwrite ($fd, "\tssl-server-verify none\n"); - if($a_global['ssldefaultdhparam']) + if ($a_global['ssldefaultdhparam']) { fwrite ($fd, "\ttune.ssl.default-dh-param\t{$a_global['ssldefaultdhparam']}\n"); - if($a_global['log-send-hostname']) + } + if ($a_global['log-send-hostname']) { fwrite ($fd, "\tlog-send-hostname\t\t{$a_global['log-send-hostname']}\n"); + } + + // lua-load + foreach($a_files as $file) { + if ($file['type'] == "luascript") { + $luafile = $configpath . "/luascript_" . $file['name']; + file_put_contents($luafile, base64_decode($file['content']), 0); + fwrite ($fd, "\tlua-load\t\t{$luafile}\n"); + + } + } + // Keep the advanced options on the bottom of the global settings, to allow additional sections to be easely added - if($a_global['advanced']) { + if ($a_global['advanced']) { $adv = explode("\n", base64_decode($a_global['advanced'])); foreach($adv as $adv_line) { fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); @@ -1073,8 +1372,9 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\tbind 127.0.0.1:$localstatsport name localstats\n"); fwrite ($fd, "\tmode http\n"); fwrite ($fd, "\tstats enable\n"); - if (is_numeric($a_global['localstats_refreshtime'])) + if (is_numeric($a_global['localstats_refreshtime'])) { fwrite ($fd, "\tstats refresh {$a_global['localstats_refreshtime']}\n"); + } fwrite ($fd, "\tstats admin if TRUE\n"); fwrite ($fd, "\tstats uri /haproxy_stats.php?haproxystats=1\n"); fwrite ($fd, "\ttimeout client 5000\n"); @@ -1084,7 +1384,7 @@ function haproxy_writeconf($configpath) { } } - if (haproxy_verion() >= '1.6') { + if (haproxy_version() >= '1.6') { $use_mailers = is_array($a_mailers) && count($a_mailers) > 0; if ($use_mailers) { fwrite ($fd, "mailers globalmailers\n"); @@ -1093,16 +1393,26 @@ function haproxy_writeconf($configpath) { } fwrite ($fd, "\n"); } + $use_resolvers = is_array($a_resolvers) && count($a_resolvers) > 0; + if ($use_resolvers) { + fwrite ($fd, "resolvers globalresolvers\n"); + foreach($a_resolvers as $resolver) { + fwrite ($fd, "\tnameserver {$resolver['name']} {$resolver['server']}:{$resolver['port']}\n"); + } + fwrite ($fd, "\tresolve_retries {$a_global['resolver_retries']}\n"); + fwrite ($fd, "\ttimeout retry {$a_global['resolver_timeoutretry']}\n"); + fwrite ($fd, "\thold valid {$a_global['resolver_holdvalid']}\n"); + fwrite ($fd, "\n"); + } } // Try and get a unique array for address:port as frontends can duplicate $a_bind = array(); - if(is_array($a_frontends)) { + if (is_array($a_frontends)) { foreach ($a_frontends as $frontend) { - if($frontend['status'] != 'active') - continue; - if(!$frontend['backend_serverpool']) + if ($frontend['status'] != 'active') { continue; + } $primaryfrontend = get_primaryfrontend($frontend); $bname = $primaryfrontend['name']; @@ -1131,8 +1441,8 @@ function haproxy_writeconf($configpath) { $subfolder = "$configpath/{$frontend['name']}"; $certs = $frontend['ha_certificates']['item']; - if (is_array($certs)){ - if (count($certs) > 0){ + if (is_array($certs)) { + if (count($certs) > 0) { @mkdir($subfolder, 0755, true); foreach($certs as $cert){ $filenamefoldercert = "$subfolder/{$cert['ssl_certificate']}.pem"; @@ -1148,7 +1458,7 @@ function haproxy_writeconf($configpath) { $ssl_crt .= " crt $subfolder"; } } - }else{ + } else { $ssl_crt=""; unlink_if_exists("var/etc/{$frontend['name']}.{$frontend['port']}.crt");//cleanup for possible old haproxy package version } @@ -1161,8 +1471,9 @@ function haproxy_writeconf($configpath) { } if ($ssl_crt != "") { - if ($b['ssl_info'] == "") + if ($b['ssl_info'] == "") { $b['ssl_info'] = "ssl {$frontend['dcertadv']}"; + } $b['ssl_info'] .= $ssl_crt; } @@ -1170,26 +1481,26 @@ function haproxy_writeconf($configpath) { $b['config'][] = $frontend; } } - $a_pendingpl = array(); // Construct and write out configuration for each "frontend" - if(is_array($a_bind)) { + if (is_array($a_bind)) { foreach ($a_bind as $bind) { - if (count($bind['config']) > 1) + if (count($bind['config']) > 1) { $frontendinfo = "frontend {$bind['name']}-merged\n"; - else + } else { $frontendinfo = "frontend {$bind['name']}\n"; + } fwrite ($fd, "{$frontendinfo}"); $advancedextra = array(); $ca_file = ""; $first = true; - if (is_array($bind['clientcert_ca']['item'])){ + if (is_array($bind['clientcert_ca']['item'])) { $filename = "$configpath/clientca_{$bind['name']}.pem"; - foreach($bind['clientcert_ca']['item'] as $ca){ - if (!empty($ca['cert_ca'])){ + foreach($bind['clientcert_ca']['item'] as $ca) { + if (!empty($ca['cert_ca'])) { haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first); $first = false; } @@ -1199,9 +1510,9 @@ function haproxy_writeconf($configpath) { } $crl_file = ""; $first = true; - if (is_array($bind['clientcert_crl']['item'])){ + if (is_array($bind['clientcert_crl']['item'])) { $filename = "$configpath/clientcrl_{$bind['name']}.pem"; - foreach($bind['clientcert_crl']['item'] as $ca){ + foreach($bind['clientcert_crl']['item'] as $ca) { haproxy_write_certificate_crl($filename, $ca['cert_crl'], !$first); $first = false; } @@ -1210,8 +1521,9 @@ function haproxy_writeconf($configpath) { $advanced_bind = $bind['advanced_bind']; $ssl_info = $bind['ssl_info']; $ssl_info .= $ca_file . $crl_file; - if ($bind['sslclientcert-invalid']) + if ($bind['sslclientcert-invalid']) { $ssl_info .= " crt-ignore-err all"; + } $useipv4 = false; $useipv6 = false; @@ -1226,12 +1538,12 @@ function haproxy_writeconf($configpath) { } fwrite ($fd, "{$listenip}"); - if (use_frontend_as_unixsocket($bind['name'])){ + if (use_frontend_as_unixsocket($bind['name'])) { fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket name unixsocket accept-proxy {$ssl_info} {$advanced_bind}\n"); } // https is an alias for tcp for clarity purposes - if($bind['type'] == "https") { + if ($bind['type'] == "https") { $backend_type = "tcp"; } else { $backend_type = $bind['type']; @@ -1240,26 +1552,32 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); fwrite ($fd, "\tlog\t\t\tglobal\n"); - if ($bind['socket-stats'] == 'yes') + if ($bind['socket-stats'] == 'yes') { fwrite ($fd, "\toption\t\t\tsocket-stats\n"); - if ($bind['dontlognull'] == 'yes') + } + if ($bind['dontlognull'] == 'yes') { fwrite ($fd, "\toption\t\t\tdontlognull\n"); - if ($bind['dontlog-normal'] == 'yes') + } + if ($bind['dontlog-normal'] == 'yes') { fwrite ($fd, "\toption\t\t\tdontlog-normal\n"); - if ($bind['log-separate-errors'] == 'yes') + } + if ($bind['log-separate-errors'] == 'yes') { fwrite ($fd, "\toption\t\t\tlog-separate-errors\n"); - if ($bind['log-detailed'] == 'yes'){ - if ($backend_type == 'http') + } + if ($bind['log-detailed'] == 'yes') { + if ($backend_type == 'http') { fwrite ($fd, "\toption\t\t\thttplog\n"); - else + } else { fwrite ($fd, "\toption\t\t\ttcplog\n"); + } } if ($backend_type == 'http') { - if($bind['httpclose'] && $bind['httpclose'] != "none" ) + if ($bind['httpclose'] && $bind['httpclose'] != "none") { fwrite ($fd, "\toption\t\t\t{$bind['httpclose']}\n"); + } - if($bind['forwardfor']) { + if ($bind['forwardfor']) { fwrite ($fd, "\toption\t\t\tforwardfor\n"); fwrite ($fd, "\tacl https ssl_fc\n"); fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http if !https\n"); @@ -1267,19 +1585,20 @@ function haproxy_writeconf($configpath) { } } - if($bind['max_connections']) - fwrite ($fd, "\tmaxconn\t\t\t" . $bind['max_connections'] . "\n"); + if ($bind['max_connections']) { + fwrite ($fd, "\tmaxconn\t\t\t{$bind['max_connections']}\n"); + } - if(!$bind['client_timeout']) + if (!$bind['client_timeout']) { $bind['client_timeout'] = 30000; + } - fwrite ($fd, "\ttimeout client\t\t" . $bind['client_timeout'] . "\n"); + fwrite ($fd, "\ttimeout client\t\t{$bind['client_timeout']}\n"); - // Advanced pass thru - if($bind['advanced']) { - $advanced = explode("\n", base64_decode($bind['advanced'])); - foreach($advanced as $adv_line) { + if ($bind['advanced']) { + $advanced = explode("\n", base64_decode($bind['advanced'])); + foreach ($advanced as $adv_line) { if ($adv_line != "") { fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); } @@ -1288,176 +1607,224 @@ function haproxy_writeconf($configpath) { // Combine the rest of the frontend configs $default_backend = ""; - $config_acls = ""; + $config_acls = array(); + $config_actions = ""; $config_usebackends = ""; $config_usedefaultbackends = ""; $transparent_clientip = false; foreach ($bind['config'] as $frontend) { - $backend = haproxy_find_backend($frontend['backend_serverpool']); - if ($backend["transparent_clientip"] == 'yes') { + //todo: check also use_backend actions + if (frontend_usetransparentbackend($frontend)) { $transparent_clientip = true; break; } } if ($transparent_clientip && $useipv4 && $useipv6) { // set the src_is_ipv4 acl if needed. - $config_acls .= "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n"; + $acl = "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n"; + $config_acls[$acl] = 1; } $inspectdelay = 0; $i = 0; $acllist = array(); + $needs_clientcert = array(); $acl_newid = 0; foreach ($bind['config'] as $frontend) { + // loop through 'shared frontends' within one primary. + $a_acl = get_frontend_acls($frontend); + + $a_actionitems = $frontend['a_actionitems']['item']; + if (!is_array($a_actionitems)) { + $a_actionitems = array(); + } + if (!empty($frontend['backend_serverpool'])) { + // insert extra use_backend action without a user-condition + $item = array(); + $item['action'] = "use_backend"; + $item['use_backendbackend'] = $frontend['backend_serverpool']; + $a_actionitems[] = $item; + } - $backend = haproxy_find_backend($frontend['backend_serverpool']); - $transparent_clientip = $backend["transparent_clientip"] == 'yes'; + //$backend = haproxy_find_backend($frontend['backend_serverpool']); + //$transparent_clientip = $backend["transparent_clientip"] == 'yes'; + $transparent_clientip = frontend_usetransparentbackend($frontend); + $allowfordefaultbackend = true; $ipv = array(); if ($transparent_clientip) { if ($useipv4 && $useipv6) { $ipv["ipv4"]['acl'] = " src_is_ipv4 "; + $ipv["ipv4"]['aclnameadd'] = "_ipv4"; $ipv["ipv6"]['acl'] = " !src_is_ipv4 "; + $ipv["ipv6"]['aclnameadd'] = "_ipv6"; $allowfordefaultbackend = false; // transparent backend must always match client-ip which is ipv4 v.s. ipv6 specific so there cannot be a default. - } else if ($useipv6) + } elseif ($useipv6) { $ipv["ipv6"]['acl'] = " "; - else + $ipv["ipv6"]['aclnameadd'] = ""; + } else { $ipv["ipv4"]['acl'] = " "; - } else - $ipv["ipvANY"]['acl'] = " "; - - // combine acl's with same name to allow for 'combined checks' to check for example hostname and fileextension together.. - $a_acl_combine = array(); - foreach ($a_acl as $entry) { - $name = $entry['ref']['name']; - - $acl = array(); - $acl['ref'] = $entry['ref']; - $acltype = haproxy_find_acl($entry['ref']['expression']); - $acl['acltype'] = $acltype; - if (!isset($acltype)) - continue; - $a_acl_combine[$name][] = $acl; - - if (isset($acltype['require_client_cert'])){ - $acl = array(); - $acl['ref']['expression'] = "ssl_c_used"; - $acl['acltype']['syntax'] = "ssl_c_used"; - $acl['acltype']['novalue'] = 1; - $a_acl_combine[$name][] = $acl; + $ipv["ipv4"]['aclnameadd'] = ""; } + } else { + $ipv["ipvANY"]['acl'] = " "; + $ipv["ipvANY"]['aclnameadd'] = ""; } - + $certacl = ""; $y = 0; foreach($ipv as $ipversion => $ipversionoptions) { - $useracls = array(); - $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type'])."_".$ipversion; - if (!isset($a_pendingpl[$poolname])) { - $a_pendingpl[$poolname] = array(); - $a_pendingpl[$poolname]['name'] = $poolname; - $a_pendingpl[$poolname]['backend'] = $frontend['backend_serverpool']; - $a_pendingpl[$poolname]['frontend'] = $bind; - $a_pendingpl[$poolname]['ipversion'] = $ipversion; - } - $canbedefaultbackend = false; - // Write this out once, and must be before any backend config text - if (($default_backend == "" || $frontend['secondary'] != 'yes') && count($a_acl) == 0 ) { - $canbedefaultbackend = true; - if ($allowfordefaultbackend) - $default_backend = $poolname; + $cert_acls = ""; + $aclcrt_name = ""; + + // ACL's + foreach ($a_acl as $entry) { + $aclitem = $entry['ref']; + $expression = $aclitem['expression']; + + $aclname = $aclitem['name']; + $acltype = haproxy_find_acl($expression); + if (!isset($acltype)) + continue; + + // Filter out acls for different modes + if ($acltype['mode'] != '' && $acltype['mode'] != strtolower($bind['type'])) { + continue; + } + if ($acltype['inspect-delay'] != '') { + $inspectdelay = $acltype['inspect-delay']; + } + if ($acltype['advancedoptions'] != '') { + $advancedextra[$acltype['syntax']] = $acltype['advancedoptions']."\n"; + } + if ($acltype['require_client_cert']) { + $needs_clientcert[$aclname] = true; + } + if ($aclitem['certacl']) { + $aclname = "aclcrt_{$frontend['name']}"; + $aclcrt_name = $aclname; + } + + if (($expression == "source_ip") && is_alias($aclitem['value'])) { + $filename = "$configpath/ipalias_{$aclitem['value']}.lst"; + $listitems = haproxy_hostoralias_to_list($aclitem['value']); + $fd_alias = fopen("$filename", "w"); + foreach($listitems as $item) { + fwrite($fd_alias, $item."\r\n"); + } + fclose($fd_alias); + $expr = "src -f $filename"; + } else { + $expr = sprintf($acltype['syntax'], $aclitem['value']); + if (is_array($acltype['fields'])) { + foreach ($acltype['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $aclitem[$expression . $fieldname]; + if ($fieldname == "backend") { + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + $parameter = $backendname; + } + $expr = str_replace("{{$fieldname}}", $parameter, $expr); + } + } + } + $config_acls ["\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"] = 1; } - - foreach ($a_acl_combine as $a_usebackend) { - $aclnames = ""; - foreach ($a_usebackend as $entry2) { - $entry = $entry2['ref']; - $acl = $entry2['acltype']; - - // Filter out acls for different modes - if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type'])) - continue; - if (($entry['expression'] == "source_ip") && is_alias($entry['value'])) { - $filename = "$configpath/ipalias_{$entry['value']}.lst"; - $listitems = haproxy_hostoralias_to_list($entry['value']); - $fd_alias = fopen("$filename", "w"); - foreach($listitems as $item) - fwrite($fd_alias, $item."\r\n"); - fclose($fd_alias); - $expr = "src -f $filename"; - } else - $expr = sprintf($acl['syntax'],$entry['value'],$poolname); - - $not = $entry['not'] == "yes" ? "!" : ""; - - unset($aclkey); - foreach($acllist as $aclid => $aclitem) { - if ($aclitem['expr'] == $expr) { - $aclkey = $aclid; + + $systemacl = trim("{$aclcrt_name}{$ipversionoptions['acl']}"); + + foreach ($a_actionitems as $actionitem) { + $actionid = $actionitem['action']; + $action = $a_action[$actionid]; + + $action_cfg = $action['syntax']; + + if (is_array($action['fields'])) { + foreach ($action['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $actionitem[$actionid . $field['name']]; + + if ($fieldname == "backend") { + $backend = $parameter; + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + if (!isset($a_pendingpl[$backendname])) { + $a_pendingpl[$backendname] = array(); + $a_pendingpl[$backendname]['name'] = $backendname; + $a_pendingpl[$backendname]['backend'] = $backend; + $a_pendingpl[$backendname]['frontend'] = $bind; + $a_pendingpl[$backendname]['ipversion'] = $ipversion; + } + $parameter = $backendname; } + $action_cfg = str_replace("{{$fieldname}}", $parameter, $action_cfg); } - if (isset($aclkey)) { - $aclname = $acllist[$aclkey]['aclname']; + } + $condition = ""; + if (!empty($actionitem['acl']) || !empty($systemacl)) { + $useclientcert = ""; + $useracls = ""; + $aclnames = explode(' ', $actionitem['acl']); + foreach($aclnames as $aclname) { + if ($needs_clientcert[$aclname]) { + $useclientcert = " aclsystem_ssl_c_used"; + } + $not = ""; + foreach ($a_acl as $entry) { + if ($entry['ref']['name'] == $aclname && $entry['ref']['not'] == 'yes') { + $not = "!"; + } + } + $useracls .= " {$not}{$aclname}"; + } + $condition = " if {$useracls}{$useclientcert} {$systemacl}"; + } + + $action = "\t{$action_cfg} {$condition}\n"; + + if ($actionid == "use_backend") { + if (empty($condition)) { + $config_usedefaultbackends .= "\tdefault_backend {$parameter}{$condition}\n"; } else { - $aclkey = $acl_newid++; - if ($entry['certacl']) { - $aclname = "aclcrt_".$frontend['name']; - $certacl = $aclname; + if (!empty($actionitem['acl'])){ + $config_usebackends .= $action; } else { - $aclname = "aclusr_{$entry['expression']}"; - if (!isset($acl['novalue'])) - $aclname .= "_{$entry['value']}"; - $aclname = haproxy_escape_acl_name($aclname); - $i++; + // add use_backend if ipv4/6 before default_backend if any exists.. + $config_usedefaultbackends .= $action; } - $acllist[$aclkey]['aclname'] = $aclname; - $acllist[$aclkey]['expr'] = $expr; - $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"; } - if (!isset($entry['certacl'])) - $useracls[$y] .= $not . $aclname . " "; - - if ($acl['inspect-delay'] != '') - $inspectdelay = $acl['inspect-delay']; - - if ($acl['advancedoptions'] != '') - $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n"; + } else { + $config_actions .= $action; } - $y++; - } - - $systemacl = trim("{$certacl}{$ipversionoptions['acl']}"); - if (!empty($systemacl) && count($useracls) == 0) $useracls[] = ""; // add empty item to enter foreach loop at least once when a system acl is pressent. - foreach($useracls as $useracl) { - $backendacl = ""; - $backendacl .= "|| {$useracl}{$systemacl}"; - $backendacl = substr($backendacl, 3); - if ($canbedefaultbackend) { - // makes sure these come last even though systemacl's might have been added. - $config_usedefaultbackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; - } else - $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; } } } - if ($inspectdelay > 0) + if ($inspectdelay > 0) { fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "s\n"); + } + if (count($needs_clientcert) > 0) { + fwrite ($fd, "\tacl\t\t\taclsystem_ssl_c_used\tssl_c_used\n"); + } // Write acl's first, so they may be used by advanced text options written by user. - fwrite ($fd, $config_acls); + foreach($config_acls as $acl => $dummy) { + fwrite ($fd, $acl); + } - foreach($advancedextra as $extra) + foreach($advancedextra as $extra) { fwrite ($fd, "\t".$extra."\n"); + } + fwrite ($fd, $config_actions); // Write backends after advanced options so custom use_backend rules can be applied first. fwrite ($fd, $config_usebackends); fwrite ($fd, $config_usedefaultbackends); - if ($default_backend) + if ($default_backend) { fwrite ($fd, "\tdefault_backend\t\t" . $default_backend . "\n"); + } fwrite ($fd, "\n"); } @@ -1477,21 +1844,20 @@ function haproxy_writeconf($configpath) { // close config file fclose($fd); - if ($input_errors) - { + if ($input_errors) { require_once("guiconfig.inc"); print_input_errors($input_errors); } else { // Only sync to xmlrpc backup machine if no errors are found in config - if(isset($config['installedpackages']['haproxy']['enablesync'])) { + if (isset($config['installedpackages']['haproxy']['enablesync'])) { haproxy_do_xmlrpc_sync(); } } } function haproxy_is_running() { - $running = (shell_exec("/bin/pgrep -x haproxy") != ''); - return $running; + $running = (shell_exec("/bin/pgrep -x haproxy") != ''); + return $running; } function haproxy_load_modules() { @@ -1513,6 +1879,24 @@ function haproxy_load_modules() { unmute_kernel_msgs(); } +function frontend_usetransparentbackend($frontend) { + $backend = haproxy_find_backend($frontend['backend_serverpool']); + if ($backend["transparent_clientip"] == 'yes') { + return true; + } + if (is_array($frontend['a_actionitems']['item'])) { + foreach($frontend['a_actionitems']['item'] as $action) { + if ($action['action'] == "use_backend") { + $backend = haproxy_find_backend($action['use_backendbackend']); + if ($backend["transparent_clientip"] == 'yes') { + return true; + } + } + } + } + return false; +} + function use_transparent_clientip_proxying() { global $config; $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; @@ -1532,16 +1916,16 @@ function haproxy_get_transparent_backends(){ $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; $transparent_backends = array(); foreach ($a_backends as $backend) { - if ($backend["transparent_clientip"] != 'yes') + if ($backend["transparent_clientip"] != 'yes') { continue; + } $real_if = get_real_interface($backend["transparent_interface"]); $a_servers = &$backend['ha_servers']['item']; if (is_array($a_servers)) { foreach($a_servers as $be) { - if (!$be['status'] == "inactive") - continue; - if (!is_ipaddr($be['address'])) + if (!$be['status'] == "inactive" || !is_ipaddr($be['address'])){ continue; + } $item = array(); $item['name'] = $be['name']; $item['interface'] = $real_if; @@ -1618,9 +2002,9 @@ function load_ipfw_rules() { $rulenum = 64000; // why that high? captiveportal.inc also does it... $rules = "flush\n"; foreach($transparent_backends as $transparent_be) { - if (is_ipaddrv4($transparent_be["address"])) + if (is_ipaddrv4($transparent_be["address"])) { $rules .= "add $rulenum fwd localhost tcp from {$transparent_be["address"]} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; - else if (is_ipaddrv6($transparent_be["address"])) { + } elseif (is_ipaddrv6($transparent_be["address"])) { list ($addr, $scope) = explode("%", $transparent_be['address']); $rules .= "add $rulenum fwd ::1 tcp from {$addr} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; } @@ -1715,7 +2099,7 @@ function haproxy_check_run($reload) { } } - if(isset($a_global['enable'])) { + if (isset($a_global['enable'])) { if (isset($a_global['carpdev'])) { $status = haproxy_carpipismaster($a_global['carpdev']); if (!$status) { @@ -1726,18 +2110,18 @@ function haproxy_check_run($reload) { } unlock($haproxylock); return (0); - } else if (haproxy_is_running() && $reload == 0) { + } elseif (haproxy_is_running() && $reload == 0) { unlock($haproxylock); return (0); } log_error("Starting haproxy on CARP master."); /* fallthrough */ - } else if ($reload == 0){ + } elseif ($reload == 0) { unlock($haproxylock); return (0); } - if(use_transparent_clientip_proxying()) { + if (use_transparent_clientip_proxying()) { filter_configure(); load_ipfw_rules(); } else { @@ -1751,14 +2135,16 @@ function haproxy_check_run($reload) { if (file_exists('/var/run/haproxy.pid')){ $old_pid = file_get_contents('/var/run/haproxy.pid'); - } else + } else { $old_pid = 'none'; + } if (haproxy_is_running()) { - if (isset($a_global['terminate_on_reload'])) + if (isset($a_global['terminate_on_reload'])) { $sf_st = "-st";//terminate old process as soon as the new process is listening - else + } else { $sf_st = "-sf";//finish serving existing connections exit when done, and the new process is listening + } syslog(LOG_NOTICE, "haproxy: reload old pid:$old_pid"); exec("/usr/local/sbin/haproxy -f {$configpath}/haproxy.cfg -p /var/run/haproxy.pid $sf_st `cat /var/run/haproxy.pid` 2>&1", $output, $errcode); @@ -1768,12 +2154,20 @@ function haproxy_check_run($reload) { } if (file_exists('/var/run/haproxy.pid')){ $new_pid = file_get_contents('/var/run/haproxy.pid'); - } else + } else { $new_pid = 'none'; + } syslog(LOG_NOTICE, "haproxy: started new pid:$new_pid"); - foreach($output as $line) + $syslogmessage = ""; + foreach($output as $line) { $haproxy_run_message .= "<br/>" . htmlspecialchars($line) . "\n"; + $syslogmessage .= str_replace("\n"," ",$line); + } + if (!empty($syslogmessage)) { + syslog(LOG_NOTICE, "haproxy: startup error output!: {$syslogmessage}"); + } + } else { if ($reload && haproxy_is_running()) { //exec("/bin/pkill -F /var/run/haproxy.pid haproxy");//doesnt work for multiple pid's in a pidfile @@ -1786,10 +2180,11 @@ function haproxy_check_run($reload) { } function haproxy_kill($killimmediately = true) { - if ($killimmediately) + if ($killimmediately) { $signal = "KILL"; // stop now - else + } else { $signal = "USR1"; // stop when all connections are closed + } killprocesses("haproxy", "/var/run/haproxy.pid", $signal); } @@ -1838,7 +2233,7 @@ function haproxy_xmlrpc_sync_configure() { haproxy_configure(); // Configure HAProxy config files to use the new configuration. // sync 2nd and further nodes in the chain if applicable. - if(isset($config['installedpackages']['haproxy']['enablesync'])) { + if (isset($config['installedpackages']['haproxy']['enablesync'])) { haproxy_do_xmlrpc_sync(); } } @@ -1857,34 +2252,38 @@ function get_frontend_id($name) { } function haproxy_is_frontendname($name) { - if ($name[0] == '!') + if ($name[0] == '!') { $name = substr($name, 1); + } return get_frontend_id($name) != null; } function get_primaryfrontend($frontend) { global $config; $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if ($frontend['secondary'] == 'yes') + if ($frontend['secondary'] == 'yes') { $mainfrontend = $a_frontend[get_frontend_id($frontend['primary_frontend'])]; - else + } else { $mainfrontend = $frontend; + } return $mainfrontend; } function get_frontend_ipport($frontend, $userfriendly=false) { $mainfrontend = get_primaryfrontend($frontend); $result = array(); - if (!is_arrayset($mainfrontend,"a_extaddr","item")) + if (!is_arrayset($mainfrontend,"a_extaddr","item")) { return $result; + } foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { if ($extaddr['extaddr'] == 'custom'){ $addr = $extaddr['extaddr_custom']; } else { $addr = haproxy_interface_ip($extaddr['extaddr'], $userfriendly); } - if ($userfriendly and is_ipaddrv6($addr)) + if ($userfriendly and is_ipaddrv6($addr)) { $addr = "[{$addr}]"; + } $port = $extaddr['extaddr_port']; $newitem = array(); @@ -1910,10 +2309,11 @@ function get_frontend_bindips($frontend) { $iporalias = $extaddr['extaddr_custom']; $a_ip = haproxy_addressoralias_to_list($iporalias); } - if ($extaddr['extaddr_ssl'] == 'yes') + if ($extaddr['extaddr_ssl'] == 'yes') { $ssl = $ssl_info; - else + } else { $ssl = ""; + } foreach($a_ip as $ip) { $portsnumeric = group_ports(haproxy_portoralias_to_list($extaddr['extaddr_port'])); @@ -1940,46 +2340,66 @@ function haproxy_check_config() { $activefrontends = array(); $issues = array(); - foreach($a_backends as $frontend) { - if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) + foreach ($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) { continue; + } $ipports = get_frontend_ipport($frontend); foreach($ipports as $ipport) { $id = "{$ipport['addr']}:{$ipport['port']}"; - if (isset($activefrontends[$id])) - $issues['P_'.$id] = "Multiple primary frontends with IP:Port \"$id\", use Shared-Frontends instead."; - else - $activefrontends[$id] = true; + if (isset($activefrontends[$id])) { + $activefrontends[$id] = $activefrontends[$id].", ".$frontend['name']; + $issues['P_'.$id] = "Multiple primary frontends ({$activefrontends[$id]}) with IP:Port \"$id\", use Shared-Frontends instead."; + } else { + $activefrontends[$id] = $frontend['name']; + } } } - foreach($a_backends as $frontend) { - if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) + foreach ($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) { continue; + } $mainfrontend = get_primaryfrontend($frontend); - if (!isset($mainfrontend)) + if (!isset($mainfrontend)) { $issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend."; + } } - foreach ($issues as $item) + foreach ($issues as $item) { $result .= ($result == false ? "" : "<br/>") . $item; + } + return $result; +} + +function get_haproxy_backends() { + global $config; + $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $result = array(); + if (!is_array($a_backend)) { + return $result; + } + foreach ($a_backend as &$backend) { + $result[$backend['name']]['name'] = "{$backend['name']}"; + $result[$backend['name']]['ref'] = &$backend; + } + uasort($result, haproxy_compareByName); return $result; } -function get_haproxy_frontends($excludeitem="") { +function get_haproxy_frontends($excludeitem = "") { global $config; $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; $result = array(); - if(!is_array($a_frontend)) + if (!is_array($a_frontend)) { return $result; - foreach($a_frontend as &$frontend) - { - if ($frontend['secondary']) - continue; - if ($frontend['name'] == $excludeitem) + } + foreach ($a_frontend as &$frontend) { + if ($frontend['secondary'] || $frontend['name'] == $excludeitem) { continue; + } $serveraddress = get_frontend_ipport($frontend, true); $serveradresstext = null; - foreach($serveraddress as $addr) { + foreach ($serveraddress as $addr) { $serveradresstext .=($serveradresstext == null ? "" : ", ") . "{$addr['addr']}:{$addr['port']}"; } $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradresstext})"; @@ -2009,30 +2429,44 @@ function get_frontend_uses_ssl_only($frontend) { $mainfrontend = get_primaryfrontend($frontend); if (is_arrayset($mainfrontend,'a_extaddr','item')) { foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { - if ($extaddr['extaddr_ssl'] != 'yes') + if ($extaddr['extaddr_ssl'] != 'yes') { return false; + } } } return true; } -function haproxy_get_cert_acl($cert) { - $acl_item = array(); +function haproxy_get_cert_acls($cert, $usealternativenames = false) { + $result = array(); - $cert_cn = cert_get_cn($cert['crt']); + if (!$usealternativenames) { + $cert_cns = array(); + $cert_cns[] = cert_get_cn($cert['crt']); + } else { + $cert_cns = haproxy_get_certificate_subjectAltNames($cert['crt']); + } $descr = haproxy_escape_acl_name($cert['descr']); unset($cert); - $is_wildcard = substr($cert_cn, 0, 2) == "*."; - $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex. - $wild_regex = ""; - if ($is_wildcard) { - $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard + //$i = 1; + foreach ($cert_cns as $cert_cn) { + $acl_item = array(); + $is_wildcard = substr($cert_cn, 0, 2) == "*."; + $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex. + $wild_regex = ""; + if ($is_wildcard) { + $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard + } + $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port. + + $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}"; + //$aclname_add = $usealternativenames ? "_{$i}" : ""; + $acl_item['ref'] = array('name' => "{$aclname}_{$descr}{$aclname_add}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true); + + //$i++; + $result[] = $acl_item; } - $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port. - - $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}"; - $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true); - return $acl_item; + return $result; } function get_frontend_acls($frontend) { @@ -2043,12 +2477,14 @@ function get_frontend_acls($frontend) { { foreach ($a_acl as $entry) { $acl = haproxy_find_acl($entry['expression']); - if (!$acl) + if (!$acl) { continue; + } // Filter out acls for different modes - if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) + if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) { continue; + } $not = $entry['not'] == "yes" ? "not: " : ""; $acl_item = array(); $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $not . $entry['value']); @@ -2060,22 +2496,36 @@ function get_frontend_acls($frontend) { if (get_frontend_uses_ssl($frontend)) { $a_acl = &$frontend['ha_acls']['item']; - if(!is_array($a_acl)) - $a_acl=array(); + if (!is_array($a_acl)) { + $a_acl = array(); + } - $poolname = $frontend['backend_serverpool'] . "_" . strtolower($frontend['type']); - $aclname = "SNI_" . $poolname; + //$poolname = $frontend['backend_serverpool'] . "_" . strtolower($frontend['type']); + //$aclname = "SNI_" . $poolname; - if (ifset($frontend['ssloffloadacl']) == 'yes' || ifset($frontend['ssloffloadaclnondefault']) == 'yes') { + if (ifset($frontend['ssloffloadacl']) == 'yes') { + $cert = lookup_cert($frontend['ssloffloadcert']); + $result = array_merge($result, haproxy_get_cert_acls($cert)); + } + if (ifset($frontend['ssloffloadacl_an']) == 'yes') { $cert = lookup_cert($frontend['ssloffloadcert']); - $result[] = haproxy_get_cert_acl($cert); + $result = array_merge($result, haproxy_get_cert_acls($cert, true)); } if (ifset($frontend['ssloffloadacladditional']) == 'yes') { $certs = $frontend['ha_certificates']['item']; - if (is_array($certs)){ - foreach($certs as $certref){ + if (is_array($certs)) { + foreach ($certs as $certref) { $cert = lookup_cert($certref['ssl_certificate']); - $result[] = haproxy_get_cert_acl($cert); + $result = array_merge($result, haproxy_get_cert_acls($cert)); + } + } + } + if (ifset($frontend['ssloffloadacladditional_an']) == 'yes') { + $certs = $frontend['ha_certificates']['item']; + if (is_array($certs)) { + foreach ($certs as $certref) { + $cert = lookup_cert($certref['ssl_certificate']); + $result = array_merge($result, haproxy_get_cert_acls($cert, true)); } } } @@ -2087,12 +2537,14 @@ function get_backend_id($name) { global $config; $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; $i = 0; - if(is_array($a_backend)) - foreach($a_backend as $key => $backend) { - if ($backend['name'] == $name) + if (is_array($a_backend)) { + foreach ($a_backend as $key => $backend) { + if ($backend['name'] == $name) { return $i; + } $i++; } + } return null; } @@ -2100,8 +2552,9 @@ function get_backend($name) { global $config; $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; $id = get_backend_id($name); - if (is_numeric($id)) + if (is_numeric($id)) { return $a_backend[$id]; + } return null; } @@ -2112,8 +2565,9 @@ function use_frontend_as_unixsocket($name) { $a_servers = &$backend['ha_servers']['item']; if (is_array($a_servers)) { foreach($a_servers as $server) { - if ($server['forwardto'] && $server['forwardto'] == $name) + if ($server['forwardto'] && $server['forwardto'] == $name) { return true; + } } } } @@ -2133,8 +2587,9 @@ function haproxy_escape_acl_name($aclname) { function haproxy_find_create_certificate($certificatename) { global $g; $cert = lookup_cert_by_name($certificatename); - if (is_array($cert)) + if (is_array($cert)) { return $cert; + } global $config; $a_cert =& $config['cert']; $cert = array(); diff --git a/config/haproxy-devel/pkg/haproxy_htmllist.inc b/config/haproxy-devel/pkg/haproxy_htmllist.inc index 394f3ff6..a17a5089 100644 --- a/config/haproxy-devel/pkg/haproxy_htmllist.inc +++ b/config/haproxy-devel/pkg/haproxy_htmllist.inc @@ -48,100 +48,128 @@ class HaproxyHtmlList public $fields_details = null; public $keyfield = ""; - public function HaproxyHtmlList($tablename, $fields){ + public function HaproxyHtmlList($tablename, $fields) { $this->tablename = $tablename; $this->fields = $fields; } - public function Draw($data){ + public function Draw($data) { $this->haproxy_htmllist($data, $this->fields, $this->editmode, $this->fields_details); } - function haproxy_htmllist_get_values(){ + public function outputjavascript() { + $table_def = array(); + $table_def['keyfield'] = $this->keyfield; + phparray_to_javascriptarray($table_def, "tabledefinition_".$this->tablename,Array('/*','/*/*')); + phparray_to_javascriptarray($this->fields, "fields_".$this->tablename,Array('/*','/*/name','/*/type','/*/text','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + if (count($this->fields_details) != 0) { + phparray_to_javascriptarray($this->fields_details,"fields_details_".$this->tablename,Array('/*','/*/name','/*/columnheader','/*/type','/*/text','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name','/*/items/*/*/name')); + } + } + + // function retrieves all posted values and returns an array + public function haproxy_htmllist_get_values() { $values = array(); - for($x=0; $x<99; $x++) { + for($x = 0; $x < 99; $x ++) { $value = array(); $add_item = false; - foreach($this->fields as $item){ + if (is_array($this->fields_details)) { + $fields = array_merge($this->fields, $this->fields_details); + } else { + $fields = $this->fields; + } + foreach($fields as $item) { $itemname = $item['name']; - $value[$itemname] = $_POST[$itemname.$x]; - if ($item['type'] == 'textarea') + $value[$itemname] = $_POST[$this->tablename.$itemname.$x]; + if ($item['type'] == 'textarea') { $value[$itemname] = base64_encode($value[$itemname]); - $add_item |= isset($_POST[$itemname.$x]); + } + $add_item |= isset($_POST[$this->tablename.$itemname.$x]); } if ($add_item) { if ($this->keyfield != "") { if (isset($_POST[$this->tablename."_key".$x])) $key = $_POST[$this->tablename."_key".$x]; - else - $key = $_POST[$this->keyfield.$x]; - - } else + else { + $key = $_POST[$this->tablename.$this->keyfield.$x]; + } + } else { $key = ""; - + } + $index = $_POST[$this->tablename."_rowindex".$x]; + $value['_index'] = $index; if (isset($values[$key])) $values[] = $value; else $values[$key] = $value; } } + usort($values, 'sort_index'); + return $values; } - - private function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { - $itemnamenr = $itemname . $counter; + + function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { + $itemnamenr = $this->tablename . $itemname . $counter; $itemtype = $item['type']; if ($editable) { $itemtype = $item['type']; - if ($itemtype == "select"){ - echo_html_select($itemnamenr, $item['items'], $itemvalue,"","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); - } else - if ($itemtype == "checkbox"){ + if ($itemtype == "select") { + echo_html_select($itemnamenr, $item['items'], $itemvalue,"-none available-","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); + } elseif ($itemtype == "checkbox") { $checked = $itemvalue=='yes' ? " checked" : ""; echo "<input onclick='html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);' name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />"; - } else - if ($itemtype == "textarea"){ + } elseif ($itemtype == "textarea") { echo "<textarea name='$itemnamenr' id='$itemnamenr' type='text' cols='{$item['size']}' rows='10'>"; echo htmlspecialchars(base64_decode($itemvalue)); echo "</textarea>"; - } else + } elseif ($itemtype == "fixedtext") { + echo $item['text']; + } else { echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />"; + } } else { - if ($itemtype == "select"){ + if ($itemtype == "select") { echo $item['items'][$itemvalue]['name']; - } else - if ($itemtype == "checkbox"){ + } elseif ($itemtype == "checkbox") { echo $itemvalue=='yes' ? gettext('yes') : gettext('no'); - } else - if ($itemtype == "textarea"){ + } elseif ($itemtype == "textarea") { echo '<div style="overlow:scroll;max-height:120px;overflow-y: scroll;">'; - echo str_replace("\n","<br/>", htmlspecialchars(base64_decode($itemvalue))); + echo str_replace(" "," ", str_replace("\n","<br/>", htmlspecialchars(base64_decode($itemvalue)))); echo '</div>'; - } else + } elseif ($itemtype == "fixedtext") { + echo $item['text']; + } else { echo htmlspecialchars($itemvalue); + } } } function haproxy_htmllist($rowvalues,$items,$editstate=false,$itemdetails=null){ $tablename = $this->tablename; global $g, $counter; - echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'> + echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='{$tablename}'> + <thead> <tr>"; foreach($items as $item){ echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>"; } echo "<td width='5%' class=''></td> - </tr>"; - if (is_array($rowvalues)){ - foreach($rowvalues as $keyid => $value){ - if ($this->keyfield != "") { - if (preg_match("/[^0-9]/", $keyid)) + </tr> + </thead> + <tbody>"; + if (is_array($rowvalues)) { + foreach($rowvalues as $keyid => $value) { + if (!empty($this->keyfield)) { + if (preg_match("/[^0-9]/", $keyid)) { $itemvalue = $keyid; - else + } else { $itemvalue = $value[$this->keyfield]; + } $key = "<input name='{$tablename}_key{$counter}' id='{$tablename}_key{$counter}' type='hidden' value='{$itemvalue}'>"; - } else + } else { $key = ""; + } if (!$editstate) { echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >"; @@ -152,26 +180,37 @@ class HaproxyHtmlList $itemname = $item['name']; $itemvalue = $value[$itemname]; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); - } else + $item['customdrawcell']($this, $item, $itemvalue, false); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + } echo "</td>"; $leftitem = false; } echo " - <td class='list'> - <table border='0' cellspacing='0' cellpadding='1'><tr> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> - </td></tr></table> - </td>"; + <td class='list'> + <table border='0' cellspacing='0' cellpadding='1'><tr> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow({$counter}); return false;' /> + </td> + <td valign='middle'> + <input name='{$tablename}_rowindex{$counter}' id='{$tablename}_rowindex{$counter}' type='hidden' value='{$counter}' /> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + if (empty($this->keyfield)) { + echo "<td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_up.gif' title='move row up' width='17' height='17' border='0' onclick='moveRowUp({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_down.gif' title='move row down' width='17' height='17' border='0' onclick='moveRowDown({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + } + echo "</tr></table> + </td>"; echo "</tr>"; } $displaystyle = $editstate ? "" : "display: none;"; @@ -181,9 +220,10 @@ class HaproxyHtmlList $itemvalue = $value[$itemname]; echo "<td class='vtable'>".$key; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $item['name'].$counter); - } else + $item['customdrawcell']($this, $item, $itemvalue, true, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + } echo "</td>"; $key = ""; } @@ -191,11 +231,21 @@ class HaproxyHtmlList <td class='list'> <table border='0' cellspacing='0' cellpadding='1'><tr> <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' /> + <input name='{$tablename}_rowindex{$counter}' id='{$tablename}_rowindex{$counter}' type='hidden' value='{$counter}' /> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow({$counter}, \"{$tablename}\"); return false;' /> </td> <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> - </td></tr></table> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + if (empty($this->keyfield)) { + echo "<td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_up.gif' title='move row up' width='17' height='17' border='0' onclick='moveRowUp({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_down.gif' title='move row down' width='17' height='17' border='0' onclick='moveRowDown({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + } + echo "</tr></table> </td>"; echo "</tr>"; if (isset($itemdetails)) { @@ -204,7 +254,7 @@ class HaproxyHtmlList ?> <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'> <div style="position:relative;float:right;width:11px;height:11px;"> - <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')"> + <a onclick="htmltable_toggle_details('<?=$tablename?>','<?=$counter?>','<?="htmltable_{$tablename}_{$counter}_details"?>')"> <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings" src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/> </a> @@ -215,80 +265,92 @@ class HaproxyHtmlList $itemnr = 0; echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>"; $itemcount = count($itemdetails); + $leftitem = true; foreach($itemdetails as $item) { - echo "<div style='float: left;padding-right: 2px;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo $item['columnheader'] . ": "; $itemname = $item['name']; $itemvalue = $value[$itemname]; + //TODO don't filter empty items, filter context un-related items through customizable function.. + if (empty($itemvalue)) { + continue; + } + echo "<div style='float: left;padding-right: 2px;'>"; + $tdclass = ""; + if (!$leftitem) { + echo ", "; + } + $leftitem = false; + echo $item['columnheader'] . ": "; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); - } else + $item['customdrawcell']($this, $item, $itemvalue, false, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); - $leftitem = false; + } $itemnr++; - if ($itemcount != $itemnr) - echo ", "; echo "</div>"; } echo "</div>"; echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>"; echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >"; - $leftitem = true; foreach($itemdetails as $item) { - echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo "<td style='border-right:0' class='$tdclass'>"; + $itemname = $item['name']; + echo "<tr id='tr_edititemdetails_{$counter}_{$itemname}'>"; + echo "<td style='border-right:0'>"; echo "{$item['columnheader']}: "; echo "</td>"; - echo "<td style='border-left:0' class='$tdclass'>"; - $itemname = $item['name']; + echo "<td style='border-left:0'>"; $itemvalue = $value[$itemname]; - echo "{$item['description']}<br/>"; + + if (!empty($item['description'])) { + echo "{$item['description']}<br/>"; + } if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $itemname . $counter); - } else + $item['customdrawcell']($this, $item, $itemvalue, true, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + } echo "</td>"; - $leftitem = false; - echo "</tr>"; + echo "</tr>"; } echo "</table>"; echo "</div>"; echo "</td>"; echo "</tr>"; } - if (isset($itemdetails)) { - $colspan = count($items)-1; - echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >"; - echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>"; - echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; - echo "</td>"; - echo "</tr>"; - } - $counter++; } } - echo "</table> - <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'> + echo "</tbody> + </table> + <a onclick='javascript:addRowTo(\"{$tablename}\"); return false;' href='#'> <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' /> </a>"; } } +function sort_index(&$a, &$b) { + // sort callback function, cannot be inside the object. + if ($a['_index'] != $b['_index']) { + return $a['_index'] > $b['_index'] ? 1 : -1; + } + return 0; +} + function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){ $list = new HaproxyHtmlList($tablename, $items); $list->haproxy_htmllist($rowvalues, $items, $editstate, $itemdetails); } -function haproxy_htmllist_get_values($html_list){ - $list = new HaproxyHtmlList("-", $html_list); +function haproxy_htmllist_get_values($tablename, $html_list){ + $list = new HaproxyHtmlList($tablename, $html_list); return $list->haproxy_htmllist_get_values(); } function haproxy_htmllist_js(){ + global $g; ?><script type="text/javascript"> + + var theme = "<?=$g['theme']?>"; + function html_listitem_change(tableId, fieldId, rowNr, field) { javascript_event = tableId + "_listitem_change"; var fn = window[javascript_event]; @@ -297,61 +359,73 @@ function haproxy_htmllist_js(){ } } - function htmllist_get_select_items(prefix,tableId) { + function htmllist_get_select_items(prefix, tableId) { var items; - var i = tableId.lastIndexOf('_'); - var items_name = prefix+"_"+tableId.substr(i+1); - items = eval("typeof "+items_name+" !== 'undefined' ? "+items_name+" : {}"); + var items_name = prefix+"_"+tableId; + items = eval("typeof "+items_name+" !== 'undefined' ? "+items_name+" : null"); return items; } + function createFieldHtml(tableId, field, rowId) { + var result = ""; + if(field['type'] == 'textbox') { + result="<input size='" + field['size'] + "' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + + "'><\/input> "; + } else if(field['type'] == 'textarea') { + result="<textarea cols='" + field['size'] + "' rows='30' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + + "'><\/textarea> "; + } else if(field['type'] == 'select') { + var seltext = ""; + var fieldid = field['name']; + var fn = window["htmllist_get_select_options"]; + fielditems = field['items']; + if (typeof fn === 'function'){ + fielditems = htmllist_get_select_options(tableId, field['name'], fielditems); + } + for (var fieldvalueid in fielditems) { + var fieldvalue = fielditems[fieldvalueid] + seltext += "<option value='"+fieldvalueid+"'>"+fieldvalue['name']+"<\/option>"; + } + + result="<select style='width:" + field['size'] + "' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + "' "+ + "onchange='html_listitem_change(\""+tableId+"\",\""+field['name']+"\",\""+rowId+"\",this);' " + + ">" + seltext + "<\/select> "; + } else if(field['type'] == 'fixedtext') { + result=field['text']; + } else { + result="<input type='checkbox' name='" + tableId + field['name'] + rowId +"'"+ + "id='" + tableId + field['name'] + rowId + "' "+ + "onclick='html_listitem_change(\""+tableId+"\",\""+field['name']+"\",\""+rowId+"\",this);' " + + "value='yes'><\/input> "; + } + return result; + } + var addRowTo = (function() { return (function (tableId) { var d, tbody, tr, td, bgc, i, ii, j, type, seltext, items; var btable, btbody, btr, btd; d = document; - items = htmllist_get_select_items('fields',tableId); - tbody = d.getElementById(tableId).getElementsByTagName("tbody").item(0); - tr = d.createElement("tr"); totalrows++; - tr.setAttribute("id","aclrow" + totalrows); - + + // create edit row fields + items = htmllist_get_select_items('fields',tableId); + tr = d.createElement("tr"); + tr.setAttribute("id","tr_edit_" + totalrows); for (var i in items) { + fieldhtml = createFieldHtml(tableId, items[i], totalrows); td = d.createElement("td"); - if(items[i]['type'] == 'textbox') { - td.innerHTML="<input size='" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/input> "; - } else if(items[i]['type'] == 'textarea') { - td.innerHTML="<textarea cols='" + items[i]['size'] + "' rows='30' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/textarea> "; - } else if(items[i]['type'] == 'select') { - seltext = htmllist_get_select_options(tableId, items[i]['name']); - td.innerHTML="<select style='width:" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + "' "+ - "onchange='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + - ">" + seltext + "<\/select> "; - } else { - td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +"'"+ - "id='" + items[i]['name'] + totalrows + "' "+ - "onclick='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + - "value='yes'><\/input> "; - } + td.innerHTML = fieldhtml; tr.appendChild(td); } td = d.createElement("td"); td.rowSpan = "1"; td.setAttribute("class","list"); - - items = htmllist_get_select_items('fields_details',tableId); - for (var i in items) { - td.innerHTML=td.innerHTML+"<input type='hidden' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/input> "; - } // Recreate the button table. btable = document.createElement("table"); @@ -360,20 +434,69 @@ function haproxy_htmllist_js(){ btable.setAttribute("cellpadding", "1"); btbody = document.createElement("tbody"); btr = document.createElement("tr"); + btd = document.createElement("td"); btd.setAttribute("valign", "middle"); - btd.innerHTML = '<img src="/themes/' + theme + '/images/icons/icon_x.gif" title="delete entry" width="17" height="17" border="0" onclick="removeRow(this); return false;" />'; + btd.innerHTML = + '<input name="'+tableId+'_rowindex'+totalrows+'" id="'+tableId+'_rowindex'+totalrows+'" type="hidden" value="'+totalrows+'" />' + + '<img src="/themes/' + theme + '/images/icons/icon_x.gif" title="delete entry" width="17" height="17" border="0" onclick="deleteRow(' + totalrows + ", '" + tableId + "'); return false;\" />"; btr.appendChild(btd); + btd = document.createElement("td"); btd.setAttribute("valign", "middle"); btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_plus.gif\" title=\"duplicate entry\" width=\"17\" height=\"17\" border=\"0\" onclick=\"dupRow(" + totalrows + ", '" + tableId + "'); return false;\" />"; btr.appendChild(btd); + + + var tabledefinition = htmllist_get_select_items("tabledefinition", tableId); + if (tabledefinition && tabledefinition['keyfield'] == "") { + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_up.gif\" title=\"move entry up\" width=\"17\" height=\"17\" border=\"0\" onclick=\"moveRowUp(" + totalrows + ", '" + tableId + "'); return false;\" />"; + btr.appendChild(btd); + + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_down.gif\" title=\"move entry down\" width=\"17\" height=\"17\" border=\"0\" onclick=\"moveRowDown(" + totalrows + ", '" + tableId + "'); return false;\" />"; + btr.appendChild(btd); + } + btbody.appendChild(btr); btable.appendChild(btbody); td.appendChild(btable); tr.appendChild(td); - tbody.appendChild(tr); - + tbody.appendChild(tr); // add the edit row to the table + + // create viewdetail row + items = htmllist_get_select_items('fields_details',tableId); + if (items) { + tr = d.createElement("tr"); + tr.setAttribute("id","tr_viewdetail_" + totalrows); + td = d.createElement("td"); + tr.appendChild(td); + td = d.createElement("td"); + table = d.createElement("table"); + for (var i in items) { + field = items[i]; + fieldhtml = createFieldHtml(tableId, field, totalrows); + subtr = d.createElement("tr"); + subtr.setAttribute("id","tr_edititemdetails_" + totalrows + "_" + field['name']); + subtd = d.createElement("td"); + subtd.innerHTML = field['columnheader'] + ": " + fieldhtml; + subtr.appendChild(subtd); + table.appendChild(subtr); + } + td.appendChild(table); + tr.appendChild(td); + tbody.appendChild(tr); // add the viewdetail row to the table + } + // show/hide conditional fields if applicable using a custom function. + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, "toggle_details", totalrows, null); + } + javascript_row_added = tableId + "_row_added"; var fn = window[javascript_row_added]; if (typeof fn === 'function'){ @@ -387,18 +510,18 @@ function haproxy_htmllist_js(){ addRowTo(tableId); items = htmllist_get_select_items('fields',tableId); for (var i in items) { - dupEl = document.getElementById(items[i]['name'] + rowId); - newEl = document.getElementById(items[i]['name'] + totalrows); + dupEl = document.getElementById(tableId + items[i]['name'] + rowId); + newEl = document.getElementById(tableId + items[i]['name'] + totalrows); if (dupEl && newEl) if(items[i]['type'] == 'checkbox') newEl.checked = dupEl.checked; else newEl.value = dupEl.value; } - items = htmllist_get_select_items('fields_details',tableId); + items = htmllist_get_select_items('fields_details', tableId); for (var i in items) { - dupEl = document.getElementById(items[i]['name'] + rowId); - newEl = document.getElementById(items[i]['name'] + totalrows); + dupEl = document.getElementById(tableId + items[i]['name'] + rowId); + newEl = document.getElementById(tableId + items[i]['name'] + totalrows); if (dupEl && newEl) if(items[i]['type'] == 'checkbox') newEl.value = dupEl.checked ? 'yes' : ''; @@ -428,21 +551,89 @@ function haproxy_htmllist_js(){ if (edit) edit.parentNode.removeChild(edit); } - function removeRow(el) { - var cel; - // Break out of one table first - while (el && el.nodeName.toLowerCase() != "table") - el = el.parentNode; - while (el && el.nodeName.toLowerCase() != "tr") - el = el.parentNode; - if (el && el.parentNode) { - cel = el.getElementsByTagName("td").item(0); - el.parentNode.removeChild(el); + function moveRowUp(rowId, tableId) { + moveRow(rowId, tableId, true); + } + function moveRowDown(rowId, tableId) { + moveRow(rowId, tableId, false); + } + function moveRow(rowId, tableId, up) { + var rowview = document.getElementById("tr_view_" + rowId); + var rowedit = document.getElementById("tr_edit_" + rowId); + var rowviewdetail = document.getElementById("tr_viewdetail_" + rowId); + + var parent = rowedit.parentNode; + var swapid; + var swaprowedit; + if (up){ + //move current rows before the previous row + var prevtr; + if (rowview) { + prevtr = rowview.previousElementSibling; + } else { + prevtr = rowedit.previousElementSibling; + } + if (!prevtr) + return; // was already top element. + var swapid = prevtr['id']; + var i = swapid.lastIndexOf('_'); + swapid = swapid.substr(i+1); + var prevrowview = document.getElementById("tr_view_" + swapid); + swaprowedit = document.getElementById("tr_edit_" + swapid); + if (prevrowview){ + firstprevrow = prevrowview; + } else { + firstprevrow = swaprowedit; + } + // move the 3 rows + if (rowview) { + parent.insertBefore(rowview, firstprevrow); + } + parent.insertBefore(rowedit, firstprevrow); + if (rowviewdetail) { + parent.insertBefore(rowviewdetail, firstprevrow); + } + } else { + //move next row before the current row + var nexttr; + if (rowviewdetail) { + nexttr = rowviewdetail.nextElementSibling; + } else { + nexttr = rowedit.nextElementSibling; + } + if (!nexttr) { + return; // was already bottom element. + } + var swapid = nexttr['id']; + var i = swapid.lastIndexOf('_'); + swapid = swapid.substr(i+1); + var prevrowview = document.getElementById("tr_view_" + swapid); + swaprowedit = document.getElementById("tr_edit_" + swapid); + var prevrowviewdetail = document.getElementById("tr_viewdetail_" + swapid); + if (rowview){ + firstrow = rowview; + } else { + firstrow = rowedit; + } + // move the 3 rows + if (prevrowview) { + parent.insertBefore(prevrowview, firstrow); + } + parent.insertBefore(swaprowedit, firstrow); + if (prevrowviewdetail) { + parent.insertBefore(prevrowviewdetail, firstrow); + } } + + var id_a = document.getElementById(tableId+'_rowindex' + swapid); + var id_b = document.getElementById(tableId+'_rowindex' + rowId); + temp = id_a.value; + id_a.value = id_b.value; + id_b.value = temp; } - function htmltable_toggle_details(table_row_detail_id) { + function htmltable_toggle_details(tableId, rowNr, table_row_detail_id) { tredit = document.getElementById(table_row_detail_id+'_off'); trviewdetail = document.getElementById(table_row_detail_id+'_edit'); treditdetail = document.getElementById(table_row_detail_id+'_view'); @@ -450,6 +641,13 @@ function haproxy_htmllist_js(){ tredit.style.display=current_on ? '' : 'none'; trviewdetail.style.display=current_on ? 'none' : ''; treditdetail.style.display=current_on ? '' : 'none'; + + // show/hide conditional fields if applicable using a custom function. + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, "toggle_details", rowNr, null); + } } </script><? } diff --git a/config/haproxy-devel/pkg/haproxy_upgrade_config.inc b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc index c1c951df..58e66852 100644 --- a/config/haproxy-devel/pkg/haproxy_upgrade_config.inc +++ b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc @@ -1,6 +1,6 @@ <?php /* - haproxy.inc + haproxy_upgrade_config.inc Copyright (C) 2015 PiBa-NL All rights reserved. @@ -26,7 +26,9 @@ POSSIBILITY OF SUCH DAMAGE. */ +require_once("haproxy_utils.inc"); require_once("pkg-utils.inc"); +require_once("haproxy.inc"); function haproxy_upgrade_config() { global $config, $static_output; @@ -193,6 +195,75 @@ function haproxy_upgrade_config() { } $configversion = "00.19"; } + if ($configversion < "00.32") { + $frontends = array(); + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) { + $primaryfrontend = get_primaryfrontend($frontend); + $fe_name = $primaryfrontend['name']; + $frontends[$fe_name][] = &$frontend; + } + + foreach ($frontends as $primary) { + $acl_count = array(); + foreach ($primary as &$frontend){ + $acl_use = array(); + $a_actions = &$frontend['a_actionitems']['item']; + if (!is_array($a_actions)) { + $a_actions = array(); + } + + $primaryfrontend = get_primaryfrontend($frontend); + $frontendtype = $primaryfrontend['type']; + $is_default = true; + if (is_array($frontend['ha_acls']['item'])) { + $a_acl = &$frontend['ha_acls']['item']; + + foreach ($a_acl as &$aclitem) { + $aclname = $aclitem['name']; + $acltype = haproxy_find_acl($aclitem['expression']); + if ($aclitem['expression'] == "backendservercount") { + $aclitem['backendservercountbackend'] = $frontend['backend_serverpool']; + } + if (!isset($acl_count[$aclname])) { + $acl_count[$aclname] = 1; + } else { + $acl_count[$aclname] += 1; + $aclitem['name'] .= "_{$acl_count[$aclname]}"; + } + if (!isset($acltype)) + continue; + if ($acltype['mode'] != '' && $acltype['mode'] != strtolower($frontendtype)) { + continue; + } + $acl_use[$aclname][] = $aclitem['name']; + } + foreach ($acl_use as $key => $acl_x) { + $aclx = $acl_count[$key]; + $aclnames = ""; + foreach($acl_x as $aclname) { + $aclnames .= " $aclname"; + } + $aclnames = trim($aclnames); + $action['action'] = 'use_backend'; + $action['use_backendbackend'] = $frontend['backend_serverpool']; + $action['acl'] = $aclnames; + $a_actions[] = $action; + $is_default = false; + } + } + if (!$is_default) { + /* + // default backends still exist ;) no need to convert them to 'actions'. + $action['action'] = 'use_backend'; + $action['use_backendbackend'] = $frontend['backend_serverpool']; + $action['acl'] = ""; // default backend has no acl + $a_actions[] = $action;*/ + $frontend['backend_serverpool'] = ""; + } + } + } + $configversion = "00.32"; + } $writeconfigupdate = $config['installedpackages']['haproxy']['configversion'] <> $configversion; if ($writeconfigupdate) { diff --git a/config/haproxy-devel/pkg/haproxy_utils.inc b/config/haproxy-devel/pkg/haproxy_utils.inc index ec72b986..04cacb30 100644 --- a/config/haproxy-devel/pkg/haproxy_utils.inc +++ b/config/haproxy-devel/pkg/haproxy_utils.inc @@ -122,11 +122,11 @@ function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,l // $bindable[key]['description'] can be shown to user in a selection box global $config; - $ipverions = split(',',$ipv); + $ipversions = split(',',$ipv); $interfacetypes= split(',',$interfacetype); $bindable = array(); - if (in_array("ipv4",$ipverions)){ + if (in_array("ipv4",$ipversions)){ if (in_array('any',$interfacetypes)){ $item = array(); $item[ip] = '0.0.0.0'; @@ -187,7 +187,7 @@ function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,l if (!isset($config['system']['ipv6allow'])) return $bindable;// skip adding the IPv6 addresses if those are not 'allowed' - if (in_array("ipv6",$ipverions)){ + if (in_array("ipv6",$ipversions)){ if (in_array('any',$interfacetypes)){ $item = array(); $item[ip] = '::'; @@ -386,6 +386,27 @@ function haproxy_get_certificates($type = 'server,user', $get_includeWebCert=fal return $certificates; } +function haproxy_get_certificate_subjectAltNames($str_crt, $decode = true) { + if ($decode) { + $str_crt = base64_decode($str_crt); + } + $result = array(); + $ext = openssl_x509_parse($str_crt, false); + $subjectAltName = $ext['extensions']['subjectAltName']; + $lines = explode('\n', $subjectAltName); + foreach($lines as $line) { + $items = explode(',', $line); + foreach($items as $item) { + $item = trim($item); + if (strpos($item, "DNS:") === 0) { + $DNSitem = substr($item, 4); + $result[] = $DNSitem; + } + } + } + return $result; +} + function haproxy_get_crls() { global $config; $certificates=array(); @@ -406,7 +427,8 @@ function haproxy_get_crls() { function phparray_to_javascriptarray_recursive($nestID, $path, $items, $nodeName, $includeitems) { $offset = str_repeat(' ',$nestID); $itemName = "item$nestID"; - echo "{$offset}$nodeName = {};\n"; + //echo "{$offset}$nodeName = {};\n"; + echo "{$offset}$nodeName = Object.create(null);\n"; if (is_array($items)) foreach ($items as $key => $item) { |