var old_octet = ['', '', '', ''];
var selected = null;
var current_ns_element = null;
var current_ns_function = null;
var IE=0, NS=0;
var blnDOM = false, blnIE4 = false, blnNN4 = false;
var popup_window;
var temp_popup_window; // PopUp Window that will close when the page is changed

// Detect the browser
IE  = (-1 != navigator.appVersion.indexOf("MSIE")) ? 1 : 0;
NS  = ("Netscape" == navigator.appName) ? 1 : 0;

if (document.getElementById) blnDOM = true;
else if (document.layers) { blnNN4 = true;}
else if (document.all) blnIE4 = true;

document.onkeypress = ns_keypresscheck;
document.onkeydown = ns_keydowncheck;
document.onkeyup = ns_keyupcheck;

function encode_url (sUrl) {
    return escape(sUrl).replace(/\+/g, '%2C').replace(/\"/g, '%22').replace(/\'/g, '%27');
}

function backup_test_popup() {
    new_window=window.open("/cgi-bin/backup_test.cgi");
    if (new_window && window.focus) {
        new_window.focus();
    }
    return false;
}

// put the focus in the user input field if it's empty
// otherwise, do not change the focus
function focus_on_empty(input_obj) {
    if(!input_obj.value) {
        input_obj.focus();
    }
}

function popup(primary_tab, secondary_tab, width, height) {
    // All vars past secondary tab are 'key', 'value' pairs.
    // 'key' is what you want passed to the popup.
    // 'value' is either the value you want passed, or the name of the form
    // element you want interpolated to have its value passed.  (prepend
    // interpolated vars with __)

    var args = [];

    // width and height are optional and numeric keys aren't allowed.
    if (typeof width == 'number') {
        w = width;
        h = height;
    } else {
        w = 750;
        h = 520;
    }
    
    for (var i = 0; i < arguments.length; i++) {
        args[i] = arguments[i];
    }
    args.push(
        'user', '__user',
        'password', '__password',
        'et', '__et',
        'locale', '__locale'
    );
    var variables = [];
    for (var i = 2; i < args.length; i += 2) {
        if (typeof args[i] == 'number') {
            continue;
        }
        if (args[i+1].substring(0,2) == '__') {
            // Removes leading __ (substr from pos 2 - end)
            var arg = args[i+1].substring(2,args[i+1].length);
            var value;
            for (var j=0; j < document.f.elements.length; j++) {
                if (document.f.elements[j].name == arg) {
                   variables[i] = escape(args[i]) + '=' + escape(document.f.elements[j].value) ;
                }
            }
        } else {
            variables[i] = escape(args[i]) + '=' + escape(args[i+1]);
        }
    }
    variables.unshift(
        "/cgi-bin/index.cgi?",
        "primary_tab=" + primary_tab,
        "secondary_tab=" + secondary_tab,
        "content_only=1"
    )
    var href_string = variables.join('&');
    ex_open_popup_window(href_string, w, h, "", "", 0, 0);
    return false;
}

function ldap_test_popup(domain, row) {
  var email = '';
  var host = '';
  var port = '';
  var tls_mode = '';
  var tls_require = '';
  var username = '';
  var pass = '';
  var filter = '';
  var domain = '';
  var searchbase = '';
  var unique_attr = '';
  var email_attr = '';
  for (var i=0; i<document.f.elements.length; i++) {
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_email:"+row) {
      email = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_host:"+row) {
      host = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_port:"+row) {
      port = document.f.elements[i].value;
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_tls_mode:"+row && document.f.elements[i].checked == true) {
      tls_mode = document.f.elements[i].value;
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_tls_require:"+row && document.f.elements[i].checked == true) {
      tls_require = document.f.elements[i].value;
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_username:"+row) {
      username = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_password:"+row) {
      pass = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_filter:"+row) {
      filter = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_domain:"+row) {
      domain = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_searchbase:"+row) {
      searchbase = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_unique_attr:"+row) {
      unique_attr = escape(document.f.elements[i].value);
    }
    if (document.f.elements[i].name == "UPDATE_mta_ldap_advanced_email_attr:"+row) {
      email_attr = escape(document.f.elements[i].value);
    }
  }
  new_window=window.open("/cgi-bin/ldap_test.cgi?host="+host+"&port="+port+"&tls_mode="+tls_mode+"&tls_require="+tls_require+"&username="+username+"&password="+pass+"&filter="+filter+"&searchbase="+searchbase+"&unique_attr="+unique_attr+"&email_attr="+email_attr+"&domain="+domain+"&email="+email, "ldap_test", "width=600,height=500");
  if (new_window && window.focus) {
    new_window.focus();
  }
  return false;
}

function confirm_ldap_test() {
  if (!confirm('Please confirm that you have successfully tested the LDAP configuration by pressing the test button at the end of this row')) {
    return false;
  }
  else {
    return true;
  }
}

/**
 * This is used to create a new browsing window which contains the smtp
 * testing cgi script. It takes several parameters from the document currently
 * being viewed and passes these as URL parameters to the script.
 */
