/// <summary>
        /// Performs the given WebRequestFunction, retrying if an error occurs, and handling
        /// proxy authentication.
        /// </summary>
        /// <param name="func">The WebRequestFunction to execute.</param>
        /// <param name="arg">The WebRequestFunction argument.</param>
        /// <returns>The WebRequestFunction return value.</returns>
        private object PerformWebRequest(WebRequestFunction func, Object arg)
        {
            int retries = 2;

            while (retries-- > 0)
            {
                try
                {
                    Object       ret;
                    WebException proxyAuthException;
                    return(ProxyAuthHandler(func, arg, out ret, out proxyAuthException));
                }
                catch
                {
                    if (retries == 0)
                    {
                        throw; // rethrow only if no more retries left
                    }
                }
            }

            return(null);
        }
 /// <summary>
 /// Performs the actual WebRequestFunction and returns whether or not we require proxy auth.
 /// </summary>
 /// <returns>True if we received HTTP 407: Proxy Authentication Required.</returns>
 private bool IsProxyAuthRequired(WebRequestFunction func, Object arg, out Object ret, out WebException proxyAuthException)
 {
     try
     {
         ret = func(arg);
         proxyAuthException = null;
         return(false);
     }
     catch (WebException ex)
     {
         if (ex.Status == WebExceptionStatus.ProtocolError && ((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
         {
             // proxy auth required
             ret = null;
             proxyAuthException = ex;
             return(true);
         }
         else
         {
             // other error
             throw;
         }
     }
 }
        /// <summary>
        /// If proxy auth is required then the proxy password is retrieved from saved credentials
        /// or requested from the user. This is repeated until the WebRequestFunction succeeds
        /// (upon which the credentials are saved), or the user cancels.
        /// </summary>
        private object ProxyAuthHandler(WebRequestFunction func, Object arg, out Object ret, out WebException proxyAuthException)
        {
            if (!IsProxyAuthRequired(func, arg, out ret, out proxyAuthException))
            {
                return(ret);
            }


            // got HTTP 407

            // extract realm

            string realm = proxyAuthException.Response.Headers[HttpResponseHeader.ProxyAuthenticate];

            Match match = Regex.Match(realm, @"realm=\""(.+?)\""", RegexOptions.IgnoreCase); // eg,  "Basic realm=\"The realm name\""  (inc quotes)

            if (match.Success)
            {
                realm = match.Groups[1].Value;
            }
            else if (WebRequest.DefaultWebProxy is WebProxy) // custom
            {
                realm = ((WebProxy)WebRequest.DefaultWebProxy).Address.Host;
            }
            else
            {
                realm = Language.NetManager_PleaseEnterCredentials;
            }


            // ask for credentials until succeeds or cancelled

            while (true)
            {
                // remove save check if auth failed

                if (WebRequest.DefaultWebProxy.Credentials != null)
                {
                    proxyCredDialog.SaveChecked = false;
                }


                // get proxy credentials (prompt if not stored)

                NetworkCredential cred = GetProxyCredentials(realm);
                if (cred == null)
                {
                    throw proxyAuthException;         // user cancelled, return original 407 exception
                }
                WebRequest.DefaultWebProxy.Credentials = cred;


                // try again

                if (!IsProxyAuthRequired(func, arg, out ret, out proxyAuthException)) // success
                {
                    proxyCredDialog.AlwaysDisplay = false;

                    try
                    {
                        if (proxyCredDialog.SaveChecked)
                        {
                            proxyCredDialog.Confirm(true); // store
                        }
                        else
                        {
                            proxyCredDialog.Confirm(false); // unstore
                        }
                    }
                    catch { }

                    return(ret);
                }
                else // failed again
                {
                    proxyCredDialog.AlwaysDisplay = true;
                    proxyCredDialog.Password      = "";

                    try // throws an exception if didn't actually show dialog (ie, stored password was wrong)
                    {
                        proxyCredDialog.Confirm(false);
                    }
                    catch { }
                }
            } // end while
        }