// define global settings
var gdn_AuthService      = "GDNAuth.ashx",
gdn_ExtrovertService = "Extrovert/GDNExtrovert.ashx",
gdn_MaxSessions      = 10,
gdn_RegService       = "GCION.ashx",
gdn_Version          = "3.4.2",
gdn_language= typeof gdn_language == 'string' ? gdn_language : "eng"; 
gdn_browsers=[
	"Explorer|>=|6.0|Windows",
	"Firefox|>=|1.0|Windows",
	"Firefox|>=|1.0|Linux",
	"Firefox|>=|1.0|Mac",
	"Safari|>=|1.0|Mac"
],
gdn_section_front= typeof gdn_section_front != 'undefined' ? gdn_section_front : ""
;


// define global objects
var 
gdn_Timers     = [];
gdn_Requests   = [];
gdn_Widgets    = {};

// define actions
gdn_Actions={ 
Login:0,
Refresh:0,
Reg:0,
RegThanks: 0
};

// define div identifiers
gdn_Divs= { 
'ErrorSummary-Inline': "UAErrorSummary-Inline",
'ErrorSummary-PopUp': "UAErrorSummary-PopUp",
'ErrorSummary-ThirdPartyInline': "UAErrorSummary-ThirdPartyInline",
'ErrorSummary-ThirdPartyPopUp': "UAErrorSummary-ThirdPartyPopUp",
Login: "login-container",
Newsletters: "newsletter-subscription",
NewslettersList: "Newsletters",
PluckLogin: "pluck-signin",
PluckReg: "pluck-register",
PluckLogout: "pluck-signout",
SaxotechLogin: "saxotech-login",
'Status-Inline': "UAStatus-Inline",
'Status-PopUp': "UAStatus-PopUp",
'Status-ThirdPartyInline': "UAStatus-ThirdPartyInline",
'Status-ThirdPartyPopUp': "UAStatus-ThirdPartyPopUp",
'CustomStatus-PopUp': "UACustomStatus-PopUp",
'CustomStatus-Inline': "UACustomStatus-Inline"
}

// define timeouts
gdn_Timeouts= {
Avatar:5,
Element:30
};

// define timeout identifiers
gdn_TimeoutIds= { 
Default: 0
};
var gdn_ext_ex   = {},
gdn_local_ex = {},
gdn_msgs     = { eng: { 
CancelExec: "Canceling your membership...",
CancelFailed: "We were unable to cancel your membership",
CancelTimeout: "We were unable to cancel your membership. Please try again later.",
ChangeActDupEmail: "The email address you entered is already in use",
ChangeActDupUser: "The screen name you entered is already in use",
ChangeActExec: "Updating your account...",
ChangeActFailed: "We were unable to update your account",
ChangeActTimeout: "We were unable to update your account. Please try again later.",
ChangePwdExec: "Changing your password...",
ChangePwdFailed: "We were unable to change your password",
ChangePwdInvalid: "Your old password is invalid",
ChangePwdTimeout: "We were unable to change your password. Please try again later.",
ChangeUsrDupUser: "The screen name you entered is already in use",
ChangeUsrExec: "Updating your account...",
ChangeUsrFailed: "We were unable to update your account",
ChangeUsrTimeout: "We were unable to update your account. Please try again later.",
ConfirmActivated: "Your account has already been activated",
ConfirmExec: "Sending your confirmation email...",
ConfirmInvalid: "The email address you entered is invalid",
ConfirmTimeout: "We were unable to send your confirmation email. Please try again later.",
ForgotPwdExec: "Retrieving your password...",
ForgotPwdInvalid: "The email address you entered is invalid",
ForgotPwdTimeout: "We were unable to retrieve your password. Please try again later.",
LoginExec: "Loading...",
LoginFailed: "Invalid email or password",
LoginLockedOut: "Your account is locked out. Please try again in 10 minutes.",
LoginNoCookies: "Cookies must be enabled to log in",
LoginTimeout: "Unable to log you in",
LoginUnavailable: "Your {0} is currently unavailable. Please manually enter your information and click the Become a Member button to sign up now.",
NletterExec: "Updating your newsletter subscriptions...",
NletterFailed: "Your newsletter subscriptions could not be updated",
NletterNone: "No newsletters were found",
NletterSaved: "Your newsletter subscriptions updated successfully",
NletterTimeout: "We were unable to update your newsletter subscriptions. Please try again later.",
RegDupEmail: "The email address you entered is already in use",
RegDupUser: "The screen name you entered is already in use",
RegExec: "Registering your account...",
RegFailed: "We were unable to complete your registration",
RegTimeout: "We were unable to register your account. Please try again later.",
ZagExec: "Registering...",
ZagTimeout: "We were unable to register you. Please try again later.",
CompanySizeNone: "You must select your company size",
CountryNone: "You must select your country",
EmailInvalid: "Your email address is invalid (Ex. username@domain.com)",
EmailMax: "Your email address must be 100 characters or less",
EmailNone: "You must enter your email address",
ErrorHeader: "The following errors occurred in each required field:",
FirstNameMax: "Your first name must be 30 characters or less",
GenderNone: "You must select your gender",
IndustryNone: "You must select your industry",
LastNameMax: "Your last name must be 30 characters or less",
OccupationNone: "You must select your occupation",
OldPwdNone: "You must enter your old password",
PwdConfirm: "You must confirm your password",
PwdInvalid: "Your password can only contain letters and numbers, no spaces",
PwdMax: "Your password must be 30 characters or less",
PwdMin: "Your password must be at least 5 characters",
PwdNoMatch: "Your passwords do not match",
PwdNone: "You must enter your password",
UserNameCreate: "If you do not have a screen name, please create one",
UserNameInvalid: "Your screen name can only contain letters and numbers, no spaces",
UserNameMax: "Your screen name must be 16 characters or less",
UserNameMin: "Your screen name must be at least 5 characters",
UserNameNone: "You must enter your screen name",
YobInvalid: "Your year of birth is invalid (Ex. 1975)",
YobNone: "You must enter your year of birth",
ZipFailed: "Your zip code is in the correct format but it is not valid",
ZipInvalid: "Your zip code is invalid (Ex. 47012)",
ZipNone: "You must enter your zip code",
YobUnderage: "We're sorry.  We cannot accept your registration at this time.  Please review our <a href=\"ReplacehrefTOS\">Terms of Service</a>"
}};
var GDN = window.GDN || {};
GDN.namespace = function(nameSpace)
{
  if (!nameSpace || !nameSpace.length)
    return null;

  var levels = nameSpace.split(".");
  var currentNamespace = GDN;

  // GDN is implied, so it is ignored if it is included
  for (var i = (levels[0] == "GDN") ? 1 : 0; i < levels.length; ++i)
  {
    currentNamespace[levels[i]] = currentNamespace[levels[i]] || {};
    currentNamespace = currentNamespace[levels[i]];
  }

  return currentNamespace;
};

// register child namespaces
GDN.namespace("Cookies");
GDN.namespace("UA");
GDN.namespace("UA.Events");
GDN.namespace("UR");
GDN.namespace("UR.Events");
GDN.AddHandler = function(object, type, fns)
{
  // Internet Explorer
  if (object.addEventListener)
  {
    object.addEventListener(type, fns, false);
    return true;
  }
  // Firefox
  else if (object.attachEvent)
    return object.attachEvent('on' + type, fns);
  // all other browsers
  else
    object['on' + type] = fns;
};

/// <summary>
/// Listens for the specified element as it is being loaded and executes a
/// callback handler once the element is loaded.
/// </summary>
/// <param name="elementName">The name of the element.</param>
/// <param name="callback">The callback handler to execute.</param>
GDN.AddListener = function(elementName, callback)
{
  // set timer
  if (gdn_Timers[elementName] == null)
    gdn_Timers[elementName] = 0;

  // ensure element is available
  if (document.getElementById(elementName))
  {
    // clear timeout
    window.clearTimeout(gdn_TimeoutIds[elementName]);

    // reset timer
    gdn_Timers[elementName] = 0;
    
    // execute callback
    if (callback)
      callback.call();
  }
  else
  {
    // continue execution until timeout is reached
    if (gdn_Timers[elementName] < (gdn_Timeouts["Element"] * 1000))
    {
      // set timeout
      gdn_TimeoutIds[elementName] = window.setTimeout("GDN.AddListener('" + elementName + "', " + callback + ")", 100);
        
      // update timer
      gdn_Timers[elementName] += 100;
    }
    // end execution if timeout is reached
    else
    {
      // reset timer
      gdn_Timers[elementName] = 0;
    }
  }
};

/// <summary>
/// Appends the specified name and value parameter onto the query string
/// of the specified URL.
/// </summary>
/// <param name="url">The URL in which to append the parameter.</param>
/// <param name="name">The name of the parameter.</param>
/// <param name="value">The value of the parameter.</param>
GDN.AppendParam = function(url, name, value)
{
  // check for question mark in URL
  if (url.indexOf("?") == -1)
    return url + "?" + name + "=" + escape(value);
  else
    return url + "&" + name + "=" + escape(value);
};

/// <summary>
/// Gets the absolute URL for the specified path.
/// </summary>
/// <param name="url">The relative URL to combine.</param>
/// <param name="path">The relative path to combine.</param>
/// <param name="secure">A value indicating if the URL should be secure.</param>
GDN.CombinePath = function(url, path, secure)
{
  if (secure)
  {
    // append HTTPS prefix if not set
    if (url.substr(0, 7) != "https://")
      var absUrl = "https://" + url;
    else
      var absUrl = url;
  }
  else
  {
    // append HTTP prefix if not set
    if (url.substr(0, 7) != "http://")
      var absUrl = "http://" + url;
    else
      var absUrl = url;
  }

  // append trailing forward slash if not set
  if (path.charAt(0) != "/")
    absUrl += "/" + path;
  else
    absUrl += path;

  return absUrl;
};

/// <summary>
/// Gets the absolute URL, including the specified query string
/// parameters, of the registration service.
/// </summary>
/// <param name="parameters">Query string parameters in which to append to the request URL.</param>
GDN.RegUrl = function(parameters)
{
  // get absolute URL to data service
  var url = GDN.CombinePath(gdn_host, gdn_RegService);

  // append query string parameters if specified
  if (!GDN.IsNullOrEmpty(parameters))
    url += "?" + parameters.replace(/\?/, "") + "&CacheDefeat=" + new Date().getTime();

  return url;
};


/// <summary>
/// Disables the user interface for maintenance either by division or site.
/// </summary>
GDN.Disable = function()
{
  if ((document.getElementById(gdn_Divs["PluckLogin"])))    var element = "PluckLogin";
  if ((document.getElementById(gdn_Divs["PluckReg"])))      var element = "PluckReg";
  if ((document.getElementById(gdn_Divs["SaxotechLogin"]))) var element = "SaxotechLogin";
  if ((document.getElementById(gdn_Divs["Newsletters"])))   var element = "Newsletters";
  if ((document.getElementById(gdn_Divs["Login"])))         var element = "Login";

  if (document.getElementById(gdn_Divs[element]))
    GDN.Widget.Load("inline", "MaintenanceMode", "gdn_Widgets['MaintenanceMode']", "gdn_Divs['" + element + "']");
};

/// <summary>
/// Gets the age of a user.
/// </summary>
/// <param name="yob">The year of birth for a user.</param>
GDN.GetAge = function(yob)
{
  // get today's date
  var today = new Date();

  return (!GDN.IsNullOrEmpty(yob)) ? (today.getFullYear() - yob) : 0;
};

/// <summary>
/// Gets a creation date.
/// </summary>
GDN.GetCreationDate = function()
{
  // get today's date
  var today = new Date();

  return today.getFullYear().toString() +
    (((today.getMonth() + 1) < 10) ? ("0" + (today.getMonth() + 1).toString()) : (today.getMonth() + 1).toString()) +
    ((today.getDate() < 10) ? ("0" + today.getDate().toString()) : (today.getDate().toString()));
};

/// <summary>
/// Gets a value in its native data type.
/// </summary>
/// <param name="value">The value in its native data type.</param>
GDN.GetDataType = function(value)
{
  if (value == true || value == false)
    return value;
  else if (GDN.IsNullOrEmpty(value))
    return 'null';
  else if (!isNaN(value))
    return value;
  else
    return '"' + value + '"';
};

/// <summary>
/// Gets the domain name where cookies set by the application reside.
/// </summary>
GDN.GetDomainName = function()
{
  // get default top level domain
  var domain = window.location.host;
  var match = /([\w-]+)\.[a-zA-Z]{2,3}$/i.exec(domain);
  domain = match ? "." + match[0] : domain;

  try 
  {
    // get overriden domain if set
  	if (gdn_cookie_domain)
      return "." + gdn_cookie_domain;
    else
      return domain;
  }
  catch (e) { return domain; }
};

