$section->addInput(new Form_Select('protocol', 'Protocol', $pconfig['protocol'], array_combine(explode(" ", strtolower($protocols)), explode(" ", $protocols))))->setHelp('Choose which protocol this rule should match. In most cases "any" is specified.');
$group = new Form_Group('Source');
$group->add(new Form_Select('source_type', null, $pconfig['source'] == "any" || $pconfig['source'] == "(self)" ? $pconfig['source'] : "network", array('any' => gettext('Any'), '(self)' => gettext('This Firewall (self)'), 'network' => gettext('Network'))))->setHelp('Type')->setWidth('3');
$group->add(new Form_IpAddress('source', null, $pconfig['source']))->addMask('source_subnet', $pconfig['source_subnet'])->setHelp('Source network for the outbound NAT mapping.')->setPattern('[a-zA-Z0-9\\_\\.\\:]+');
$group->add(new Form_Input('sourceport', null, 'text', $pconfig['sourceport']))->setHelp('Port')->setWidth('2');
$section->add($group);
$group = new Form_Group('Destination');
$group->add(new Form_Select('destination_type', null, $pconfig['destination'] == "any" ? "any" : "network", array('any' => gettext('Any'), 'network' => gettext('Network'))))->setHelp('Type')->setWidth('3');
$group->add(new Form_IpAddress('destination', null, $pconfig['destination'] == "any" ? "" : $pconfig['destination']))->addMask('destination_subnet', $pconfig['destination_subnet'])->setHelp('Destination network for the outbound NAT mapping.')->setPattern('[a-zA-Z0-9\\_\\.\\:]+');
$group->add(new Form_Input('dstport', null, 'text', $pconfig['dstport']))->setHelp('Port')->setWidth('2');
$section->add($group);
$section->addInput(new Form_Checkbox('destination_not', null, 'Not', $pconfig['destination_not']))->setHelp('Invert the sense of the destination match.');
$form->add($section);
$section = new Form_Section('Translation');
$section->addClass('translation');
$section->addInput(new Form_Select('target', 'Address', $pconfig['target'], build_target_list()));
$section->addInput(new Form_IpAddress('targetip', 'Other subnet', $pconfig['targetip']))->addMask('targetip_subnet', $pconfig['targetip_subnet'])->addClass('othersubnet')->setHelp('Packets matching this rule will be mapped to the IP address given here.' . '<br />' . 'To apply this rule to a different IP address than the IP address of the interface chosen above, ' . 'select it here (' . '<a href="firewall_virtual_ip.php">' . gettext("Virtual IP") . '</a> ' . 'addresses need to be defined on the interface first)');
$section->addInput(new Form_Select('poolopts', 'Pool options', $pconfig['poolopts'], array('' => gettext('Default'), 'round-robin' => gettext('Round Robin'), 'round-robin sticky-address' => gettext('Round Robin with Sticky Address'), 'random' => gettext('Random'), 'random sticky-address' => gettext('Random with Sticky Address'), 'source-hash' => gettext('Source hash'), 'bitmask' => gettext('Bit mask'))))->setHelp('Only Round Robin types work with Host Aliases. Any type can be used with a Subnet.' . '<br />' . '</span><ul class="help-block">' . '<li>' . 'Round Robin: Loops through the translation addresses.' . '</li>' . '<li>' . 'Random: Selects an address from the translation address pool at random.' . '</li>' . '<li>' . 'Source Hash: Uses a hash of the source address to determine the translation address, ensuring that the redirection address is always the same for a given source.' . '</li>' . '<li>' . 'Bitmask: Applies the subnet mask and keeps the last portion identical; 10.0.1.50 -&gt; x.x.x.50.' . '</li>' . '<li>' . 'Sticky Address: The Sticky Address option can be used with the Random and Round Robin pool types to ensure that a particular source address is always mapped to the same translation address.' . '</li>' . '</ul><span class="help-block">');
$group = new Form_Group('Port');
$group->addClass('natportgrp');
$group->add(new Form_Input('natport', null, 'text', $pconfig['natport']))->setHelp('Enter the source port or range for the outbound NAT mapping.');
$group->add(new Form_Checkbox('staticnatport', null, 'Static port', $pconfig['staticnatport']));
$section->add($group);
$form->add($section);
$section = new Form_Section('Misc');
$section->addInput(new Form_Checkbox('nosync', 'No XMLRPC Sync', null, $pconfig['nosync'], 'yes'))->setHelp('Prevents the rule on Master from automatically syncing to other CARP members. ' . 'This does NOT prevent the rule from being overwritten on Slave.');
$section->addInput(new Form_Input('descr', 'Description', 'text', $pconfig['descr']))->setHelp('A description may be entered here for administrative reference (not parsed).');
if (isset($id) && $a_out[$id]) {
    $section->addInput(new Form_Input('id', null, 'hidden', $id));
}
$section->addInput(new Form_Input('after', null, 'hidden', $after));
$section->addInput(new Form_Select('protocol', 'Protocol', $pconfig['protocol'], array_combine(explode(" ", strtolower($protocols)), explode(" ", $protocols))))->setHelp('Choose which protocol this rule should match. In most cases "any" is specified.');
$group = new Form_Group('Source');
$group->add(new Form_Select('source_type', null, $pconfig['source'] == "any" || $pconfig['source'] == "(self)" ? $pconfig['source'] : "network", array('any' => gettext('Any'), '(self)' => gettext('This Firewall (self)'), 'network' => gettext('Network'))))->setHelp('Type')->setWidth('3');
$group->add(new Form_IpAddress('source', null, $pconfig['source']))->addMask('source_subnet', $pconfig['source_subnet'])->setHelp('Source network for the outbound NAT mapping.')->setPattern('[a-zA-Z0-9_.:]+');
$group->add(new Form_Input('sourceport', null, 'text', $pconfig['sourceport']))->setHelp('Port or Range')->setWidth('2');
$section->add($group);
$group = new Form_Group('Destination');
$group->add(new Form_Select('destination_type', null, $pconfig['destination'] == "any" ? "any" : "network", array('any' => gettext('Any'), 'network' => gettext('Network'))))->setHelp('Type')->setWidth('3');
$group->add(new Form_IpAddress('destination', null, $pconfig['destination'] == "any" ? "" : $pconfig['destination']))->addMask('destination_subnet', $pconfig['destination_subnet'])->setHelp('Destination network for the outbound NAT mapping.')->setPattern('[a-zA-Z0-9_.:]+');
$group->add(new Form_Input('dstport', null, 'text', $pconfig['dstport']))->setHelp('Port or Range')->setWidth('2');
$section->add($group);
$section->addInput(new Form_Checkbox('destination_not', null, 'Not', $pconfig['destination_not']))->setHelp('Invert the sense of the destination match.');
$form->add($section);
$section = new Form_Section('Translation');
$section->addClass('translation');
$section->addInput(new Form_Select('target', 'Address', $pconfig['target'], build_target_list()))->setHelp('Connections matching this rule will be mapped to the specified <b>Address</b>.' . '<br />' . 'The <b>Address</b> can be an Interface, a Host-type Alias, or a ' . '<a href="firewall_virtual_ip.php">' . gettext("Virtual IP") . '</a> ' . ' address.');
$section->addInput(new Form_IpAddress('targetip', 'Other subnet', $pconfig['targetip']))->addMask('targetip_subnet', $pconfig['targetip_subnet'])->setHelp('This subnet must be routed to the firewall or each address in the subnet must be defined in one or more ' . '<a href="firewall_virtual_ip.php">' . gettext("Virtual IP") . '</a> ' . ' addresses.');
$section->addInput(new Form_Select('poolopts', 'Pool options', $pconfig['poolopts'], array('' => gettext('Default'), 'round-robin' => gettext('Round Robin'), 'round-robin sticky-address' => gettext('Round Robin with Sticky Address'), 'random' => gettext('Random'), 'random sticky-address' => gettext('Random with Sticky Address'), 'source-hash' => gettext('Source hash'), 'bitmask' => gettext('Bit mask'))))->setHelp('Only Round Robin types work with Host Aliases. Any type can be used with a Subnet.' . '<br />' . '</span><ul class="help-block">' . '<li>' . 'Round Robin: Loops through the translation addresses.' . '</li>' . '<li>' . 'Random: Selects an address from the translation address pool at random.' . '</li>' . '<li>' . 'Source Hash: Uses a hash of the source address to determine the translation address, ensuring that the redirection address is always the same for a given source.' . '</li>' . '<li>' . 'Bitmask: Applies the subnet mask and keeps the last portion identical; 10.0.1.50 -&gt; x.x.x.50.' . '</li>' . '<li>' . 'Sticky Address: The Sticky Address option can be used with the Random and Round Robin pool types to ensure that a particular source address is always mapped to the same translation address.' . '</li>' . '</ul><span class="help-block">');
$section->addInput(new Form_Input('source_hash_key', 'Source Hash Key', 'text', $pconfig['source_hash_key']))->setHelp('The key that is fed to the hashing algorithm in hex format, preceeded by "0x", or any string. A non-hex string is hashed using md5 to a hexadecimal key. Defaults to a randomly generated value.')->setWidth(10);
$group = new Form_Group('Port or Range');
$group->addClass('natportgrp');
$group->add(new Form_Input('natport', null, 'text', $pconfig['natport']))->setHelp('Enter the external source <b>Port or Range</b> used for remapping ' . 'the original source port on connections matching the rule. <br/><br/>' . 'Port ranges are a low port and high port number separated by ":".<br/>' . 'Leave blank when <b>Static Port</b> is checked.');
$group->add(new Form_Checkbox('staticnatport', null, 'Static Port', $pconfig['staticnatport']));
$section->add($group);
$form->add($section);
$section = new Form_Section('Misc');
$section->addInput(new Form_Checkbox('nosync', 'No XMLRPC Sync', null, $pconfig['nosync'], 'yes'))->setHelp('Prevents the rule on Master from automatically syncing to other CARP members. ' . 'This does NOT prevent the rule from being overwritten on Slave.');
$section->addInput(new Form_Input('descr', 'Description', 'text', $pconfig['descr']))->setHelp('A description may be entered here for administrative reference (not parsed).');
if (isset($id) && $a_out[$id]) {
    $section->addInput(new Form_Input('id', null, 'hidden', $id));
}