function smtp_test_popup(domain, row, hostname, default_domain, locale, user, password, et) {
  var email = '';
  var host = '';
  var port = '';
  var use_mx = 0;
  for (var i=0; i<document.f.elements.length; i++) {
    // Get the email address
    if (document.f.elements[i].name == "UPDATE_mta_relay_advanced_email:" + row ||
        document.f.elements[i].name == "UPDATE_mta_outbound_relay_email:" + row) {

        email = document.f.elements[i].value;
    }

    // Get the host
    if (document.f.elements[i].name == "UPDATE_mta_relay_advanced_host:" + row ||
        document.f.elements[i].name == "UPDATE_mta_outbound_relay_host:" + row) {

        host = document.f.elements[i].value;
    }

    // Get the port
    if (document.f.elements[i].name == "UPDATE_mta_relay_advanced_port:" + row ||
        document.f.elements[i].name == "UPDATE_mta_outbound_relay_port:" + row) {

        port = document.f.elements[i].value;
    }

    // Use MX lookup?
    if (document.f.elements[i].name == "UPDATE_mta_relay_advanced_use_mx:" + row &&
        document.f.elements[i].value == "Yes" &&
        document.f.elements[i].checked) {
        use_mx = 1;
    }
  }

  // Create the popup window
  new_window=window.open("/cgi-bin/smtp_test.cgi?locale="+locale+"&host="+host+"&port="+port+"&domain="+domain+"&email="+email+"&hostname="+hostname+"&default_domain="+default_domain+"&user="+user+"&password="+password+"&et="+et+"&use_mx="+use_mx, "smtp_test", "width=600,height=550");

  // Focus the new window
  if (new_window && window.focus) {
    new_window.focus();
  }
  
  return false;
}

function basic_smtp_test_popup(domain, email, hostname, default_domain, locale, user, password, et) {
  var host = '';
  var port = '';
  for (var i=0; i<document.f.elements.length; i++) {
    if (document.f.elements[i].name == "UPDATE_mta_relay_host") {
      host = document.f.elements[i].value;
    }
    if (document.f.elements[i].name == "UPDATE_mta_relay_email") {
      email = document.f.elements[i].value;
    }
    if (document.f.elements[i].name == "UPDATE_mta_relay_port") {
      port = document.f.elements[i].value;
    }
  }
  new_window=window.open("/cgi-bin/smtp_test.cgi?locale="+locale+"&host="+host+"&port="+port+"&domain="+domain+"&email="+email+"&hostname="+hostname+"&default_domain="+default_domain+"&user="+user+"&password="+password+"&et="+et, "smtp_test", "width=600,height=550");
  if (new_window && window.focus) {
    new_window.focus();
  }
  return false;
}

function block_ip(ip) {
  window.open('/cgi-bin/index.cgi?primary_tab=BLOCK/ACCEPT&secondary_tab=IP%20Block%2FAccept&UPDATE_new_mta_acl_ip_block_address='+ip+'&UPDATE_new_mta_acl_ip_block_netmask=255.255.255.255&UPDATE_new_mta_acl_ip_block_action=Block&add_mta_acl_ip_block_address=Add', '_top');
}
function unblock_ip(client_whitelist_id) {
  window.open('/cgi-bin/index.cgi?primary_tab=BLOCK/ACCEPT&secondary_tab=IP%20Block%2FAccept&remove_mta_acl_ip_block_address:'+client_whitelist_id+'=Remove', '_top');
}
function whitelist_sender(sender) {
    window.open('/cgi-bin/index.cgi?primary_tab=BLOCK/ACCEPT&secondary_tab=Email%20Sender%20Block%2FAccept&UPDATE_new_mta_acl_email_src_allow_address='+sender+'&add_mta_acl_email_src_allow_address=Add', '_top');
}
function unwhitelist_sender(sender_whitelist_id) {
  window.open('/cgi-bin/index.cgi?primary_tab=BLOCK/ACCEPT&secondary_tab=Email%20Sender%20Block%2FAccept&remove_mta_acl_email_src_allow_address:'+sender_whitelist_id+'=Remove', '_top');
}

function block_ip_error() {
  alert('The IP you wish to unblock is part of a larger blocked subnet.  To unblock just this IP, you must go to the IP Block/Accept page under the BLOCK/ACCEPT tab and break apart the blocked subnet.');
  over_button=1;
}
function fingerprint(id) {
  alert('Message fingerprint has been sent to Barracuda Networks fingerprint server');
  over_button=1;
}
function open_message_detail_window(id, email, locale, machine, port, password, et, realm, secondary_tab) {
  if (over_button==1) {
    over_button=0;
    return;
  }
  message_detail_win = window.open('/cgi-bin/view_message_log_detail.cgi?id='+id+'&user='+email+'&email='+email+'&locale='+locale+'&machine='+machine+'&port='+port+'&password='+password+'&et='+et+'&realm='+realm+'&secondary_tab='+secondary_tab, 'message', 'width=700,height=600,scrollbars=yes,resizable=yes');
  if (window.focus) {
    message_detail_win.focus();
  }
}