/// <summary>
/// Gets a message for the specified language.
/// </summary>
/// <param name="key">The key used to get the message.</param>
GDN.GetMessage = function(key)
{
  return gdn_msgs[gdn_language][key];
};

/// <summary>
/// Gets the version of the library or cookie.
/// </summary>
/// <param name="type">The type of version to retrieve.</param>
GDN.GetVersion = function(type)
{
  switch (type)
  {
    case "Cookie":
    {
      // ensure cookie exists
      if (!GDN.Cookie.Exists("GCIONID")) return 1;

      // get cookie
      var cookie = GDN.Base64.Decode(GDN.Cookie.Get("GCIONID"));

      // get cookie parts
      var parts = cookie.split('~');
      
      return parts[1];
    }
    default : return gdn_Version;
  }
};

/// <summary>
/// Gets a value indicating if the specified object is null or empty.
/// </summary>
/// <param name="object">The object to determine if it is null or empty.</param>
GDN.IsNullOrEmpty = function(object)
{  
  if (object == null || (object == '' && 'number' != typeof object) ||
    object.Length == 0 || object == "null" || object == "undefined" ||
    object == undefined || object.toString().replace(/^\s+|\s+$/, '') == "")
  {
    return true;
  }
  else
    return false;
};
GDN.getPath= function(file, type) { 
	file= file.endsWith(".js") ? file : file + ".js"; 
	return [GEL.env.gelpath.path + '/legacy/GDN' , type, file].join ("/");
}

GDN.LoadFile = function(file, type, callback)
{
  var url=  GDN.getPath(file, type);  

  // get file if it has not been loaded
  if (!GDN.Rpc.IsLoaded(url))
  {
    // add callback handler
    if (callback)
      GDN.Callback.Add(callback);
  
    // get file
    GDN.Rpc.Send(url);
  }
  else
  {
    // execute callback handler
    if (callback)
      callback.call();
  }
};

/// <summary>
/// Sets the focus on the first field in the form.
/// </summary>
/// <param name="name">The name of the form object.</param>
GDN.SetFocus = function(name)
{
  // get reference to form object
  var form = document.getElementById(name);

  // set focus on first text field
  try
  {
    for (var i = 0; i < form.elements.length; i++)
    {
      if (/text/.test(form.elements[i].type) || /password/.test(form.elements[i].type))
      {
        form.elements[i].focus();
        break;
      }
    }
  }
  catch (e) {}
};

/// <summary>
/// Sets the inner HTML of the specified element using the specified value.
/// </summary>
/// <param name="elementName">The name of the element.</param>
/// <param name="html">The HTML to set inside the element.</param>
GDN.SetInnerHtml = function(elementName, html)
{
  var layer;
  
  // all other browsers
  if (document.layers)
  {
    layer = document.layers[elementName];
    layer.document.open();
    layer.document.write(html);
    layer.document.close();
  }
  
  // Internet Explorer
  if (document.all)
  {
    layer = document.all[elementName];
    layer.innerHTML = html;
  }
  
  // Mozilla browsers
  if (document.getElementById)
  {
    layer = document.getElementById(elementName);
    layer.innerHTML = html;
  }
};

/// <summary>
/// Trims leading and trailing spaces from a string.
/// </summary>
String.prototype.trim = function()
{
	return this.replace(/^\s+|\s+$/g, "");
};

/// <summary>
/// The Api type provides methods for using external methods defined in client
/// applications that are invoked in internal event handlers. 
/// </summary>
GDN.Api =
{
  /// <summary>
  /// Invokes all API methods.
  /// </summary>
 
  /// <param name="eventType">The type of event to invoke.</param>
  Invoke : function(eventType)
  {
    var fns = GDN.Api.Methods;
    var par = GDN.Api.Params;
    var evt = GDN.Api.Events;
    
    for (var i = 0; i < evt.length; i++)
    {
      if (evt[i].toLowerCase() == eventType.toLowerCase())
        fns[i].apply(GDN, new Array(par[i]));
    }
  },
  
  /// <summary>
  /// Registers an API method.
  /// </summary>
  /// <param name="method">A reference to the method.</param>
  /// <param name="param">A parameter to send to the method.</param>
  /// <param name="eventType">The type of event to invoke.</param>
  Register : function(method, param, eventType)
  {      
    // add method and event type
    GDN.Api.Methods.push(method);
    GDN.Api.Params.push(param);
    GDN.Api.Events.push(eventType);
  }
};

// initialize
if (!GDN.Api.Methods) GDN.Api.Methods = [];
if (!GDN.Api.Params)  GDN.Api.Params  = [];
if (!GDN.Api.Events)  GDN.Api.Events  = [];
/// <summary>
/// The Base64 type provides methods to encode/decode Base64 strings. 
/// </summary>
GDN.Base64 =
{
  /// <summary>
  /// Gets the base 64 key used for encoding/decoding a value.
  /// </summary>
  Key : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  
  /// <summary>
  /// Base 64 decodes the specified value.
  /// </summary>
  /// <param name="value">The value to decode.</param>
  Decode : function(value)
  {
    var keyStr = this.Key;
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
     
    value = value.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do
    {
      enc1 = keyStr.indexOf(value.charAt(i++));
      enc2 = keyStr.indexOf(value.charAt(i++));
      enc3 = keyStr.indexOf(value.charAt(i++));
      enc4 = keyStr.indexOf(value.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64)
        output = output + String.fromCharCode(chr2);

      if (enc4 != 64)
        output = output + String.fromCharCode(chr3);

      chr1 = chr2 = chr3 = "";
      enc1 = enc2 = enc3 = enc4 = "";
    } while (i < value.length);

    return output;
  },

  /// <summary>
  /// Base 64 encodes the specified value.
  /// </summary>
  /// <param name="value">The value to encode.</param>
  Encode : function(value)
  {
    var keyStr = this.Key;
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    do
    {
      chr1 = value.charCodeAt(i++);
      chr2 = value.charCodeAt(i++);
      chr3 = value.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2))
        enc3 = enc4 = 64;
      else if (isNaN(chr3))
        enc4 = 64;

      output = output + 
        keyStr.charAt(enc1) + 
        keyStr.charAt(enc2) + 
        keyStr.charAt(enc3) + 
        keyStr.charAt(enc4);
         
      chr1 = chr2 = chr3 = "";
      enc1 = enc2 = enc3 = enc4 = "";
    } while (i < value.length);

    return output;
  }
};
/// <summary>
/// The Callback type provides methods for handling client callbacks. 
/// </summary>
GDN.Callback =
{
  /// <summary>
  /// Adds a callback handler.
  /// </summary>
  /// <param name="handler">A reference to the callback handler.</param>
  Add : function(handler)
  {
    // remove callback handler
    if (GDN.Callback.Handlers.length > 0)
      GDN.Callback.Handlers = [];
      
    // add callback handler
    GDN.Callback.Handlers.push(handler);
  },

  /// <summary>
  /// Invokes a callback handler.
  /// </summary>
  Invoke : function()
  {
    var fns = GDN.Callback.Handlers;
    for (var n = 0; n < fns.length; n++){
      fns[n].apply(GDN, arguments);
    }
  }
};

// initialize
if (!GDN.Callback.Handlers) GDN.Callback.Handlers = [];
/// <summary>
/// The Cookie type provides methods for handling cookies. 
/// </summary>
GDN.Cookie =
{
  /// <summary>
  /// Gets a value indicating if the specified cookie exists.
  /// </summary>
  /// <param name="name">The name of the cookie.</param>
  Exists : function(name)
  {
    var cookieString = document.cookie;
    var cookieSet    = cookieString.split(';');
    var setSize      = cookieSet.length;
    var cookiePieces = "";
    var cookieData   = "";
    
    for (var x = 0; ((x < setSize) && (cookieData == "")); x++)
    {
      cookiePieces = cookieSet[x].split('=');
      
      if (cookiePieces[0].substring(0, 1) == ' ')
        cookiePieces[0] = cookiePieces[0].substring(1, cookiePieces[0].length);
      
      if (cookiePieces[0] == name)
        return true;
    }

    return false;
  },

  /// <summary>
  /// Gets the value stored in the specified cookie.
  /// </summary>
  /// <param name="name">The name of the cookie.</param>
  Get : function(name)
  {    
    var values = (' ' + document.cookie).match(new RegExp(' ' + name + '=[^;]*', 'g')) || [];
    var length = 0;
    var result = null;
    
    for (var i = 0; i < values.length; i++)
    {
      if (values[i].length > length)
      {
        length = values[i].length;
	      result = unescape(values[i].substring(2 + name.length));
      }
    }

	  return result;
  },
  
  /// <summary>
  /// Removes the specified cookie.
  /// </summary>
  /// <param name="name">The name of the cookie.</param>
  /// <param name="path">The path to the cookie.</param>
  /// <param name="domain">The domain name for the cookie.</param>
  /// <param name="relative">A value indicating if the cookie is relative to the domain.</param>
  Remove : function(name, path, domain, relative)
  {
	  if (this.Get(name))
	  {
	    document.cookie = name + '=' +
	      ((path) ? ';path=' + path : ';path=' + '\/') +
			  ((domain) ? ';domain=' + domain : ';domain=' +
			  ((relative) ? domain : GDN.GetDomainName())) +
			  ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
	  }
  },
  
  /// <summary>
  /// Sets a cookie containing the specified value.
  /// </summary>
  /// <param name="name">The name of the cookie.</param>
  /// <param name="value">The value to store in the cookie.</param>
  /// <param name="expires">The expiration date of the cookie.</param>
  /// <param name="path">The path to the cookie.</param>
  /// <param name="domain">The domain name for the cookie.</param>
  /// <param name="secure">A value indicating whether the cookie is secure.</param>
  Set : function(name, value, expires, path, domain, secure)
  {
    var today = new Date();
    today.setTime(today.getTime());
    
    if (expires)
      expires = expires * 1000 * 60 * 60 * 24;

    var expirationDate = new Date(today.getTime() + (expires));
    
    document.cookie = name + '=' + value +
      ((expires) ? ';expires=' + expirationDate.toGMTString() : '') +
      ((path) ? ';path=' + path : ';path=' + '\/' ) +
      ((domain) ? ';domain=' + domain : ';domain=' + GDN.GetDomainName()) +
      ((secure) ? ';secure' : '');
  }
};

/// <summary>
/// The Json type provides methods for generating strongly typed JSON objects.
/// </summary>
GDN.Json = function()
{
  // data members
  var _attributes = [];
  var _names      = [];
  var _values     = [];
  
  // methods
  this.Add          = Add;
  this.AddAttribute = AddAttribute;
  this.Clear        = Clear;
  this.HasEntries   = HasEntries;
  this.ToString     = ToString;

  /// <summary>
  /// Adds an entry to the collection. 
  /// </summary>
  /// <param name="name">The name of the entry.</param>
  /// <param name="value">The value of the entry.</param>
  function Add(name, value)
  {
    _names.push(name);
    _values.push(value);
  }

  /// <summary>
  /// Adds an attribute to the collection. 
  /// </summary>
  /// <param name="name">The name of the attribute.</param>
  /// <param name="value">The value of the attribute.</param>
  function AddAttribute(name, value)
  {
    _attributes.push('{"Key":"' + name + '","Value":"' + value + '"}');
  }

  /// <summary>
  /// Clears all entries from the collection. 
  /// </summary>
  function Clear()
  {
    _attributes = [];
    _names      = [];
    _values     = [];
  }

  /// <summary>
  /// Gets a value indicating if any entries were added to the collection.
  /// </summary>
  function HasEntries()
  {
    if (_names.length == 0)
      return false;
    else
      return true;
  }

  /// <summary>
  /// Gets a string representation of a JSON object for all entries contained
  /// in the collection.
  /// </summary>
  function ToString()
  {
    // ensure entries exist
    if (!this.HasEntries()) return null;

    var json = '{';

    // append entries
    for (var i = 0; i < _names.length; i++)
    {
      if (i != _names.length - 1)
        json += '"' + _names[i] + '"' + ':' + GDN.GetDataType(_values[i]) + ',';
      else
        json += '"' + _names[i] + '"' + ':' + GDN.GetDataType(_values[i]);
    }
    
    // append attributes
    if (_attributes.length > 0)
    {
      json += ',"Attributes":[';
    
      for (var i = 0; i < _attributes.length; i++)
      {
        if (i != _attributes.length - 1)
          json += _attributes[i] + ',';
        else
          json += _attributes[i] + ']';
      }
    }
    
    json += '}';

    return json;
  }
};
/// <summary>
/// The Request type provides methods for obtaining query string parameters
/// from an HTTP request. 
/// </summary>
GDN.Request =
{
  /// <summary>
  /// Initializes the Request object and reads URL parameters into an array. 
  /// </summary>
  Init : function()
  {
	  this.params = new Object();
  	
    var querystring = location.search.substring(1, location.search.length);

	  if (querystring.length == 0) return;

	  querystring = querystring.replace(/\+/g, ' ');
	  var args = querystring.split('&');
  	
    // split out each name/value pair
	  for (var i = 0; i < args.length; i++)
	  {
		  var value;
		  var pair = args[i].split('=');
		  var name = unescape(pair[0].toString().toLowerCase());

		  if (pair.length == 2)
			  value = unescape(pair[1]);
		  else
			  value = name;
  		
		  this.params[name] = value;
	  }
	},

  /// <summary>
  /// Gets a value from the specified query string name parameter.
  /// </summary>
  /// <param name="name">The name of the item to retrieve from the query string.</param>
  /// <param name="defaultValue">The default value to return if the specified name is not found.</param>
  QueryString : function(name, defaultValue)
  {
	  if (defaultValue == null) defaultValue = null;
  	
	  var value = this.params[name.toLowerCase()];
	  if (value == null) value = defaultValue;
  	
	  return value;
  }
};