function open_bulk_edit_window(user, password, auth_type, realm, et, primary_tab, secondary_tab, varname, locale, limited) {
  ex_open_popup_window('/cgi-bin/bulk_edit.cgi?user='+user+'&password='+password+'&auth_type='+auth_type+'&realm='+realm+'&et='+et+'&locale='+locale+'&bulk_list_var_name='+varname+'&from_primary_tab='+primary_tab+'&from_secondary_tab='+secondary_tab, 600, 500, 'cuda_sf_main','',false,false);
}

function open_popup_window(href) {
  popup_window = window.open(href, 'release_notes', 'width=500,height=500,scrollbars=yes,resizable=yes');
  if (window.focus) {
    popup_window.focus();
  }
}

function ex_open_popup_window(href,w,h,parent_name,page_ref,flag_wait_screen,flag_full) {
  window.name=parent_name;
  if (parent_name){
      var sep='?';
      if (href.indexOf('?')>0){
          sep='&';
      }
      var url=href + sep + 'parent_name=' + parent_name;
  }else{
      var url=href;
  }
  var real_url='';
  var new_window;
  if (page_ref)
    url = url + '#' + page_ref;

  if (flag_wait_screen){
      real_url=url;
      url='about:blank';
  }

  var child_window='child_window'+Math.ceil(Math.random()*1000000);

  var window_options = 'width='+w+',height='+h+',scrollbars=yes,resizable=yes';
  if (flag_full){
      window_options = window_options + ',location=yes,toolbar=yes,menubar=yes,directories=yes'
  }

  if (parent_name){
    temp_popup_window = window.open(url, child_window, 'width='+w+',height='+h+window_options);
    new_window=temp_popup_window;
  } else {
    popup_window = window.open(url, child_window, 'width='+w+',height='+h+window_options);
    new_window=popup_window;
    popup_window.opener = self;
  }

  if (flag_wait_screen){
      var html="<html>";
      html = html + "<body>\n";
      html = html + "<head>\n";
      html = html + "<script>\n";
      html = html + "var cnt=0;\n";
      html = html + "function doDots () { \
                      var dots=''; \
                      cnt++; \
                      for (var i=0;i<cnt;i++){ \
                       dots = dots + '.'; \
                      } \
                      document.getElementById('dots').innerHTML=dots; \
                      setTimeout('doDots()',1000); \
                     }"
      html = html + "</script>\n";
      html = html + "</head>\n";
      html = html + "<table width=100% height=100% border=1 bordercolor=blue><tr><td align=center valign=center>\n";
      html = html + "Please Wait<br><div id=dots></div>\n";
      html = html + "</td></tr></table>\n";
      html = html + "<script>setTimeout('doDots()',1000);</script>\n";
      html = html + "</body>\n";
      html = html + "</html>\n";
      new_window.document.write(html);
      new_window = window.open(real_url, child_window);
  }
}

function close_popup_windows() {
    if ((temp_popup_window) && (temp_popup_window.closed == false) && window.name != temp_popup_window.name) {
        temp_popup_window.window.close();
    }
}

var image_lookup = new Array();
function spam_button_pressed(button_object) {
  // parse the button id
  var log_message_id = button_object.name.substr(button_object.name.lastIndexOf('_')+1);
  // clear all the buttons
  image_lookup['na_button_'+log_message_id].src='/images/na.gif';
  image_lookup['spam_button_'+log_message_id].src='/images/spam.gif';
  image_lookup['notspam_button_'+log_message_id].src='/images/notspam.gif';
  // press our button
  button_object.src = button_object.src.replace('.gif','_pressed.gif');
  var form_element = eval("document.f.spam_"+log_message_id);
  if (button_object.name.indexOf('notspam') > -1) {
    form_element.value = "no";
  }
  else {
    if (button_object.name.indexOf('spam') > -1) {
      form_element.value = "yes";
    }
    else {
      form_element.value = "";
    }
  }
}

function spam_button_hover(button_object) {
  // if we are pressed, dont show hover
  if (button_object.src.indexOf('_pressed') > -1) {
    return;
  }
  if (button_object.src.indexOf('_over') > -1) {
    return;
  }
  // hover
  button_object.src = button_object.src.replace('.gif','_over.gif');
}
function spam_button_nohover(button_object) {
  // if we are hovering, restore
  if (button_object.src.indexOf('_over') > -1) {
    button_object.src = button_object.src.replace('_over.gif','.gif');
  }
}

function ns_keypresscheck(e) {
  if (! current_ns_element) return;
  var form_type = current_ns_function || 'format_octet';
  return eval(form_type + '(current_ns_element, e || event)');
}

function ns_keydowncheck(e) {
  if (! current_ns_element) return;
  var form_type = current_ns_function || 'format_octet';
  return eval(form_type + '(current_ns_element, e || event)');
}