// initialize
GDN.Request.Init();
/// <summary>
/// The Rpc type provides methods for executing remote procedure calls.
/// </summary>
GDN.Rpc =
{  
  /// <summary>
  /// Creates a RPC request and executes the request using the specified
  /// request URL.
  /// </summary>
  /// <param name="requestUrl">The request URL used in the RPC request.</param>
  Create : function(requestUrl)
  {
    // define DOM elements
    var htmlTag   = document.getElementsByTagName('head').item(0);
    var scriptTag = document.createElement('script');
      
    // set tag attributes
    scriptTag.setAttribute('language', 'javascript');
    scriptTag.setAttribute('type', 'text/javascript');
    scriptTag.setAttribute('src', requestUrl);
      
    // append tag to DOM
    htmlTag.appendChild(scriptTag);
      
    return false;
  },
  
  /// <summary>
  /// Determines whether the specified request URL has been loaded.
  /// </summary>
  /// <param name="requestUrl">The request URL to send in the RPC request.</param>
  IsLoaded : function(requestUrl)
  {
    for (var i = 0; i < gdn_Requests.length; i++)
    {
      if (gdn_Requests[i] == requestUrl)
        return true;
    }

    return false;
  },

  /// <summary>
  /// Sends the RPC request to the specified request URL.
  /// </summary>
  /// <param name="requestUrl">The request URL to send in the RPC request.</param>
  Send : function(requestUrl)
  {
    if (!this.IsLoaded(requestUrl))
    {
      gdn_Requests[gdn_Requests.length] = requestUrl;
      this.Create(requestUrl);
    }
  }
};
/// <summary>
/// The Session type provides methods for handling the Session cookie.
/// </summary>
GDN.Cookies.Session =
{
  /// <summary>
  /// Gets the name of the cookie.
  /// </summary>
  Name: "GCIONSN",

  /// <summary>
  /// Gets a value from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetValue : function(key)
  {
    // ensure cookie exists
    if (!GDN.Cookie.Exists(this.Name)) return null;

    // get cookie
    var cookie = GDN.Base64.Decode(GDN.Cookie.Get(this.Name));

    // get cookie parts
    var pairs = cookie.split('~');
    
    for (var i = 0; i < pairs.length; i++)
    {
      // get name/value pair
      var pair = pairs[i].split(':');

      // return value if match is found
      if (key == pair[0])
        return pair[1];
    }

    return null;
  },
  
  /// <summary>
  /// Sets a value in the cookie using the specified key and value.
  /// </summary>
  /// <param name="key">The key for the value.</param>
  /// <param name="value">The value to set.</param>
  SetValue : function(key, value)
  {
    // check if cookie exists
    if (GDN.Cookie.Exists(this.Name))
    {
      // get cookie
      var cookie = GDN.Base64.Decode(GDN.Cookie.Get(this.Name));

      // get cookie parts
      var pairs = cookie.split('~');

      // key flag
      var keyExists = false;

      for (var i = 0; i < pairs.length; i++)
      {
        // get name/value pair
        var pair = pairs[i].split(':');

        // update value if it exists
        if (key == pair[0])
        {
          keyExists = true;
          pairs[i] = pair[0] + ":" + value;
        }
      }

      // append value
      if (!keyExists)
        pairs.push(key + ":" + value);

      // join name/value pairs
      cookie = pairs.join('~');
    }
    else
      cookie = key + ":" + value;

    // set cookie
    GDN.Cookie.Set(this.Name, GDN.Base64.Encode(cookie));
  }
};
/// <summary>
/// The Widget type provides methods for handling widgets. 
/// </summary>
GDN.Widget =
{
  // properties
  Code    : null,
  Element : null,
  Name    : null,
  Ref     : null,
  Type    : null,
  Url     : null,
  Var     : null,
  Pos     : null,
  Width   : 350,
  Height  : 250,
    
  /// <summary>
  /// Executes when a widget is loaded.
  /// </summary>
  Callback : function()
  {  
    // execute code
    if (GDN.Widget.Code)
      eval(GDN.Base64.Decode(GDN.Widget.Code));
    
    // show widget
    if (GDN.Widget.Type == "popup")
    {
      GDN.Widget.Show(eval(GDN.Widget.Var), GDN.Widget.Width, GDN.Widget.Height,
        GDN.Widget.Ref, GDN.Widget.Pos);
    }
    else
      GDN.SetInnerHtml(eval(GDN.Widget.Element), eval(GDN.Widget.Var));
  },

  /// <summary>
  /// Closes a popup widget.
  /// </summary>
  Close : function()
  {
    try { cClick(); } catch (e) {}
  },
  
  /// <summary>
  /// Gets the footer content for a widget.
  /// </summary>
  GetFooter : function()
  {
    return '<a href=\"' + gdn_tos_url + '\">Terms of Service</a> | '
    + '<a href=\"' + gdn_pp_url + '\">Privacy Policy</a> | '
    + '<a href=\"' + gdn_faq_url + '\">FAQ</a> | '
    + '<a href=\"' + gdn_feedback_url + '\">Feedback</a>'
    + '<hr class=\"GDNLine\" />'
    + GDN.Widget.GetCloseWindow();
  },
  
  /// <summary>
  /// Gets the close window link for the popup widgets.
  /// </summary>
  GetCloseWindow : function()
  {
    return '<a href=\"javascript:GDN.Widget.Close();\">Close this window</a>';
  },
  
  /// <summary>
  /// Loads a widget and executes a callback handler if specified.
  /// </summary>
  Load : function()
  {
    // get common arguments
    this.Type    = arguments[0];
    this.Name    = arguments[1];
    this.Var     = unescape(arguments[2]);
    this.Url     = GDN.getPath(this.Name, "UAWidgets"); 
  
    // get additional arguments by type
    if (this.Type == "popup"){
      this.Width  = arguments[3];
      this.Height = arguments[4];
      this.Code   = arguments[5];
      this.Ref    = (arguments[6]) ? arguments[6] : "UAWidgetRef-PopUp";
      this.Pos    = arguments[7];
    }else { 
      this.Element = arguments[3];
      this.Code    = arguments[4];
    }
  
    // determine if widget is already loaded
    if (GDN.IsNullOrEmpty(eval(this.Var))){
      // add callback handler
      GDN.Callback.Add(GDN.Widget.Callback);
      // load required files by type
      if (this.Name != "LoggedIn" && this.Name != "LoggedOut")
        GDN.LoadFile("UI");
      // get widget file if it has not been loaded
      if (!GDN.Rpc.IsLoaded(this.Url))
        GDN.Rpc.Send(this.Url);
    }else{
      // invoke callback handler
      GDN.Widget.Callback();
      if (this.Name == "LoggedIn")
      {
        // get elements
        var pluckPersonaImg = document.getElementById("PluckPersonaImg");
        var avatarImg       = document.getElementById("AvatarImg");
        var screenName      = document.getElementById("ScreenName");
        var pluckPersona    = document.getElementById("PluckPersona");
        var pluckPhotos     = document.getElementById("PluckPhotos");
        var pluckBlogs      = document.getElementById("PluckBlogs");
        
        // update values
        pluckPersonaImg.href = GDN.AppendParam(gdn_persona_url, "U", GDN.Cookies.Pluck.GetValue("UserId"));
        pluckPersona.href    = GDN.AppendParam(gdn_persona_url, "U", GDN.Cookies.Pluck.GetValue("UserId"));
        pluckPhotos.href     = GDN.AppendParam(gdn_photos_url, "U", GDN.Cookies.Pluck.GetValue("UserId"));
        pluckBlogs.href      = GDN.AppendParam(gdn_blogs_url, "U", GDN.Cookies.Pluck.GetValue("UserId"));
        
        avatarImg.src = GDN.Avatar();
        GDN.SetInnerHtml("ScreenName", "hi, " + GDN.Cookies.GDN.GetValue("UserName") + "!");
      }
    }
  },
  
  /// <summary>
  /// Shows the specified popup widget.
  /// </summary>
  /// <param name="widget">The HTML of the widget to display.</param>
  /// <param name="width">The width of the widget.</param>
  /// <param name="height">The height of the widget.</param>
  /// <param name="ref">The name of the element referenced as a popup corner.</param>
  Show : function(widget, width, height, ref)
  {
    // get position
    if (GDN.IsNullOrEmpty(arguments[4]))
      var position = "UL";
    else
      var position = arguments[4];
  
    // show widget
    GDN.LoadFile("UI"); 
    (function(){ 
    if(typeof overlib != 'function')
    	return setTimeout(arguments.callee, 100); 
    try
    {
      overlib(widget, STICKY, WIDTH, width, HEIGHT, height,
        REF, ref, REFC, position, REFP, position,
        REFX, 0, REFY, 0, BGCLASS, "UAWidget-PopUpBorder",
        FGCLASS, "UAWidget-PopUpBg");
    }
    catch (e) { 
    	setTimeout(arguments.callee, 100); 
    }
    })(); 
  }
};
// handle UA events for Pluck
function PluckUAEvent(eventId)
{
  switch (eventId)
  {
    // handles log outs
    case "Out":
    {
      // clear avatar for Pluck 
      try
      {
        gsl.personaHref = null;
      }
      catch (e) {}
    }
    break;

    // handles cancellations
    case "Cancel":
    {
      // clear avatar for Pluck 
      try
      {
        gsl.personaHref = null;
      }
      catch (e) {}
    }
    break;
  }
}
 
// register events
GDN.Api.Register(PluckUAEvent, "Out", "Logout");
GDN.Api.Register(PluckUAEvent, "Cancel", "Cancel");

// handle UA events for Saxotech
function SaxotechUAEvent(eventId)
{
  switch (eventId)
  {
    // handles log outs
    case "Out":
    {
      // remove Saxotech session cookie
      GDN.Cookie.Remove("PBCSSESSIONID");
      GDN.Cookie.Remove("PBCSSESSIONID", "/", "", true);
      GDN.Cookie.Remove("PBCSSESSIONID", "/", "." + gdn_site_url, true);
    }
	  break;
	// handles writing out Search link
	case "Search":
	{
	  GDN.SetInnerHtml("CustomLinks", UserSearchLink);
	}
	  break;
	// handles Newsletters log in
	case "NLLogin":
	{
	  if(NLSigninOnly)
	  {
		NLetersRedirect("nlettersubscribe");
	  }
	  else
	  {
		updateNlettersSubscription("SignIn");
	  }
	}
	  break;
	// handles Newsletters log in
	case "NLRegister":
	{
		if (GDN.Cookie.Exists("GDNNL")) 
		{
			updateNlettersSubscription("Register");
		}
		else
		{
			NLetersRedirect("nlettererror");
		}
	  
	}
	  break;
  }
}
 
// register events
GDN.Api.Register(SaxotechUAEvent, "Out", "Logout");

if(typeof gdn_enable_search != 'undefined' && gdn_enable_search) 
{
GDN.Api.Register(SaxotechUAEvent, "Search", "LoggedOut");
GDN.Api.Register(SaxotechUAEvent, "Search", "LoggedIn");
}

function GoToPDSearch()
{
	location.href='http://'+PDURL+'/sp?aff=1171&skin='+PDSKIN+'&keywords='+document.PDSearch.keywords.value;
}