function ns_keyupcheck(e) {
  if (! current_ns_element) return;
  var form_type = current_ns_function || 'format_octet';
  return eval(form_type + '(current_ns_element, e || event)');
}

function format_octet(self, event) {
  // handle input for an octet
  // we can derive the name and number of the ip variable we're manipulating
  //   the format is "name__number"
  var octet = self.value;

  // determine the base name of this ip
  var base_name = self.name.replace(/__[0-9]$/, "");
  // determine our octet number from the base name
  var octet_number = self.name.replace(/^.*__/g, "");
  // determine the next octet
  var next_octet_name;
  var next_octet_number;
  if (octet_number < 3) {
    next_octet_number = (parseInt(octet_number) + 1);
    next_octet_name = base_name + "__" + (next_octet_number);
  }
  else {
    next_octet_name = null;
    next_octet_number = 3;
  }
  // determine the previous octet
  var prev_octet_name;
  var prev_octet_number;
  if (octet_number > 0) {
    var prev_octet_number = (parseInt(octet_number) - 1);
    prev_octet_name = base_name + "__" + (prev_octet_number);
  }
  else {
    prev_octet_name = null;
    prev_octet_number = 0;
  }
  // if we need to advance/retreat octets, new_octet_object will be non-null
  var new_octet_object = null;

  var evt = event;
  var charCode = (evt.charCode) ? evt.charCode :
        ((evt.which) ? evt.which : evt.keyCode);

  // ignore all but digit (48-57), "." (190), space (32), tab (9),  backspace (8), and delete (46)
  // also allow arrows (37-40)
  // handle tab
  if (charCode == 9) {
    return true;
  }

  // Translate the numeric keypad
     // Handle digits 0 - 9
  if( charCode >= 96 && charCode <= 105 )
    charCode -= 48;
    // Handle the "dot"
  if( charCode == 110 )
      charCode = 190;

  // abort non-digit...
  if (charCode != 9 &&
      charCode != 8 &&
      charCode != 46 &&
      charCode != 190 &&
      charCode != 32 &&
      charCode != 37 &&
      charCode != 38 &&
      charCode != 39 &&
      charCode != 40 &&
      !(charCode >= 48 && charCode <= 57)) {
    return false;
  }

  // allow arrows
  if (charCode == 37 || charCode == 39) {
    return true;
  }

  // convert up/down to left/right
  var new_charCode = -1;
  if (charCode == 38) {
    new_charCode = 37;
  }
  if (charCode == 40) {
    new_charCode = 39;
  }
  if (new_charCode > -1) {
    if (evt.charCode) evt.charCode = new_charCode;
    if (evt.which) evt.which = new_charCode;
    if (evt.keyCode) evt.keyCode = new_charCode;
    return true;
  }

  // cancel if we're a "." (or space) and the octet is empty or selected
  if ((charCode == 190 || charCode == 32) &&
      (octet == "" || selected == self.name)) {
    return false;
  }

  //If the value is already 0, then replace the value with new value
  if (evt.type == 'keydown' && octet=="0" && charCode != 190){
      self.value='';
  }

  // clear out previously selected note
  selected = null;

  // handle backspace
  if (evt.type == 'keydown' && charCode == 8 && octet == "" && prev_octet_name != null) {
    new_octet_object = eval("document.f."+prev_octet_name);
    new_octet_object.focus();
    new_octet_object.value = new_octet_object.value;
    return true;
  }
  // ignore backspace on keyup
  if (evt.type == 'keyup' && charCode == 8) {
    return false;
  }

  if (evt.type == 'keyup') {
    // if we just typed a "." and we're at the beginning, stay here
    if (octet == "." + old_octet[octet_number] || octet == " " + old_octet[octet_number]) {
      octet = old_octet[octet_number];
      new_octet_object = self;
    }
    // otherwise, advance to next octet
    if ((octet.replace(/\./g, "") != octet || octet.replace(/ /g, "") != octet) && next_octet_name != null) {
      new_octet_object = eval("document.f."+next_octet_name);
    }
  
    // fix/alert if bad input
    // strip all but numbers
    octet = octet.replace(/[^0-9]/g, "");
    // if we just typed our third digit and it is valid, advance...
    if (octet.length == 3 && octet <= 255 && octet >= 0 && next_octet_name != null) {
      new_octet_object = eval("document.f."+next_octet_name);
    }
    if (octet.length > 3) {
      if (old_octet[octet_number].length == 3) {
        // if we typed a fourth character, restore the value
        // if we typed it at the end, advance
        if (octet.substr(0,3) == old_octet[octet_number] && next_octet_name != null) {
          new_octet_object = eval("document.f."+next_octet_name);
        } 
        octet = old_octet[octet_number];
      }
    }
    if (octet > 255 || octet < 0) {
      octet = old_octet[octet_number];
      alert('Valid numbers are between 0 and 255');
    }

    old_octet[octet_number] = octet;

    if (self.value != octet) {
      self.value = octet;
    }

  }
  // advance to next/previous octet if desired
  if (new_octet_object != null) {
    new_octet_object.focus();
    new_octet_object.select();
    selected = new_octet_object.name;
  }

  return true;
  
}