var UserSearchPopup = 
gdn_Widgets['UserSearch']= 
'<div align=\"center\" class=\"UAWidget-PopUp\">'  
  + '  <div align=\"left\">'
  + '    <h3>Search People</h3>'
  + '    <span>Search screen names, real names, and profile information.</span>'
  + '  </div>'
  + '  <br />'
  + '  <form id=\"UAWidget-Search\" method=\"get\" name=\"PDSearch\" action=\"javascript:GoToPDSearch();\"  >'
  + '    <table border=\"0\" cellpadding=\"0\" cellspacing=\"10\">'
  + '    <tr>'
  + '      <td align=\"right\" nowrap=\"nowrap\" style=\"vertical-align: middle;\"><label for=\"keywords\">Keywords:</label></td>'
  + '      <td align=\"left\" style=\"vertical-align: middle;\"><input type=\"text\" id=\"keywords\" name=\"keywords\" size=\"30\" /></td>'
  + '      <td align=\"middle\"><img src=\"/graphics/button_go.gif\" OnClick=\"GoToPDSearch()\" alt=\"Go\" border=\"0\" style=\"padding-left: 3px\" /></a></td>'
  + '    </tr>'
  + '    </table>'
  + '	<br>'
  + '  <div align=\"center\">' + GDN.Widget.GetCloseWindow() + '</div>'
  + '   </form>';
   
var UserSearchLink = "| <a href=\"javascript:GDN.Widget.Show(UserSearchPopup,350,50,'UAWidgetRef-PopUp');\" ><b>Search people</b></a>";
  
/// <summary>
/// The Browser type provides methods for detecting Web browser types and
/// versions. 
/// </summary>
GDN.UR.Browser =
{
  /// <summary>
  /// Gets a BrowserType object from the specified entry.
  /// </summary>
  /// <param name="data">The browser and OS identification data.</param>
  Get : function(data)
  {
    // initialize BrowserType object
    var browserType = new GDN.UR.BrowserType();    
  
    // get browser parts
    var parts = data.split("|");

    for (var i = 0; i < parts.length; i++)
    {
      switch (i)
      {
        case 0: browserType.Name      = parts[i]; break;
        case 1: browserType.Condition = parts[i]; break;
        case 2: browserType.Version   = parseFloat(parts[i]); break;
        case 3: browserType.Os        = parts[i]; break;
      }
    }
    
    return browserType;
  },

  /// <summary>
  /// Initializes the Browser object and sniffs the user's browser to
  /// determine the type and version.
  /// </summary>
	Init : function ()
	{
	  // get browser name
		this.Browser = this.SearchString(this.BrowserData) || null;
		
		// get browser version
		this.Version = this.SearchVersion(navigator.userAgent)
			|| this.SearchVersion(navigator.appVersion)
			|| null;
			
	  // get operating system
		this.Os = this.SearchString(this.OsData) || null;
	},
	
	/// <summary>
  /// Determines if the current Web browser is supported.
  /// </summary>
  IsSupported : function()
  {
    var isSupported = false;
    
    for (var i = 0; i < gdn_browsers.length; i++)
    {
      // get browser
      var browser = this.Get(gdn_browsers[i]);
      
      if (this.Browser && this.Os)
      {
        if (this.Browser == browser.Name && this.Os == browser.Os)
        {
          // check double equal sign operator
          if (browser.Condition == "=")
            browser.Condition = "==";
            
          // get comparison
          var comparison = "parseFloat(" + this.Version + ") " +
              browser.Condition + " parseFloat(" + browser.Version + ")";
            
          // check version
          try
          {
            if (eval(comparison))
            {
              isSupported = true;
              break; 
            }
          }
          catch (e) {}
        }
      }
    }

    return isSupported;
  },
	
	/// <summary>
  /// Determines the type of Web browser and OS being used.
  /// </summary>
  /// <param name="data">The browser and OS identification data.</param>
	SearchString : function(data)
	{
		for (var i = 0; i < data.length; i++)
		{
		  // get names
			var browser = data[i].String;
			var os      = data[i].Prop;
			
			// get version
			this.VersionSearchString = data[i].VersionSearch || data[i].Identity;
			
			// determine browser and OS names
			if (browser)
			{
				if (browser.indexOf(data[i].SubString) != -1)
					return data[i].Identity;
			}
			else if (os)
				return data[i].Identity;
		}
	},
	
	/// <summary>
  /// Determines the version of the Web browser and OS being used.
  /// </summary>
  /// <param name="data">The browser and OS identification data.</param>
	SearchVersion : function(data)
	{
		var index = data.indexOf(this.VersionSearchString);
		if (index == -1) return;
		return parseFloat(data.substring(index + this.VersionSearchString.length + 1));
	},
	
	/// <summary>
  /// The BrowserData type provides a data structure for Web browsers.
  /// </summary>
	BrowserData:
	[
	  // Apple Safari
		{
			String    : navigator.vendor,
			SubString : "Apple",
			Identity  : "Safari"
		},

		// Firefox
		{
			String    : navigator.userAgent,
			SubString : "Firefox",
			Identity  : "Firefox"
		},

		// iCab
		{
			String    : navigator.vendor,
			SubString : "iCab",
			Identity  : "iCab"
		},

		// Internet Explorer
		{
			String        : navigator.userAgent,
			SubString     : "MSIE",
			Identity      : "Explorer",
			VersionSearch : "MSIE"
		},

		// Konqueror
		{
			String    : navigator.vendor,
			SubString : "KDE",
			Identity  : "Konqueror"
		},

		// Mozilla
		{
			String        : navigator.userAgent,
			SubString     : "Gecko",
			Identity      : "Mozilla",
			VersionSearch : "rv"
		},

		// Netscape (6+)
		{
			String    : navigator.userAgent,
			SubString : "Netscape",
			Identity  : "Netscape"
		},

		// Netscape (4-)
		{
			String        : navigator.userAgent,
			SubString     : "Mozilla",
			Identity      : "Netscape",
			VersionSearch : "Mozilla"
		},

		// Opera
		{
			Prop     : window.opera,
			Identity : "Opera"
		}
	],
	
	/// <summary>
  /// The BrowserData type provides a data structure for operating systems.
  /// </summary>
	OsData :
	[
		// Linux
		{
			String    : navigator.platform,
			SubString : "Linux",
			Identity  : "Linux"
		},
	
		// Mac
		{
			String    : navigator.platform,
			SubString : "Mac",
			Identity : "Mac"
		},
		
	  // Windows
		{
			String    : navigator.platform,
			SubString : "Win",
			Identity : "Windows"
		}
	]
};

// initialize
GDN.UR.Browser.Init();
/// <summary>
/// The BrowserType type defines a strongly typed data structure for a Web
/// browser.
/// </summary>
GDN.UR.BrowserType = function()
{
  // data members
  var _condition = null;
  var _name      = null;
  var _os        = null;
  var _version   = null;

  // properties
  this.Condition = function() { if (arguments[0]) _condition = arguments[0]; else return _condition; };
  this.Name      = function() { if (arguments[0])      _name = arguments[0]; else return _name; };
  this.Os        = function() { if (arguments[0])        _os = arguments[0]; else return _os; };
  this.Version   = function() { if (arguments[0])   _version = arguments[0]; else return _version; }
};

/// <summary>
/// Gets the number of days between two dates.
/// </summary>
/// <param name="date1">The first date to compare.</param>
/// <param name="date2">The second date to compare.</param>
GDN.GetDays = function(date1, date2)
{
  // get elements of first date
  var year1  = date1.substring(0, 4);
  var month1 = date1.substring(4, 6) - 1;
  var day1   = date1.substring(6, 8);
    
  // get elements of second date
  var year2  = date2.substring(0, 4);
  var month2 = date2.substring(4, 6) - 1;
  var day2   = date2.substring(6, 8);
  
  // initialize Date objects
  var startDate = new Date(year1, month1, day1);
  var endDate   = new Date(year2, month2, day2);
  
  // set time for one day in milliseconds
  var day = 1000 * 60 * 60 * 24;

  // get number of days
  return Math.abs(Math.ceil((endDate.getTime() - startDate.getTime()) / (day)));
};
/// <summary>
/// Shows or hides occupational fields.
/// </summary>
/// <param name="form">A reference to the form object.</param>
GDN.ToggleOccupations = function(form)
{
  // get selected occupation
  var occupation = form.Occupation.options[form.Occupation.selectedIndex].text;
  
  if (occupation == "Student/Intern" ||
    occupation == "Retired" ||
    occupation == "Not Employed")
  {
    form.Industry.selectedIndex = 0;
    form.CompanySize.selectedIndex = 0;
    
    this.Toggle("IndustryRow", "hide");
    this.Toggle("CompanySizeRow", "hide");
  }
  else
  {
    this.Toggle("IndustryRow", "show");
    this.Toggle("CompanySizeRow", "show");
  }
};