var args;
function get_args () {
  var args = new Object();
  var query = location.search.substring(1);
  var pairs = query.split("&");
  for (var i=0; i < pairs.length; i++) {
    var pos = pairs[i].indexOf('=');
    if (pos == -1) continue;
    var key = pairs[i].substring(0,pos);
    var value = pairs[i].substring(pos+1);
    args[key] = unescape(value);
  }
  return args;
}

// Routine to run the script to get a support session started
function troubleshoot_request_support_popup()
{
    // Open the window to start the session
    new_window=window.open("/cgi-bin/support-tunnel.cgi" + window.location.search, "request_support", "width=600,height=500,scrollbars=yes,resizable=yes");
    if (new_window && window.focus)
    {
        new_window.focus();
    }
    return false;
}

function batch_test_popup(user, password, et, locale){
    args=get_args();
    open_popup_window("/cgi-bin/batch_test.cgi?user="+user+"&password="+password+"&et="+et+"&locale="+locale);
}

// Routine to output syslog
function syslog_popup(type)
{
    args = get_args();
    
    // Open the window to view syslog
    new_window=window.open("/cgi-bin/nph-syslog.cgi?user="+args.user+"&password="+args.password+"&et="+args.et+"&locale="+args.locale+"&syslog="+type, "syslog", "width=600,height=500,scrollbars=yes,resizable=yes");
    if (new_window && window.focus)
    {
        new_window.focus();
    }
    return false;
}

// Content Filter screen Block All function for each category group
function blockAll(group, checked)
{
    var form = document.f;
    var name = 'UPDATE_spy_content_cat_action_' + group;
    var radio;

    if (checked)
    {
        for (var i = 0; i < form.elements.length; i++)
        {
            if (form.elements[i].name.indexOf(name) >= 0)
            {
                radio = form.elements[i];
                if (radio.value == 'Block')
                    radio.checked = true;
            }
        }
    }
    else
    {
        for (var i = 0; i < form.elements.length; i++)
        {
            if (form.elements[i].name.indexOf(name) >= 0)
            {
                radio = form.elements[i];
                if (radio.value == 'Off')
                    radio.checked = true;
           }
        }
    }
} 

// Content Filter screen Block All function for each category group
function blockApp(group, checked)
{
    var form = document.f;
    var name = 'spy_content_app_action_' + group;
    var radio;

    if (checked)
    {
        for (var i = 0; i < form.elements.length; i++)
        {
            if (form.elements[i].name.indexOf(name) >= 0)
            {
                radio = form.elements[i];
                if (radio.value == 'Block')
                    radio.checked = true;
            }
        }
    }
    else
    {
        for (var i = 0; i < form.elements.length; i++)
        {
            if (form.elements[i].name.indexOf(name) >= 0)
            {
                radio = form.elements[i];
                if (radio.value == 'Allow')
                    radio.checked = true;
           }
        }
    }
}

function replaceId (obj, newId) {
    if (obj.id) {
        obj.id = obj.id.replace(/_\d+$/, '_' + newId);
    }
}

// Adds a new boolean search filter
function addFilter () {
    var filterCount = 0;
    
    /** Create the new filter control */

    // Get a list of the `select' nodes
    var dropdowns = document.getElementsByTagName("select");

    // Get the filter counts
    for (var i = 0; i < dropdowns.length; i++) {
        if (dropdowns[i].id.indexOf("boolean_") == 0) {
            filterCount++;
        }
    }
    // Clone the first row, to make our new row
    var newFilter =
        document.getElementById("filter_control_0").cloneNode(true);
    newFilter.id = "filter_control_" + filterCount;

    /** Gather the nodes */
    var booleanNode = newFilter.childNodes[0];
    var filterNode  = newFilter.childNodes[1];
    var patternNode = newFilter.childNodes[2];
    var addNode     = newFilter.childNodes[3];
    var applyNode   = newFilter.childNodes[4];

    // Remove the "Apply Filter" button
    newFilter.removeChild(applyNode);

    /** Create the boolean dropdown */

    // Get the option strings
    var andString       = document.getElementById("boolean_and").value;
    var orString        = document.getElementById("boolean_or").value;
    var andNotString    = document.getElementById("boolean_and_not").value;
    var orNotString     = document.getElementById("boolean_or_not").value;

    // Create the new options
    var andOption       = new Option(andString);
    var orOption        = new Option(orString);
    var andNotOption    = new Option(andNotString);
    var orNotOption     = new Option(orNotString);

    // Set the values
    andOption.value     = "boolean_and";
    orOption.value      = "boolean_or";
    andNotOption.value  = "boolean_and_not";
    orNotOption.value   = "boolean_or_not";

    // Build the new drop down
    var newBoolean          = document.createElement("select");
    newBoolean.id           = "boolean_" + filterCount;
    newBoolean.options[0]   = andOption;
    newBoolean.options[1]   = orOption;
    newBoolean.options[2]   = andNotOption;
    newBoolean.options[3]   = orNotOption;

    // Replace the old boolean dropdown with the new one
    booleanNode.replaceChild(
        newBoolean,
        booleanNode.childNodes[0]
    );

    /** Set the filter dropdown to `none' -- this fixes a cloning issue. */
    filterNode.childNodes[1].selectedIndex = 0;

    /** Change the pattern box */

    // Reset the pattern text
    patternNode.childNodes[0].childNodes[1].childNodes[1].value = "";

    /** Create the remove button */

    // Create the remove button
    var newButton       = document.createElement("input");
    newButton.type      = "button";
    newButton.value     = '-';
    newButton.onclick   = removeFilter;

    // Replace the add button with the remove button
    addNode.replaceChild(
        newButton,
        addNode.childNodes[0]
    );

    /** Set new IDs */
    
    // Rename all the IDs - for three levels down
    for (var i = 0; i < newFilter.childNodes.length; i++) {
        replaceId(newFilter.childNodes[i], filterCount);
        if (!newFilter.childNodes[i].childNodes) {continue;}
        for (var j = 0; j < newFilter.childNodes[i].childNodes.length; j++) {
            replaceId(newFilter.childNodes[i].childNodes[j], filterCount);
            if (!newFilter.childNodes[i].childNodes[j].childNodes) {continue;}
            for (var k = 0; k < newFilter.childNodes[i].childNodes[j].childNodes.length; k++) {
                replaceId(newFilter.childNodes[i].childNodes[j].childNodes[k], filterCount);
                if (!newFilter.childNodes[i].childNodes[j].childNodes[k].childNodes) {continue;}
                for (var l = 0; l < newFilter.childNodes[i].childNodes[j].childNodes[k].childNodes.length; l++) {
                    replaceId(newFilter.childNodes[i].childNodes[j].childNodes[k].childNodes[l], filterCount);
                }
            }
        }
    }
    
    /** Insert the new filter control */

    var insertNode = document.getElementById("filter_control_table");
    insertNode.childNodes[0].appendChild(newFilter);
    
    // Force a pattern change
    changePattern("filter_" + filterCount);

    return;
}

// requires "%2d" format for mon/day hour:min:sec
function to2d (str) {

    if (str.length == 1) {
        str = "0"+str;
    }

    return str;
}

function updateTimeRange (id) {
    // update the time range pattern from the values of the parts

    // if we aren't a time range, just bail
    id = id.substr(id.lastIndexOf("_")+1);
    if (document.getElementById("filter_"+id).value.indexOf("time_range") == -1) {
        return true;
    }
    var y1 = document.getElementById("time_range_year_"+id).value;
    var mo1 = document.getElementById("time_range_month_"+id).value; 
    var d1 = document.getElementById("time_range_day_"+id).value;
    var h1 = document.getElementById("time_range_hour_"+id).value;
    var m1 = document.getElementById("time_range_minute_"+id).value;
    var s1 = document.getElementById("time_range_second_"+id).value;
    var y2 = document.getElementById("time_range_year2_"+id).value;
    var mo2 = document.getElementById("time_range_month2_"+id).value;
    var d2 = document.getElementById("time_range_day2_"+id).value;
    var h2 = document.getElementById("time_range_hour2_"+id).value;
    var m2 = document.getElementById("time_range_minute2_"+id).value;
    var s2 = document.getElementById("time_range_second2_"+id).value;
    var time1 = y1+"-"+to2d(mo1)+"-"+to2d(d1)+"T"+to2d(h1)+":"+to2d(m1)+":"+to2d(s1);
    var time2 = y2+"-"+to2d(mo2)+"-"+to2d(d2)+"T"+to2d(h2)+":"+to2d(m2)+":"+to2d(s2);
    document.getElementById("pattern_"+id).value = time1+"/"+time2;
    return true;
}

function removeFilter (id) {
    var filterNode  = (typeof(id) == "object" || ! id)
                    ? this.parentNode.parentNode
                    : document.getElementById("filter_control_" + id)
                    ;
    
    // Delete this node
    filterNode.parentNode.removeChild(filterNode);

    // Search and destroy the hidden form variables in the page.
    var inputNodes = document.getElementsByTagName('input');

    for (var i = 0; i < inputNodes.length; i++) {
        if (inputNodes[i].name == 'filter_' + id
        ||  inputNodes[i].name == 'pattern_' + id
        ||  inputNodes[i].name == 'boolean_' + id) {
            inputNodes[i].parentNode.removeChild(inputNodes[i]);
        }
    }
}