/// <summary>
/// Gets the absolute URL of the ZAG form.
/// </summary>
GDN.ZagFormUrl = function()
{
  // get absolute URL to ZAG form
  var url = GDN.CombinePath(gdn_site_url, gdn_zag_form_url);

  // append destination parameter
  return GDN.AppendParam(url, "Destination", GDN.Request.QueryString("Destination"));
};
/// <summary>
/// The GCION type provides methods for handling the GCION cookie.
/// </summary>
GDN.Cookies.GCION =
{
  /// <summary>
  /// Gets the format of the cookie for COPPA.
  /// </summary>
  CoppaFormat: "{gcionid}~{version}~{date_created}~{status}~",
    
  /// <summary>
  /// Gets the number of days before the cookie expires.
  /// </summary>
  Expires: 365,

  /// <summary>
  /// Gets the name of the cookie.
  /// </summary>
  Name: "GCIONID",
  
  /// <summary>
  /// Gets the format of the post-ZAG cookie.
  /// </summary>
  PostZagFormat: "{gcionid}~{version}~{date_created}~{status}~"
    + "zip:{zip}|yob:{yob}|gen:{gen}|cou:{cou}|sit:{sit}|"
    + "adr:{adr}|ind:{ind}|job:{job}|siz:{siz}",
    
  /// <summary>
  /// Gets the format of the pre-ZAG cookie.
  /// </summary>
  PreZagFormat: "{gcionid}~{version}~{date_created}~{status}~"
    + "ses:{ses}",

  /// <summary>
  /// Gets the version of the cookie.
  /// </summary>
  Version: "1",

  /// <summary>
  /// Gets a User object populated with data from the cookie.
  /// </summary>
  Get : function()
  {
    // initialize User object
    var user = new GDN.UR.User();
    // get properties
    user.CompanySize(this.GetValue("CompanySize"));
    user.Country(this.GetValue("Country"));
    user.Email(this.GetValue("Email"));
    user.GcionId(this.GetValue("GcionId"));
    user.Gender(this.GetValue("Gender"));
    user.Industry(this.GetValue("Industry"));
    user.Occupation(this.GetValue("Occupation"));
    user.Sessions(this.GetSessions());
    user.Site(this.GetValue("Site"));
    user.Status(this.GetValue("Status"));
    user.Yob(this.GetValue("Yob"));
    user.Zip(this.GetValue("Zip"));
    
    return user;
  },
  
  /// <summary>
  /// Gets a match from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetMatch : function(key)
  {
    switch (key)
    {
      case "CompanySize" : return "siz";
      case "Country"     : return "cou";
      case "Email"       : return "adr";
      case "Gender"      : return "gen";
      case "Industry"    : return "ind";
      case "Occupation"  : return "job";
      case "Sessions"    : return "ses";
      case "Site"        : return "sit";
      case "Yob"         : return "yob";
      case "Zip"         : return "zip";
    }

    return null;
  },
  
  /// <summary>
  /// Gets a Session object populated with data from the cookie.
  /// </summary>
  /// <param name="entry">The session entry to retrieve.</param>
  GetSession : function(entry)
  {
    // check for no entry
    if (GDN.IsNullOrEmpty(entry)) return null;
          
    if (entry.indexOf("#") != -1)
    {
      // get entry
      entry = entry.split('#');
          
      // initialize Session object
      var session = new GDN.UR.Session();

      // set properties
      session.Id(entry[0]);
      session.Date(entry[1]);
      session.PageViews(entry[2]);
      session.SectionFront(entry[3]);
          
      return session;
    }
    else
      return null;
  },
  
  /// <summary>
  /// Gets an array of Session objects populated with data from the cookie.
  /// </summary>
  GetSessions : function()
  {
    // get session entries
    var entries = this.GetValue("Sessions");

    // check for no entries
    if (GDN.IsNullOrEmpty(entries)) return null;
    
    if (entries.indexOf("$") != -1)
    {
      // get entries
      entries = entries.split('$');
      
      // initialize Session object array
      var sessions = [];
      
      // get each Session object
      for (var i = 0; i < entries.length; i++)
        sessions.push(this.GetSession(entries[i]));
      
      return sessions;
    }
    else
      return new Array(this.GetSession(entries));
  },
  
  /// <summary>
  /// Gets a value from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetValue : function(key)
  {
    // ensure cookie exists
    if (!GDN.Cookie.Exists(this.Name)) return null;

    // get cookie
    var cookie = GDN.Base64.Decode(GDN.Cookie.Get(this.Name));

    // get cookie parts
    var parts = cookie.split('~');
    
    switch (key)
    {
      case "GcionId"     : return parts[0];
      case "Version"     : return parts[1];
      case "DateCreated" : return parts[2];
      case "Status"      : return parts[3];
      default:
        {
          if (parts.length == 5)
          {
            // get name/value pairs
            var pairs = parts[4].split('|');
          
            // get match
            var match = this.GetMatch(key);

            for (var i = 0; i < pairs.length; i++)
            {
              // get name/value pair
              var pair = pairs[i].split(':');

              // return value if match is found
              if (match == pair[0])
                return pair[1];
            }
          }
          else
            return null;
        }
        break;
    }

    return null;
  },

  /// <summary>
  /// Sets a cookie using data from the specified User object.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  /// <param name="zagState">A value indicating a user's ZAG state.</param>
  Set : function(user, zagState){
     // populate cookie
      var 
      	cookie = zagState === GDN.UR.UserStatus.UnderAge ? 
		this.CoppaFormat :  
      		(
			zagState == GDN.UR.UserStatus.IdentifierCreated ? 
      				this.PreZagFormat : this.PostZagFormat
		),
	_email= user.Email(), 
	_ind= user.Industry(), 
	_occ= user.Occupation(), 
	_csz= user.CompanySize()
	;
      cookie = cookie.replace(/{gcionid}/gi, user.GcionId());
      cookie = cookie.replace(/{date_created}/gi, GDN.GetCreationDate());
      cookie = cookie.replace(/{version}/gi, this.Version);
      cookie = cookie.replace(/{status}/gi, user.Status());
      cookie = cookie.replace(/{zip}/gi, user.Zip());
      cookie = cookie.replace(/{yob}/gi, user.Yob());
      cookie = cookie.replace(/{gen}/gi, user.Gender());
      cookie = cookie.replace(/{cou}/gi, user.Country());
      cookie = cookie.replace(/{sit}/gi, user.Site());
      cookie = GDN.IsNullOrEmpty(_email)? 
		cookie.replace(/\|adr:{adr}/gi, "") :
      		cookie.replace(/{adr}/gi, _email) 
	;
      cookie = GDN.IsNullOrEmpty(_ind) ? 
		cookie.replace(/\|ind:{ind}/gi, "") :
      		cookie.replace(/{ind}/gi, _ind)
	;
      cookie = GDN.IsNullOrEmpty(_occ)  ? 
		cookie.replace(/\|job:{job}/gi, "") : 
      		cookie.replace(/{job}/gi, _occ) 
	;
      cookie = GDN.IsNullOrEmpty(_csz) ? 
		cookie.replace(/\|siz:{siz}/gi, "") : 
      		cookie.replace(/{siz}/gi, _csz) 
	;
      cookie = cookie.replace(/{ses}/gi, this.SetSessions(user.Sessions()));
    GDN.Cookie.Set(this.Name, GDN.Base64.Encode(cookie), this.Expires);
  },
  
  /// <summary>
  /// Creates a list of session entries to set in the cookie.
  /// </summary>
  /// <param name="sessions">An array of Session objects populated with data.</param>
  SetSessions : function(sessions)
  {  
    var entries = "";

    for (var i = 0; i < sessions.length; i++)
    {
      if (i == (sessions.length - 1))
      {
        entries += sessions[i].Id() + "#" +
          sessions[i].Date() + "#" +
          sessions[i].PageViews() + "#" +
          sessions[i].SectionFront();
      }
      else
      {
        entries += sessions[i].Id() + "#" +
          sessions[i].Date() + "#" +
          sessions[i].PageViews() + "#" +
          sessions[i].SectionFront() + "$";
      }
    }
    
    return entries;
  }
};
/// <summary>
/// The Intercept type provides methods for intercepting links.
/// </summary>
GDN.REQUIRED_PAGES= { frontpage: "frontpage", section: "section"};
GDN.UR.Intercept =
{
  /// <summary>
  /// Gets a value indicating if links can be intercepted.
  /// </summary>
  CanIntercept : function()
  {  
    // check if current URL is ZAG form
    if (window.location.href == GDN.ZagFormUrl())
      return false;

    var 
    	canIntercept = false, 
	required_pages= GDN.REQUIRED_PAGES,
	count=0, 
	user= GDN.Cookies.GCION.Get(), 
	sessions= user.Sessions(),
	session= null,
	days= 0,
	gdn_sessions= "gdn_sessions" in window ? 
		window["gdn_sessions"] : 30, 
	gdn_page_views= "gdn_page_views" in window ? 
		window["gdn_page_views"] : 3, 
	gdn_days= "gdn_days" in window ? window["gdn_days"] : 7
    	;

    for (var i = 0, l= sessions.length; i < l; i++){
      session= sessions[i]; 
      if (i != 0){
        days = 
		GDN.GetDays(
			user.Sessions()[i - 1].Date(),
          		session.Date()
		);
        if (days <= gdn_days){
          count++;
          if (
	  	count >= gdn_sessions && 
		session.PageViews() >= (gdn_page_views - 1) && 
		session.SectionFront() in required_pages
	  ){
                canIntercept = true;
		break; 
          }
        }else{ 
          if (i == 1)
            count = 1;
          else
            count = 0;
        }
      }else{ 
        count++;
        if (
		gdn_sessions == 1 && 
		session.PageViews() >= (gdn_page_views - 1) && 
		session.SectionFront() in required_pages
        ){
		canIntercept= true; 
		break; 
        }
      }
    }
    return canIntercept;
  },

  /// <summary>
  /// Changes the href property of the specified Link object.
  /// </summary>
  /// <param name="link">The Link object to change.</param>
  /// <param name="href">The URL of the link to change.</param>
  ChangeLink : function(link, href)
  {
    // get text of link
    var innerText = link.innerText;
    
    // change href
    link.href = href;
    
    // only change link text if it was changed
    if (link.innerText != innerText)
      link.innerText = innerText;
  },

  /// <summary>
  /// Escapes special characters used in regular expressions.
  /// </summary>
  /// <param name="value">The value to escape.</param>
  EscapeRegEx : function(value)
  {
    if (!arguments.callee.sRE)
    {
      var specials = ['/'];
      arguments.callee.sRE = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
    }
    
    return value.replace(arguments.callee.sRE, '\\$1');
  },
  
  /// <summary>
  /// Gets a regular expression for an exception.
  /// </summary>
  /// <param name="ex">The exception to retrieve as a regular expression.</param>
  GetRegEx : function(ex)
  {  
    // check for absolute URLs
    if (ex.indexOf("http") == -1)
    {
      // check for leading forward slash
      if (ex.charAt(0) != "/")
        ex = location.protocol + "//" + location.host + "/" + ex;
      else
        ex = location.protocol + "//" + location.host + ex;
    }
  
    // get index
    var index = ex.indexOf("*");
    
    // check for special asterisk wildcard
    if (index != -1 && index == ex.length)
    {
      var prefix = ex.substring(0, index);
      var suffix = ex.substring(index + 1, ex.length);
      ex = prefix + "([a-zA-Z0-9_-]{1,})" + suffix;
    }
 
    return "/" + this.EscapeRegEx(ex) + "/i";
  },

  /// <summary>
  /// Intercepts any links that are not defined as exceptions.
  /// </summary>
  InterceptLinks : function()
  {
    // get links
    var 
    	links = document.links,
	href= "", 
	canIntercept= false, 
        useInclusion = typeof gdn_use_inclusion == 'undefined' ? 
	 	false : 
	 	gdn_use_inclusion
   ;
     
    for (var i = 0, l= links.length; i < l; i++)
    {
      // ignore links defined as targets
      if (
      	GDN.IsNullOrEmpty(links[i].target) && 
        links[i].href.indexOf(location.hostname) != -1
      ){
          if (useInclusion)
            canIntercept = !(this.IsException(links[i].href, gdn_local_ex));
          else
            canIntercept = this.IsException(links[i].href, gdn_local_ex);
      }else{
        canIntercept = !(this.IsException(links[i].href, gdn_ext_ex));
      }
      if(!canIntercept) continue; 
      if (gdn_zag_form_url.indexOf("?") == -1)
        href = links[i].href.replace(gdn_zag_form_url + "?Destination=", "");
      else
        href = links[i].href.replace(gdn_zag_form_url + "&Destination=", "");
      // intercept link
        href = GDN.AppendParam(
      		GDN.CombinePath(gdn_site_url, gdn_zag_form_url),
        	"Destination", 
		escape(href)
	);
        this.ChangeLink(document.links[i], href);
    }
  },
  
  /// <summary>
  /// Determines if the specified link needs to be intercepted.
  /// </summary>
  /// <param name="href">The URL of the link to check.</param>
  /// <param name="ex">An array of exceptions to check.</param>
  IsException : function(href, ex)
  {
    // ignore any javascript links
    if (href.toLowerCase().substring(0, 11) == "javascript:")
      return true;

    var isException = true;

    for (var i = 0; i < ex.length; i++)
    {
      if (!GDN.IsNullOrEmpty(ex[i]))
      {
        // get regular expression
        var exception = new RegExp(eval(this.GetRegEx(ex[i])));
        
        // test link
        if (exception.test(href))
        {
          isException = false;
          break;
        }
      }
    }
    
    return isException;
  }
};
/// <summary>
/// The Page type provides methods for handling page events.
/// </summary>
GDN.UR.Page =
{
  /// <summary>
  /// Executes when it is determined links can be intercepted.
  /// </summary>
  Intercept : function()
  {
    // get user
    var user = GDN.Cookies.GCION.Get();
    
    if (user.Status() == GDN.UR.UserStatus.IdentifierCreated)
    {
      // update session
      GDN.UR.Page.UpdateSession();
      
      // intercept links
      if (GDN.UR.Intercept.CanIntercept())
      {
        // validate user before intercepting links
        GDN.LoadFile("ValidateUser", "UREvents");
      }
    }
  },

  /// <summary>
  /// Executes when the page loads.
  /// </summary>
  Load : function()
  {
    // only execute if browser is supported
    if (!GDN.UR.Browser.IsSupported())return; 
    // load files for ZAG form
    if (document.getElementById("URWidget-Zag"))
      GDN.LoadFile("ZagUser", "UREvents");
    // create user if cookie does not exist
    if (GDN.Cookie.Exists(GDN.Cookies.GCION.Name)){
      // create user if identifier does not exist
      if (GDN.IsNullOrEmpty(GDN.Cookies.GCION.GetValue("GcionId"))){
        GDN.LoadFile("CreateUser", "UREvents");
      }else{
        GDN.UR.Page.PreZag();
      }
    }else{
      GDN.LoadFile("CreateUser", "UREvents");
    }
    
  },
  
  /// <summary>
  /// Executes before a user is zagged.
  /// </summary>
  PreZag : function()
  {
    // get user
    var user = GDN.Cookies.GCION.Get();
    if (user.Status() != GDN.UR.UserStatus.IdentifierCreated){
      GDN.UR.Page.PostZag();
    }else{
      // refresh cookie if identifier is passed
      if (!GDN.IsNullOrEmpty(GDN.Request.QueryString("GID"))){
        var gcionId = GDN.Request.QueryString("GID");
        if (user.GcionId() != gcionId)
        {
          if (gcionId == "0")
          {
            user.Yob(new Date().getFullYear());
            GDN.Cookies.GCION.Set(user, GDN.UR.UserStatus.UnderAge);
          }
          else
            GDN.LoadFile("GetUser", "UREvents");
        }
      }
      else
        GDN.UR.Page.Intercept();
    }
  },
  
  /// <summary>
  /// Executes after a user is zagged.
  /// </summary>
  PostZag : function()
  {
    if (GDN.IsNullOrEmpty(GDN.Cookies.Session.GetValue("ref")))
    {
      // refresh cookie once per browser session
      GDN.LoadFile("GetUser", "UREvents");
    }
    
    // add session refresh value
    GDN.Cookies.Session.SetValue("ref", 0);
  },
  
  /// <summary>
  /// Executes when session information must be updated.
  /// </summary>
  UpdateSession : function()
  {
    // get user
    var 
    	user = GDN.Cookies.GCION.Get(),
	sectionFront= GDN.REQUIRED_PAGES[gdn_section_front] || null 
    ;
    if (GDN.IsNullOrEmpty(GDN.Cookies.Session.GetValue("ses")))
    {
      // add session
      user.AddSession(sectionFront);
      
      // set session number
      GDN.Cookies.Session.SetValue("ses", user.Sessions().length);
    }
    else
    {
      // update session
      user.UpdateSession(user.Sessions().length, sectionFront);
    }
    
    // set cookie
    GDN.Cookies.GCION.Set(user, GDN.UR.UserStatus.IdentifierCreated);
  }
};
GDN.UR.Session = function(){
	var _a= { 
		Date: null, 
		Id: 0, 
		PageViews: 0, 
		SectionFront: null
	};
  	function accessor(key){
  		return function(value){ 
  			if(value) 
				return _a[key]= value; 
			else 
				return _a[key]; 
		}
  	}
  	for (var k in _a) 
  		this[k]= accessor(k); 
};
GDN.UR.User = function()
{
  // data members
  var _a= { 
  	CompanySize: null, 
	Country: null, 
	Email: null, 
	GcionId: null, 
	Gender: null, 
	Industry: null, 
	Occupation: null, 
	Sessions: [], 
	Site: null, 
	Status: 0, 
	Yob: 0, 
	Zip: null
  }
  this.attributes= _a; 
  function accessor(key){
  	return function(value){ 
  		if(value) 
			return _a[key]= value; 
		else 
			return _a[key]; 
	}
  }
  for (var k in _a) 
  	this[k]= accessor(k); 
  // methods
  this.AddSession    = AddSession;
  this.GetSession    = GetSession;
  this.RemoveSession = RemoveSession;
  this.UpdateSession = UpdateSession;
  if (typeof arguments[0] == 'object')
    Init(arguments[0]);

  function Init(o){
  	for(var k in o)
		_a[k]= o[k]; 
  }
  function AddSession(sectionFront)
  {
  	var _sessions= this.Sessions(); 
    if ((_sessions.length + 1) >= gdn_MaxSessions)
      this.RemoveSession();
    var session = new GDN.UR.Session();
    session.Date(GDN.GetCreationDate());
    session.Id(_sessions.length + 1);
    session.PageViews(1);
    session.SectionFront(sectionFront);
    _sessions.push(session);
  }
 function GetSession(id)
  {
  	var _sessions= this.Sessions(); 
    for (var i = 0; i < _sessions.length; i++)
    {
      if (id == _sessions[i].Id())
        return _sessions[i];
    }
  }
  function RemoveSession()
  {
    // remove oldest session entry
  	var _sessions= this.Sessions(); 
    _sessions.shift();
  }
  function UpdateSession(id, sectionFront)
  {
  	var _sessions= this.Sessions(); 
    for (var i = 0; i < _sessions.length; i++)
    {
      if (id == _sessions[i].Id())
      {
        _sessions[i].PageViews(parseInt(_sessions[i].PageViews()) + 1);
        if (_sessions[i].SectionFront() != "frontpage" &&
          _sessions[i].SectionFront() != "section")        
            _sessions[i].SectionFront(sectionFront);
        
        break;
      }
    }
  }
};