function changePattern (filterId) {
    var idIndex = filterId.substring(7);
    // Enable the pattern
    if (document.getElementById(filterId).value.indexOf("search") > -1) {
        document.getElementById("pattern_" + idIndex).disabled = false;
        document.getElementById("pattern_" + idIndex).style.backgroundColor = "#ffffff";
    }
    else {
        document.getElementById("pattern_" + idIndex).disabled = true;
        document.getElementById("pattern_" + idIndex).style.backgroundColor = "#cccccc";
    }

    // Enable the time range
    if (document.getElementById(filterId).value.indexOf("time_range") > -1) {
        document.getElementById("time_range_section_" + idIndex).style.display = "inline";
        document.getElementById("pattern_section_" + idIndex).style.display = "none";
        // make sure that the pattern is enabled - we will actually ship the data back-and-forth in the
        // pattern field
        document.getElementById("pattern_" + idIndex).disabled = false;
    }
    else {
        document.getElementById("time_range_section_" + idIndex).style.display = "none";
        document.getElementById("pattern_section_" + idIndex).style.display = "inline";
    }
}

function applyFilter (urlString) {
    var filterCount = 0;

    // Grab the warning text
    var warningText = document.f.filter_lid_2497.value;   // "[Bad filter]"

    // Check the filters
    if (! checkFilterInput()) {
        return;
    }

    // Get the boolean dropdowns
    var dropdowns = document.getElementsByTagName("select");

    // Get the filter control count
    for (var i = 0; i < dropdowns.length; i++) {
        if (dropdowns[i].id.indexOf("boolean_") != -1) {
            var booleanIndex = dropdowns[i].id.substring(8);

            // Set the highest found index
            if (filterCount < booleanIndex) {
                filterCount = booleanIndex;
            }
        }
    }
    
    // Go through the filters
    for (var i = 0; i < filterCount + 1; i++) {
        // Check this boolean
        if (document.getElementById("boolean_" + i)) {

            // Check for a valid filter string
            if (! checkFilterPattern(document.getElementById("pattern_" + i).value)
            &&  document.getElementById("filter_" + i).value.indexOf("search") > -1
            ) {
                // Bail out
                alert(warningText);

                return false;
            }

            // Grab the filter
            var pattern = new String(encodeURIComponent(document.getElementById("pattern_" + i).value));

            // Escape the pluses
            pattern = pattern.replace(/\+/g, "%2b");

            urlString += "&boolean_" + i + "=" + document.getElementById("boolean_" + i).value;
            urlString += "&filter_" + i + "=" + document.getElementById("filter_" + i).value;
            urlString += "&pattern_" + i + "=" + encodeURIComponent(pattern);
        }
    }
    
    // Apply the filter
    window.open(urlString, "_top");
}

function validDomain(domain, error)
{
    var result = false;

    if (domain.match(/^[\w\.-]+\.[\w]+$/))
    {
        result = true;
    }
    else
    {
        alert(error);
    }

    return result;
}

function ipblocking(ip, netmask, ip2, netmask2, port, error, error2)
{
    var result = false;
    if ((netmask && !ip)||(netmask2 && !ip2))
    {
        alert(error);
    }
    else if(!ip && !netmask && !ip2 && !netmask2 && !port){
        alert(error2);
    }
    else
    {
        result = true;
    }
    return result;
}

function exempt(ip1,ip2,ip3,ip4,error)
{
    var result = false;
    var ip = [new decimal(parseFloat(ip1)).toBinary(),new decimal(parseFloat(ip2)).toBinary(),
              new decimal(parseFloat(ip3)).toBinary(),new decimal(parseFloat(ip4)).toBinary()];
    for(var i=1; i<4 ;i++){
        while(ip[i].length<8){
           ip[i] = "0" + ip[i];
        }
    }
    var bin = new binary(ip[0]+ip[1]+ip[2]+ip[3]).toDecimal();
    var total = 4294967295 - bin + 1;
    var text = error.replace("__1__",total);
    return confirm(text);
}

function decimal(dec)
{
    this.dec=dec;
    this.toBinary=function() { return this.dec.toString(2); }
    this.toHex=function() { return this.dec.toString(16).toUpperCase(); }
    this.toOctal=function() { return this.dec.toString(8); }
}

function binary(bin)
{
    this.bin=bin;
    this.toDecimal=function() { return parseInt(this.bin, 2); }
    this.toHex=function() { return this.toDecimal().toString(16).toUpperCase(); }
    this.toOctal=function() { return this.toDecimal().toString(8); }
}

function checkPort(port){
    if(port == 80 || port == 8080 || port == 8001|| port == 22 || port == 25 || port == 443)
        return false;
    return true;  
}