/// <summary>
/// The UserProvider type provides methods for handling user transactions.  
/// </summary>
GDN.UR.UserProvider =
{
  /// <summary>
  /// Creates the specified user.
  /// </summary>
  Create : function()
  {
    // command text
    var querystring = "q=3&c=1&NoCookie=1";

    // create user
    GDN.Rpc.Send(GDN.RegUrl(querystring));
  },
  
  /// <summary>
  /// Gets the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Get : function(user)
  {
    // command text
    var querystring = "q=3&c=1&NoCookie=1&";
    
    // append required parameters
    querystring = GDN.AppendParam(querystring, "GCIONID", user.GcionId());

    // get user
    GDN.Rpc.Send(GDN.RegUrl(querystring));
  },
  
  /// <summary>
  /// Updates ZAG data for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  UpdateZag : function(user)
  {
    // command text
    var querystring = "q=4&c=1&NoCookie=1&";
  
    // get cookie
    var cookie = GDN.Cookies.GCION.Get();

    // check for non-required zip code
    if (user.Country() != "us")
      user.Zip("00000");
      
    // append required parameters
    querystring = GDN.AppendParam(querystring, "Country", user.Country());
    querystring = GDN.AppendParam(querystring, "GCIONID", GDN.Cookies.GCION.GetValue("GcionId"));
    querystring = GDN.AppendParam(querystring, "Gender", user.Gender());
    querystring = GDN.AppendParam(querystring, "OriginatingSite", escape(gdn_reg_site_code));
    querystring = GDN.AppendParam(querystring, "YOB", user.Yob());
    querystring = GDN.AppendParam(querystring, "Zip", user.Zip());
    
    // append optional parameters
    if (gdn_occupation_required)
    {
      if (user.Occupation())
      {
        querystring = GDN.AppendParam(querystring, "Occupation", user.Occupation());
      
        if (occupation != "Student/Intern" &&
          occupation != "Retired" &&
          occupation != "Not Employed")
        {
          querystring = GDN.AppendParam(querystring, "Industry", user.Industry());
          querystring = GDN.AppendParam(querystring, "CompanySize", user.CompanySize());
        }
      }
    }

    // update ZAG data
    GDN.Rpc.Send(GDN.RegUrl(querystring));
  },
  
  /// <summary>
  /// Validates the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Validate : function(user)
  {
    // command text
    var querystring = "q=3&c=1&NoCookie=1&";
    
    // append required parameters
    querystring = GDN.AppendParam(querystring, "GCIONID", user.GcionId());

    // validate user
    GDN.Rpc.Send(GDN.RegUrl(querystring));
  },

  /// <summary>
  /// Creates ZAG data for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Zag : function(user)
  {
    // command text
    var querystring = "q=2&c=1&NoCookie=1&";
  
    // get cookie
    var cookie = GDN.Cookies.GCION.Get();

    // check for non-required zip code
    if (user.Country() != "us")
      user.Zip("00000");
      
    // append required parameters
    querystring = GDN.AppendParam(querystring, "Country", user.Country());
    querystring = GDN.AppendParam(querystring, "GCIONID", GDN.Cookies.GCION.GetValue("GcionId"));
    querystring = GDN.AppendParam(querystring, "Gender", user.Gender());
    querystring = GDN.AppendParam(querystring, "OriginatingSite", escape(gdn_reg_site_code));
    querystring = GDN.AppendParam(querystring, "YOB", user.Yob());
    querystring = GDN.AppendParam(querystring, "Zip", user.Zip());
    
    // append optional parameters
    if (gdn_occupation_required)
    {
      if (user.Occupation())
      {
        querystring = GDN.AppendParam(querystring, "Occupation", user.Occupation());
      /* Where does this come from???? */
        if (occupation != "Student/Intern" &&
          occupation != "Retired" &&
          occupation != "Not Employed")
        {
          querystring = GDN.AppendParam(querystring, "Industry", user.Industry());
          querystring = GDN.AppendParam(querystring, "CompanySize", user.CompanySize());
        }
      }
    }

    // ZAG user
    GDN.Rpc.Send(GDN.RegUrl(querystring));
  }
};
/// <summary>
/// The UserStatus type provides enumerations for determining the status
/// of a request made by a user.
/// </summary>
GDN.UR.UserStatus = 
{
  IdentifierCreated   : 1,
  ZagCollected        : 2,
  OccupationCollected : 4,
  EmailCollected      : 8,
  UnderAge            : 16
};

/// <summary>
/// Gets the absolute URL, including the specified query string
/// parameters, of the authentication service.
/// </summary>
/// <param name="parameters">Query string parameters in which to append to the request URL.</param>
GDN.AuthUrl = function(parameters)
{
  // get absolute URL to data service
  var url = GDN.CombinePath(gdn_host, gdn_AuthService, gdn_enable_ssl);

  // append query string parameters if specified
  if (!GDN.IsNullOrEmpty(parameters))
    url += "?" + parameters + "&CacheDefeat=" + new Date().getTime();

  return url;
};

/// <summary>
/// Gets the path to the avatar.
/// </summary>
GDN.Avatar = function()
{
  if (GDN.Cookies.Session.GetValue("sta") == GDN.UA.UserStatus.Success)
  {
    if (!GDN.IsNullOrEmpty(GDN.Cookies.GDN.GetValue("Avatar")))
      return decodeURIComponent(GDN.Cookies.GDN.GetValue("Avatar"));
    else
      return gdn_default_avatar;
  }
  else
    return gdn_default_avatar;
};

/// <summary>
/// Gets the absolute URL, including the specified query string
/// parameters, of the extrovert service.
/// </summary>
/// <param name="parameters">Query string parameters in which to append to the request URL.</param>
GDN.ExtrovertUrl = function(parameters)
{
  // get absolute URL to data service
  var url = GDN.CombinePath(gdn_host, gdn_ExtrovertService, gdn_enable_ssl);

  // append query string parameters if specified
  if (!GDN.IsNullOrEmpty(parameters))
    url += "?" + parameters + "&CacheDefeat=" + new Date().getTime();

  return url;
};

/// <summary>
/// Gets the HTML tag for the login title.
/// </summary>
GDN.LoginTitleTag = function()
{
  if (!GDN.IsNullOrEmpty(gdn_login_image))
    return '<img src="' + gdn_login_image + 
    	'" alt="' + gdn_login_title + 
	'" title="' + gdn_login_title + 
	'" border="0" style=\"margin-left: 0px; float: left;\" />';
  else
    return '<h3>' + gdn_login_title + '</h3>';
};

/// <summary>
/// Handles the refreshing of a page or widget.
/// </summary>
/// <param name="widget">The widget to refresh.</param>
GDN.Refresh = function(widget)
{
  switch (gdn_Actions["Refresh"])
  {
    // redirect to destination page
    case 1:
      window.location.href = GDN.Request.QueryString("Destination");
      break;
      
    // refresh page or widget
    case 2:
      {
        // check for auto refresh
        try
        {
          if (gdn_auto_refresh || gdn_login_redirect)
          {
            // refresh page
            window.location.reload();
            var clientReload = false;
          }
          else
            var clientReload = true;
        }
        catch (e) { var clientReload = true; }
            
        // refresh widget
        if (clientReload)
        {
          // show widget
          if (widget)
            eval(widget);
        
          // close widget
          GDN.Widget.Close();
        }
      }
      break;
  }
};

/// <summary>
/// Gets a user's avatar from Pluck and saves the avatar path in a cookie.
/// </summary>
GDN.SaveAvatar = function()
{
  // ensure avatar path is available
  if (!GDN.IsNullOrEmpty(gsl.personaHref))
  {
    if (GDN.Cookie.Exists(GDN.Cookies.GDN.Name))
    {
      // get user
      var user = GDN.Cookies.GDN.Get();
      // set avatar
      user.SetAttribute("Avatar", encodeURIComponent(gsl.personaHref));
      // set cookie
      GDN.Cookies.GDN.Set(user);
      // clear timeout
      window.clearTimeout(gdn_TimeoutIds["Default"]);
    }
  }
  else
  {
    // set timeout
    gdn_TimeoutIds["Default"] = window.setTimeout("GDN.SaveAvatar()", 500);
  }
};