function checkFilterInput () {
    var filterCount = 0;
    var scoreType   = /score/i;
    var datetimeType   = /time_range/i;
    var isOk        = true;

    // Get the boolean dropdowns
    var dropdowns = document.getElementsByTagName("select");

    // Get the filter control count
    for (var i = 0; i < dropdowns.length; i++) {
        if (dropdowns[i].id.indexOf("boolean_") != -1) {
            var booleanIndex = dropdowns[i].id.substring(8);

            // Set the highest found index
            if (filterCount < booleanIndex) {
                filterCount = booleanIndex;
            }
        }
    }
    
    // Check for score and time ranges
    for (var i = 0; i <= filterCount; i++) {
        // Be sure this filter exists
        if (document.getElementById("filter_" + i)) {
            var filterType  = document.getElementById("filter_" + i).value;
            var scoreMatches     = scoreType.exec(filterType);
            var datetimeMatches  = datetimeType.exec(filterType);
            
            // Check the input type
            if (scoreMatches != null) {
                // Check the input
                var pattern = document.getElementById("pattern_" + i).value;
                if (! isNumerical(pattern)) {
                    isOk = false;
                    break;
                }
            }
            if (datetimeMatches != null) {
                // first make sure we generate the single-input field combined value
                updateTimeRange('time_range_year_' + i);
                // Check the input
                var pattern = document.getElementById("pattern_" + i).value;

                if (! isValidDate(pattern)) {
                    isOk = false;
                    break;
                }
            }
        }
    }

    return isOk;
}

/** This function checks a string passed to it for only numerics.
 * It's best used with a submit button, but can be used anywhere
 * where a boolean return is acceptable.
 */
function isNumerical (string) {
    var numerical = /^[\d., -]+$/;
    
    // Try matching
    var matches = numerical.exec(string);
    
    // Check and make sure it's all numeric
    if (matches == null) {
        // Get the alert text
        var alertText = document.getElementById("numerical_filter_alert").value;
        
        // Give an error
        alert(alertText);

        return false;
    }

    return true;
}

/** This function checks a string passed to it to ensure it is a date
 * in the format used by date/time message log filter.
 * It's best used with a submit button, but can be used anywhere
 * where a boolean return is acceptable.
 */
function isValidDate (string) {
    var dateTimeRe = /^(199\d|20\d{2})\-(0[1-9]|1[0-2])\-(0[1-9]|[1-2][0-9]|3[0-1])T(0\d|1\d|2[0-3]):([0-5]\d):([0-5]\d)\/(199\d|20\d{2})\-(0[1-9]|1[0-2])\-(0[1-9]|[1-2][0-9]|3[0-1])T(0\d|1\d|2[0-3]):([0-5]\d):([0-5]\d)/;
    
    // Try matching
    var matches = dateTimeRe.exec(string);
    
    // Check and make sure it's all numeric
    if (matches == null) {
        // Get the alert text
        var alertText = document.getElementById("invalid_date_alert").value;
        
        // Give an error
        alert(alertText);

        return false;
    }

    return true;
}


/* Check to see if this is a valid pattern (for the filter control). Returns
 * true or false.
 */
function checkFilterPattern (pattern) {
    // Make sure the filter pattern is a legal pattern
    if (pattern.match(/^\s*$/)) {
        return false;
    }
    else {
        return true;
    }
}

// joe 7-27-06 b6164 update date select box when changing month or year
function updateDaySelect(year, month, dayField) {
    var tmpDate = new Date(year, month, 1, 12);
    var origDay = dayField.value;
    var i,selDay;
    // remove the old select options
    while (dayField.childNodes.length > 0) {
        dayField.removeChild(dayField.childNodes[0]);
    }
    // check for ie
    ie = (navigator.appName == "Microsoft Internet Explorer");
    // build the select options
    tmpDate.setDate(0);
    selDay = (origDay > tmpDate.getDate()) ? tmpDate.getDate() : origDay;
    for (i=1; i <= tmpDate.getDate(); i++) {
        if (ie) {
            var newObj = document.createElement("OPTION");
            newObj.text = i;
            newObj.value = (i<10)?"0"+i:i;
            dayField.add(newObj);
        } else {
            var newObj = new Option(i,(i<10)?"0"+i:i,false,(selDay==i)?true:false);
            dayField.appendChild(newObj);
        }
    }
    if (ie) {
        dayField.selectedIndex = selDay-1;
    }
}

/* On "Not Spam" click; checks to see whether any selected spam messages
 * were "confidently" spam (high spam score, or intent reasons). */
function check_for_confident_spam() {
    var found = false;
    var confirmed = new Array;

    // Get our hidden form element.
    var hidden = document.getElementsByName("spam_analysis_confirmed");
    if (hidden.length == 0) {
    } else {
        hidden = hidden[0];
    }

    // Fetch the ids of checked boxes, and compare against
    // confidently-spam ids.
    var inputs = document.getElementsByTagName("input");
    for (var inp = 0; inp < inputs.length; ++inp) {
        var i = inputs[inp];
        // Is this a checkbox input?
        if (i.type == "checkbox" && i.checked) {
            // Strip off "machine" part of name.
            var id = i.name;
            var colonLoc = id.lastIndexOf(":");
            id = id.substr(0, colonLoc);

            // Does it refer to "confidently" designated spam?
            for (j = 0; j < confidently_spam_ids.length; ++j) {
                var cfd = confidently_spam_ids[j];
                if ('quarantine_message_' + cfd == id) {
                    found = true;
                    confirmed.push(cfd);
                    break;
                }
            }
        }
    }

    if (found) {
        if (window.confirm(confirm_confidently_spam_msg)) {
            hidden.value=confirmed.join("\n");
        }
    }

    return true;
}