/// <summary>
/// Gets a user's avatar from Pluck and updates the avatar path in a cookie.
/// </summary>
GDN.UpdateAvatar = (function(){
function updateAvatar(result){ 
	var u= null, r; 
	for (var i=0,l=result.Responses.length;i<l;i++){ 
		r= result.Responses[i]; 
		if(!r.User) continue; 
		u= r.User; 
		break; 
	}
     	if(!u) return;  
      	var user = GDN.Cookies.GDN.Get();
      	user.SetAttribute("Avatar", encodeURIComponent(u.AvatarPhotoUrl));
      	GDN.Cookies.GDN.Set(user);
        GDN.Refresh('GDN.Widget.Load("inline", "LoggedIn", "gdn_Widgets[\'LoggedIn\']", "gdn_Divs[\'Login\']", "' +
        GDN.Base64.Encode('window.setTimeout("GDN.Api.Invoke(\'LoggedIn\')", 500)') + '")');
}
return function()
{
	GEL.use("com.Pluck", function(){ 
		var 
			_pi= GEL.thepage.pageinfo.url,
			_siteinstance=GEL.thepage.pageinfo.siteinstance,
			_batch= new RequestBatch(), 				
			_uKey= new UserKey(),
			_u= GEL.config.sitelifeurl || 
				["http://sitelife",_siteinstance,".", _pi.domainname , 
				"/ver1.0/Direct/Process?sid=sitelife",_siteinstance,".", 
				_pi.domainname].join("")
		; 
		_batch.AddToRequest(_uKey); 
		_batch.BeginRequest(_u, updateAvatar); 

	}); 
}
})(); 
GDN.Page = { SaveAvatar : function() { GDN.SaveAvatar(); } };
/// <summary>
/// The GDN type provides methods for handling the GDN cookie.
/// </summary>
GDN.Cookies.GDN =
{
  /// <summary>
  /// Gets the format of the cookie for COPPA.
  /// </summary>
  CoppaFormat: "{gannettid}~{version}~{date_created}~{status}~"
    + "uid:{uid}|usr:{usr}|adr:{adr}|aln:{aln}|tim:{tim}|"
    + "hsh:{hsh}|ava:{ava}|sax:0",
    
  /// <summary>
  /// Gets the number of days before the cookie expires.
  /// </summary>
  Expires: 365,

  /// <summary>
  /// Gets the format of the cookie.
  /// </summary>
  Format: "{gannettid}~{version}~{date_created}~{status}~"
    + "uid:{uid}|usr:{usr}|adr:{adr}|fnm:{fnm}|lnm:{lnm}|"
    + "aln:{aln}|cou:{cou}|gen:{gen}|sta:{sta}|yob:{yob}|"
    + "zip:{zip}|tim:{tim}|hsh:{hsh}|ava:{ava}|sax:0",

  /// <summary>
  /// Gets the name of the cookie.
  /// </summary>
  Name: "GCIONID",

  /// <summary>
  /// Gets the version of the cookie.
  /// </summary>
  Version: "3",

  /// <summary>
  /// Gets a User object populated with data from the cookie.
  /// </summary>
  Get : function()
  {
    // initialize User object
    var user = new GDN.UA.User();
    // get properties
    user.AutoLogin(this.GetValue("AutoLogin"));
    user.Country(this.GetValue("Country"));
    user.Email(this.GetValue("Email"));
    user.FirstName(this.GetValue("FirstName"));
    user.GannettId(this.GetValue("GannettId"));
    user.Gender(this.GetValue("Gender"));
    user.LastName(this.GetValue("LastName"));
    user.State(this.GetValue("State"));
    user.UserId(this.GetValue("UserId"));
    user.UserName(this.GetValue("UserName"));
    user.Yob(this.GetValue("Yob"));
    user.Zip(this.GetValue("Zip"));
    
    // set attributes
    user.SetAttribute("Avatar", this.GetValue("Avatar"));
    user.SetAttribute("Hash", this.GetValue("Hash"));
    user.SetAttribute("Timestamp", this.GetValue("Timestamp"));
    
    // get status
    user.Status(GDN.Cookies.Session.GetValue("sta"));
    
    return user;
  },
  __matchMap: { 
"AutoLogin" : "aln",
"Avatar"    : "ava",
"Country"   : "cou",
"Email"     : "adr",
"FirstName" : "fnm",
"Gender"    : "gen",
"Hash"      : "hsh",
"LastName"  : "lnm",
"State"     : "sta",
"Timestamp" : "tim",
"UserId"    : "uid",
"UserName"  : "usr",
"Yob"       : "yob",  	
"Zip"       : "zip"
	}, 
  /// <summary>
  /// Gets a match from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetMatch : function(key)
  {
  	if(key in this.__matchMap) 
		return this.__matchMap[key]; 
	else 
		return null; 
  },
  
  /// <summary>
  /// Gets a value from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetValue : (function(){ 
  	var _PARTMAP= { 
		GannettId: 0,
		Version: 1, 
		DateCreated: 2
	}
  return function(key){
    // ensure cookie exists
    	if (!GDN.Cookie.Exists(this.Name)) return null;
    	var 
		cookie = GDN.Base64.Decode(GDN.Cookie.Get(this.Name)),
		parts= cookie.split("~"),
		pairs,match, pair
	;
	if(key in _PARTMAP) 
		return parts[_PARTMAP[key]]; 
        if (parts.length != 5)
		return null; 
        pairs = parts[4].split('|');
        match = this.GetMatch(key);
        for (var i = 0; i < pairs.length; i++){
              pair = pairs[i].split(':');
              if (match == pair[0])
                	return pair[1];
        }
	return null; 
  }
  })(),

  /// <summary>
  /// Sets a cookie using data from the specified User object.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Set : function(user){
      var cookie=  (user.Yob() <= 0) || (GDN.GetAge(user.Yob()) < 14) ? 
		this.CoppaFormat : this.Format,
	  _fName= user.FirstName(), 
	  _lName= user.LastName(), 
	  _encId= user.GetAttribute("EncryptedGannettId"),
	  _avatar= user.GetAttribute("Avatar"), 
	  _hash= user.GetAttribute("Hash"), 
	  _ts= user.GetAttribute("Timestamp"),
	  _status= user.Status()
      ; 
      cookie = cookie.replace(/{gannettid}/gi, _encId ? _encId : user.GannettId()); 
      cookie = cookie.replace(/{date_created}/gi, GDN.GetCreationDate());
      cookie = cookie.replace(/{version}/gi, this.Version);
      cookie = cookie.replace(/{status}/gi, 2);
      cookie = cookie.replace(/{uid}/gi, _encId ? _encId : user.UserId());
      cookie = cookie.replace(/{usr}/gi, user.UserName());
      cookie = cookie.replace(/{adr}/gi, user.Email());
      cookie = cookie.replace(/{aln}/gi, user.AutoLogin());
      cookie = cookie.replace(/{cou}/gi, user.Country());
      cookie = cookie.replace(/{gen}/gi, user.Gender());
      cookie = cookie.replace(/{sta}/gi, user.State());
      cookie = cookie.replace(/{yob}/gi, user.Yob());
      cookie = cookie.replace(/{zip}/gi, user.Zip());
      
      cookie = cookie.replace(/{fnm}/gi, _fName != "None"); 
      cookie = cookie.replace(/{lnm}/gi, _lName);  
      cookie = cookie.replace(/{ava}/gi, _avatar ? _avatar : null);  
      cookie = cookie.replace(/{hsh}/gi, _hash ? _hash : null);  
      cookie = cookie.replace(/{tim}/gi, _ts ? _ts : null);  
    // set cookies
    GDN.Cookie.Set(this.Name, GDN.Base64.Encode(cookie), this.Expires);
    GDN.Cookies.Session.SetValue("sta", _status); 
    GDN.Cookies.Session.SetValue("sts", _status == 0 ? "Success" : "Failed");
  }
};
/// <summary>
/// The Page type provides methods for handling page events.
/// </summary>
GDN.UA.Page =
{
  /// <summary>
  /// Executes when the automatic login callout completes.
  /// </summary>
  AutoLogin : function()
  {
    // get user
    var user = new GDN.UA.User(GDN.UA.UserData);
    
    if (user.Status() == GDN.UA.UserStatus.Success)
    {
      // get values
      user.AutoLogin(GDN.Cookies.GDN.GetValue("AutoLogin"));
      user.SetAttribute("Avatar", GDN.Cookies.GDN.GetValue("Avatar"));
    
      // set cookies
      GDN.Cookies.GDN.Set(user);
      GDN.Cookies.Pluck.Set(user);
      
      // invoke API methods
      GDN.Api.Invoke("Login");
      
      // show widget
      GDN.Widget.Load("inline", "LoggedIn", "gdn_Widgets['LoggedIn']", "gdn_Divs['Login']",
        GDN.Base64.Encode('window.setTimeout("GDN.Api.Invoke(\'LoggedIn\')", 500)'));
      if (GDN.Cookies.GCION.GetValue("Status") == 16 && GDN.Cookies.GDN.GetValue("GannettId") == 0)
          document.cookie = "GCIONID =0;path=/;domain=." + gdn_site_name + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
    }
    else
    {
      // show widget
      GDN.Widget.Load("inline", "LoggedOut", "gdn_Widgets['LoggedOut']", "gdn_Divs['Login']",
        GDN.Base64.Encode('window.setTimeout("GDN.Api.Invoke(\'LoggedOut\')", 500)'));
      if (GDN.Cookies.GCION.GetValue("Status") == 16 && GDN.Cookies.GDN.GetValue("GannettId") == 0)
          document.cookie = "GCIONID =0;path=/;domain=." + gdn_site_name + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
    }
  },
  
  /// <summary>
  /// Executes when the page loads.
  /// </summary>
  Load : function()
  {
  	var 
		_d= document.getElementById(gdn_Divs.Login),
		user, status,aln
	; 
	if(!_d) return null; 
	user= GDN.Cookies.GDN.Get(); 
	status= user.Status(); 
	aln= user.AutoLogin();

      	if (
      		GDN.Cookie.Exists(GDN.Cookies.GDN.Name) && 
 		(status== GDN.UA.UserStatus.Success ||  aln == "true")
      	){
        	if (status==GDN.UA.UserStatus.Success){
        	  	GDN.Widget.Load("inline", "LoggedIn", "gdn_Widgets['LoggedIn']", "gdn_Divs['Login']",
            			GDN.Base64.Encode('window.setTimeout("GDN.Api.Invoke(\'LoggedIn\')", 500)'));
               	}else if(aln == "true"){
          		GDN.Callback.Add(GDN.UA.Page.AutoLogin);
          		GDN.UA.UserProvider.Get(user);
        	}
        }else{
          	GDN.Widget.Load("inline", "LoggedOut", "gdn_Widgets['LoggedOut']", "gdn_Divs['Login']",
            		GDN.Base64.Encode('window.setTimeout("GDN.Api.Invoke(\'LoggedOut\')", 500)'));
        }
      	if (
		GDN.Cookies.GCION.GetValue("Status") == 16 && 
		GDN.Cookies.GDN.GetValue("GannettId") == 0
	){
       		document.cookie = "GCIONID =0;path=/;domain=." + 
			gdn_site_name + 
			";expires=Thu, 01-Jan-1970 00:00:01 GMT"
		;
	}
  },
  
  /// <summary>
  /// Executes when the newsletter widget loads.
  /// </summary>
  Newsletters : function()
  {
    if (document.getElementById(gdn_Divs["Newsletters"]))
    {
      GDN.Widget.Load("inline", "Newsletters", "gdn_Widgets['Newsletters']", "gdn_Divs['Newsletters']");
    }
  },
  
  /// <summary>
  /// Executes when the Pluck login widget loads.
  /// </summary>
  PluckLogin : function()
  {
    if (document.getElementById(gdn_Divs["PluckLogin"]))
    {
      GDN.Widget.Load("inline", "PluckLogin", "gdn_Widgets['PluckLogin']", "gdn_Divs['PluckLogin']",
        GDN.Base64.Encode("gdn_Actions['Refresh'] = 1;gdn_Actions['Login'] = 2;window.setTimeout(\"GDN.SetFocus('UAWidget-PluckLogin')\", 500);"));
    }
  },
  
  /// <summary>
  /// Executes when the Pluck logout widget loads.
  /// </summary>
  PluckLogout : function()
  {
    if (document.getElementById(gdn_Divs["PluckLogout"]))
    {
      if (GDN.Cookies.Session.GetValue("sts") == GDN.UA.UserStatus.Success)
      {
        gdn_Actions["Refresh"] = 1;
       	var _url= GDN.getPath("Logout", "UAEvents"); 
        if (!GDN.Rpc.IsLoaded(_url))
          GDN.LoadFile("Logout", "UAEvents");
        else
          GDN.UA.Events.Logout.Execute();
      }
      else
        window.location.href = GDN.Request.QueryString("Destination");
    }
  },
  
  /// <summary>
  /// Executes when the Pluck registration widget loads.
  /// </summary>
  PluckReg : function()
  {
    var _e= document.getElementById(gdn_Divs.PluckReg); 
    if(!_e) return; 
    var _cb= GDN.Base64.Encode(
    	"gdn_Actions['Reg'] = 2;" + 
    	"window.setTimeout(\"GDN.SetFocus('UAWidget-PluckRegistration')\", 1500);"
    ); 
    GDN.Widget.Load(
    		"inline", 
		"PluckRegistration", 
		"gdn_Widgets['PluckReg']", 
		"gdn_Divs['PluckReg']",
		_cb
   ); 
  },
  
  /// <summary>
  /// Executes when the Saxotech login widget loads.
  /// </summary>
  SaxotechLogin : function()
  {
    if (document.getElementById(gdn_Divs["SaxotechLogin"]))
    {
      GDN.Widget.Load("inline", "SaxotechLogin", "gdn_Widgets['SaxotechLogin']", "gdn_Divs['SaxotechLogin']",
        GDN.Base64.Encode("gdn_Actions['Refresh'] = 2;gdn_Actions['Login'] = 2;window.setTimeout(\"GDN.SetFocus(\'UAWidget-SaxotechLogin\')\", 500);"));
    
      if (GDN.Cookie.Exists(GDN.Cookies.GDN.Name))
      {
        // get user
        var user = GDN.Cookies.GDN.Get();

        if (user.AutoLogin() == "true")
        {
          // set status
          user.Status(GDN.UA.UserStatus.Success);
          // set session cookie
          GDN.Cookies.Session.SetValue("sta", user.Status());
          GDN.Cookies.Session.SetValue("sts", (user.Status() == 0) ? "Success" : "Failed")
        }
      }
    }
  },
  
  SaveAvatar : function() { GDN.SaveAvatar(); }
};
/// <summary>
/// The Pluck type provides methods for handling the Pluck cookie.
/// </summary>
GDN.Cookies.Pluck =
{
  /// <summary>
  /// Gets the format of the cookie for COPPA.
  /// </summary>
  CoppaFormat: "a={a}&u={u}&e={e}&t={t}&h={h}&s={s}",

  /// <summary>
  /// Gets the format of the cookie.
  /// </summary>
  Format: "a={a}&u={u}&e={e}&f={f}&l={l}&g={g}&t={t}&h={h}&s={s}",

  /// <summary>
  /// Gets the name of the cookie.
  /// </summary>
  Name: "at",
  
  /// <summary>
  /// Gets a match from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetMatch : (function(){ 
  	var _PROPMAP= { 
		 "Email"                  :"e",
                 "FirstName"              :"f",
                 "Gender"                 :"g",
                 "Hash"                   :"h",
                 "LastName"               :"l",
                 "RegisteredApplications" :"s",
                 "Timestamp"              :"t",
                 "UserId"                 :"u",
                 "UserName"               :"a"
	};
  	return function(key){
		if(key in _PROPMAP) 
			return _PROPMAP[key]; 
		else 
			return null; 
  	}
   })(), 

  /// <summary>
  /// Gets a value from the cookie using the specified key.
  /// </summary>
  /// <param name="key">The key used to get the value.</param>
  GetValue : function(key)
  {
    // ensure cookie exists
    if (!GDN.Cookie.Exists(this.Name)) return null;

    // get cookie
    var 
    	cookie = unescape(GDN.Cookie.Get(this.Name)),
	pairs= cookie.split("&"), 
	match= this.GetMatch(key),
	pair
    ;
    for (var i = 0; i < pairs.length; i++){
      pair = pairs[i].split('=');
      if (match == pair[0])
        return pair[1];
    }
    return null;
  },
  Set : function(user){
    	var 
		cookie= (user.Yob() <= 0) || (GDN.GetAge(user.Yob()) < 14) ? 
    			this.CoppaFormat : this.Format,
		_fName= user.FirstName(), 
		_lName= user.LastName(),
		_fNVal= (_fName && _fName != "None") ? _fName : "",
		_lNVal= (_lName && _lName != "None") ? _lName : ""
   	;
      cookie = cookie.replace(/{a}/gi, user.UserName());
      cookie = cookie.replace(/{u}/gi, user.UserId().replace(/\-/gi, ""));
      cookie = cookie.replace(/{e}/gi, user.Email());
      cookie = cookie.replace(/{g}/gi, (user.Gender() == 2) ? "M" : "F");
      cookie = cookie.replace(/{t}/gi, user.GetAttribute("Timestamp"));
      cookie = cookie.replace(/{h}/gi, user.GetAttribute("Hash"));
      cookie = cookie.replace(/{s}/gi, user.GetAttribute("RegisteredApplications"));
      cookie = cookie.replace(/{f}/gi, _fNVal);
      cookie = cookie.replace(/{l}/gi, _lNVal);
      GDN.Cookie.Set(this.Name, escape(cookie).replace(/\@/gi, "%40"));
  }
};
GDN.UA.User = function()
{
  // properties
  var _a= { 
  	Attributes: [],
  	AutoLogin: false,
  	Country: "us",
  	Email: null,
  	FirstName: null,
  	GannettId: null,
  	Gender: 0,
  	IsActivated: false,
  	IsLockedOut: false,
  	IsOnline: false,
  	LastName: null,
  	Password: null,
  	State: null,
  	Status: -1,
  	UserId: null,
  	UserName: null,
  	Yob: 0,
  	Zip: "00000"
  };
  for (var k in _a) 
  	this[k]= accessor(k); 
  this.GetAttribute = GetAttribute;
  this.SetAttribute = SetAttribute;
  if (arguments[0])
    	Init(arguments[0]);
  function Init(o){
  	for (var k in o)
		_a[k]= o[k]; 
   }
  function accessor(key){
  	return function(value){ 
  		if(value) 
			return _a[key]= value; 
		else 
			return _a[key]; 
	}
  }

  function GetAttribute(name){
    	var _attributes= this.Attributes(); 
    	if(!_attributes) return null; 
    	for (var i = 0; i < _attributes.length; i++){
       		if (_attributes[i].Key == name)
          		return _attributes[i].Value;
      	}
  }
  function SetAttribute(name, value){
  	var 
    		keyExists = false,
    		_attributes= this.Attributes()
 	; 
    
    	for (var i = 0; i < _attributes.length; i++){
      		if (_attributes[i].Key == name){
        		keyExists = true;
        		break;
      		}
    	}
    	if (!keyExists)
      		return _attributes.push({"Key":name,"Value":value});
      	for (var i = 0; i < _attributes.length; i++){
       		if (_attributes[i].Key != name)
			continue; 
       		_attributes.splice(i, 1);
       		_attributes.push({
			"Key":name,
			"Value":value
		});
       		break;
      	}
  }
};
GDN.UA.UserProvider =
{
  /// <summary>
  /// Changes a password for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  ChangePassword : function(user)
  {
    // command text
    var querystring = "q=5&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
    
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes
    json.AddAttribute("GroupName", gdn_group_name);
    json.AddAttribute("NewPassword", user.GetAttribute("NewPassword"));
    json.AddAttribute("OldPassword", user.GetAttribute("OldPassword"));
    json.AddAttribute("Timestamp", GDN.Cookies.GDN.GetValue("Timestamp"));
    json.AddAttribute("Hash", GDN.Cookies.GDN.GetValue("Hash"));
    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // change password
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },

  /// <summary>
  /// Creates the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  /// <param name="destination">The redirect URL to send the user after activating.</param>
  Create : function(user, destination)
  {
    // command text
    var querystring = "q=1&c=1";
    
    // check for non-required zip code
    if (user.Country() != "us")
      user.Zip("0");
      
    // initialize JSON object
    var json = new GDN.Json();
    
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("AutoLogin", user.AutoLogin());
    json.Add("Country", user.Country());
    json.Add("Email", user.Email());
    json.Add("FirstName", user.FirstName());
    json.Add("Gender", user.Gender());
    json.Add("LastName", user.LastName());
    json.Add("Password", user.Password());
    json.Add("UserName", user.UserName());
    json.Add("Yob", user.Yob());
    json.Add("Zip", user.Zip());

    // add attributes
    if (!GDN.IsNullOrEmpty(destination))
      json.AddAttribute("Destination", destination);
    
    if (gdn_Actions["RegThanks"] == 2)
    {
      json.AddAttribute("ThirdPartyApplicationName", gdn_third_party_app_name);
      json.AddAttribute("ThirdPartySiteId", user.GetAttribute("ThirdPartySiteId"));
      json.AddAttribute("ThirdPartyUserId", user.GetAttribute("ThirdPartyUserId"));
    }
    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
      json.AddAttribute("Version", gdn_version);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
    
    // check for numeric user name and replace as string
    if (!isNaN(user.UserName()))
      querystring = querystring.replace(user.UserName(), '"' + user.UserName() + '"');
  
    // create user
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Deletes the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Delete : function(user)
  {
    // command text
    var querystring = "q=3&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
    
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes
    json.AddAttribute("GroupName", gdn_group_name);
    json.AddAttribute("Timestamp", GDN.Cookies.GDN.GetValue("Timestamp"));
    json.AddAttribute("Hash", GDN.Cookies.GDN.GetValue("Hash"));
    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // delete user
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Gets data for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Get : function(user)
  {
    // command text
    var querystring = "q=7&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
  
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes
    json.AddAttribute("GroupName", gdn_group_name);
    json.AddAttribute("Timestamp", GDN.Cookies.GDN.GetValue("Timestamp"));
    json.AddAttribute("Hash", GDN.Cookies.GDN.GetValue("Hash"));
    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // get user
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Sends authentication credentials for the specified user to a third party
  /// application that retrieves information for the user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  GetThirdPartyUser : function(user)
  {  
    // command text
    var querystring = "q=2&c=1";
  
    // add parameters
    querystring += "&ThirdPartyApplicationName=" + gdn_third_party_app_name;
    querystring += "&ApplicationName=" + gdn_app_name;
    querystring += "&Email=" + user.Email();
    querystring += "&Password=" + user.Password();

    // get third party user
    GDN.Rpc.Send(GDN.ExtrovertUrl(querystring));
  },
  
  /// <summary>
  /// Resends a confirmation email to the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  /// <param name="destination">The redirect URL to send the user after activating.</param>
  ResendConfirmation : function(user, destination)
  {
    // command text
    var querystring = "q=8&c=1";
    
    // get current page URL if destination URL is not set
    if (GDN.IsNullOrEmpty(destination))
    {
      destination = window.location.protocol + "//" + window.location.hostname +
        window.location.pathname + window.location.search;
    }

    // initialize JSON object
    var json = new GDN.Json();
  
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("Custom", gdn_saxotech_site_code);
    }

    // get user object
    querystring += "&u=" + json.ToString();
  
    // resend confirmation
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Retrieves a forgotten password and sends it to the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  RetrievePassword : function(user)
  {
    // command text
    var querystring = "q=6&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
  
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // retrieve password
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Updates account data for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Update : function(user)
  {
    // command text
    var querystring = "q=2&c=1";
    
    // check for non-required zip code
    if (user.Country() != "us")
      user.Zip("0");
      
    // initialize JSON object
    var json = new GDN.Json();
    
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("AutoLogin", user.AutoLogin());
    json.Add("Country", user.Country());
    json.Add("Email", user.Email());
    json.Add("FirstName", user.FirstName());
    json.Add("Gender", user.Gender());
    json.Add("LastName", user.LastName());
    json.Add("UserName", user.UserName());
    json.Add("Yob", user.Yob());
    json.Add("Zip", user.Zip());
    
    // add attributes
    json.AddAttribute("GroupName", gdn_group_name);
    json.AddAttribute("CurrentUserName", GDN.Cookies.GDN.GetValue("UserName"));
    json.AddAttribute("Timestamp", GDN.Cookies.GDN.GetValue("Timestamp"));
    json.AddAttribute("Hash", GDN.Cookies.GDN.GetValue("Hash"));
    
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // update user
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Updates newsletter subscriptions for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  /// <param name="newsletters">A string containing newsletter subscriptions.</param>
  UpdateNewsletters : function(user, newsletters)
  {
    // command text
    var querystring = "q=9&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
    
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("Email", user.Email());
    
    // add attributes
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
      json.AddAttribute("Newsletters", newsletters);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
  
    // update newsletters
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  },
  
  /// <summary>
  /// Validates authentication credentials for the specified user.
  /// </summary>
  /// <param name="user">A User object populated with data.</param>
  Validate : function(user)
  {
    // command text
    var querystring = "q=4&c=1";
      
    // initialize JSON object
    var json = new GDN.Json();
  
    // add properties
    json.Add("ApplicationName", gdn_app_name);
    json.Add("AutoLogin", user.AutoLogin());
    json.Add("Email", user.Email());
    json.Add("Password", user.Password());
        
    // add attributes
    json.AddAttribute("GroupName", gdn_group_name);
        
    if (gdn_enable_saxotech)
    {
      json.AddAttribute("EnableSaxotech", gdn_enable_saxotech);
      json.AddAttribute("SaxotechSiteCode", gdn_saxotech_site_code);
    }
    
    // get user object
    querystring += "&u=" + json.ToString();
    
    // validate user
    GDN.Rpc.Send(GDN.AuthUrl(querystring));
  }
};
GDN.UA.UserStatus = 
{
  Success           : 0,
  Failed            : 1,
  Pending           : 2,
  NotFound          : 3,
  LockedOut         : 4,
  DuplicateEmail    : 5,
  DuplicateUserId   : 6,
  DuplicateUserName : 7,
  InvalidAnswer     : 8,
  InvalidEmail      : 9,
  InvalidPassword   : 10,
  InvalidQuestion   : 11,
  InvalidUserId     : 12,
  InvalidUserName   : 13,
  InvalidZipCode    : 14
};


