public async Task <bool> LoginAsync(string site, string username, SecureString password, bool allFilesPermitted = false)
        {
            const string xmlExceptionmessage     = "The server returned an invalid response.";
            const string timeoutExceptionMessage = "The server did not respond.";

            try
            {
                Site = site;
                _api = new ApiUri(Site);

                var loginParams = new RequestParameters
                {
                    { "action", "login" },
                    { "format", "xml" },
                    { "lgname", username },
                };

                string loginToken = await GetLoginTokenAsync().ConfigureAwait(false);

                bool useDeprecatedLogin = (loginToken == null);
                if (useDeprecatedLogin)
                {
                    // use old method to fetch login token by loging in without password, required for fandom
                    var tokenResponse = await AttemptLoginAsync(loginParams).ConfigureAwait(false);

                    if (tokenResponse.Result != ResponseCodes.NeedToken)
                    {
                        return(false);
                    }
                    loginToken = tokenResponse.Token;
                }

                loginParams.Add("lgtoken", loginToken);
                // at this point we have no option other than to move password into managed memory
                loginParams.Add("lgpassword", password.Unsecure());

                var response = await AttemptLoginAsync(loginParams).ConfigureAwait(false);

                if (response.Result == ResponseCodes.Aborted)
                {
                    throw new LoginException("You must use a bot password (username@password).");
                }

                if (response.Result != ResponseCodes.Success)
                {
                    return(false);
                }

                Task <string> editTokenTask     = useDeprecatedLogin ? GetEditTokenViaIntokenAsync() : GetEditTokenAsync();
                Task <bool>   userConfirmedTask = IsUserConfirmedAsync(username);
                Task <bool>   authorizedTask    = IsAuthorizedForUploadFilesAsync(username);

                if (allFilesPermitted)
                {
                    await Task.WhenAll(userConfirmedTask, authorizedTask, editTokenTask)
                    .ConfigureAwait(false);
                }
                else
                {
                    await Task.WhenAll(userConfirmedTask, authorizedTask, GetPermittedTypes(), editTokenTask)
                    .ConfigureAwait(false);
                }

                if (!userConfirmedTask.Result)
                {
                    throw new LoginException("That account is not autoconfirmed.");
                }

                if (!authorizedTask.Result)
                {
                    throw new LoginException("You are not authorized to use Wiki-Up on this wiki.");
                }

                if (string.IsNullOrEmpty(editTokenTask.Result))
                {
                    throw new LoginException("Unable to obtain edit token.");
                }

                _editToken = editTokenTask.Result;
                return(true);
            }
            catch (XmlException)
            {
                throw new LoginException(xmlExceptionmessage);
            }
            catch (HttpRequestException ex)
            {
                throw new LoginException(ex.Message, ex.InnerException);
            }
            catch (TaskCanceledException)
            {
                throw new LoginException(timeoutExceptionMessage);
            }
            catch (AggregateException ex)
            {
                foreach (var innerEx in ex.InnerExceptions)
                {
                    if (innerEx is TaskCanceledException)
                    {
                        throw new LoginException(timeoutExceptionMessage);
                    }
                    else if (innerEx is HttpRequestException)
                    {
                        throw new LoginException(innerEx.Message, innerEx.InnerException);
                    }
                    else if (innerEx is XmlException)
                    {
                        throw new LoginException(xmlExceptionmessage);
                    }
                }
                throw new LoginException("An unexpected error occured.");
            }
        }
Beispiel #2
0
        public async Task <bool> LoginAsync(string site, string username, SecureString password, bool allFilesPermitted)
        {
            try
            {
                Site = site;
                _api = new ApiUri(Site);

                var loginParams = new RequestParameters
                {
                    { "action", "login" },
                    { "format", "xml" },
                    { "lgname", username },
                };

                var loginToken = await GetLoginTokenAsync().ConfigureAwait(false);

                _useDeprecatedLogin = (loginToken == null);
                if (_useDeprecatedLogin)
                {
                    // use old method to fetch login token by loging in without password, required for fandom
                    var tokenResponse = await AttemptLoginAsync(loginParams).ConfigureAwait(false);

                    if (tokenResponse.Result != ResponseCodes.NeedToken)
                    {
                        return(false);
                    }
                    loginToken = tokenResponse.Token;
                }

                loginParams.Add("lgtoken", loginToken);

                var response = await password.UseUnsecuredStringAsync <LoginResponse>((unsecuredPassword) =>
                {
                    loginParams.Add("lgpassword", unsecuredPassword);
                    return(AttemptLoginAsync(loginParams));
                });

                if (response.Result == ResponseCodes.Aborted)
                {
                    throw new LoginException(Resources.LoginExceptionAborted);
                }

                if (response.Result != ResponseCodes.Success)
                {
                    return(false);
                }

                var editTokenTask     = _useDeprecatedLogin ? GetEditTokenViaIntokenAsync() : GetEditTokenAsync();
                var userConfirmedTask = IsUserConfirmedAsync(username);
                var authorizedTask    = IsAuthorizedForUploadFilesAsync(username);
                var siteInfoTask      = GeSiteInfoAsync();

                await Task.WhenAll(userConfirmedTask, authorizedTask, editTokenTask, siteInfoTask)
                .ConfigureAwait(false);

                // From here on in if we fail the login we must also log out, as the
                // sucessfull login session cookies will cause any subsequent login
                // attempts to the same site to fail with an aborted response.

                if (!userConfirmedTask.Result)
                {
                    LogOff();
                    throw new LoginException(Resources.LoginExceptionNotAutoConfirmed);
                }

                if (!authorizedTask.Result)
                {
                    LogOff();
                    throw new LoginException(Resources.LoginExceptionNotAuthorized);
                }

                if (string.IsNullOrEmpty(editTokenTask.Result))
                {
                    LogOff();
                    throw new LoginException(Resources.LoginExceptionNoEditToken);
                }

                _editToken = editTokenTask.Result;

                var siteInfo = siteInfoTask.Result;
                HomePage   = siteInfo.BaseUrl;
                ScriptPath = siteInfo.ScriptPath;
                if (!allFilesPermitted)
                {
                    foreach (var ext in siteInfo.Extensions)
                    {
                        _permittedFiles.Add(ext);
                    }
                }
                var languageCode = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
                _errorLanguageCode = siteInfo.IsSupportedLanguage(languageCode) ? languageCode : "en";
                var useErrorLangVersion = new Version("1.29.0.0");
                _useErrorLang = siteInfo.MediaWikiVersion >= useErrorLangVersion;

                return(true);
            }
            catch (XmlException)
            {
                LogOffIfCookiesPresent();
                throw new LoginException(Resources.LoginExceptionInvalidResponse);
            }
            catch (HttpRequestException ex)
            {
                LogOffIfCookiesPresent();
                throw new LoginException(ex.Message, ex.InnerException);
            }
            catch (TaskCanceledException)
            {
                LogOffIfCookiesPresent();
                throw new LoginException(Resources.LoginExceptionTimeout);
            }
            catch (AggregateException ex)
            {
                LogOffIfCookiesPresent();
                foreach (var innerEx in ex.InnerExceptions)
                {
                    if (innerEx is TaskCanceledException)
                    {
                        throw new LoginException(Resources.LoginExceptionTimeout);
                    }
                    else if (innerEx is HttpRequestException)
                    {
                        throw new LoginException(innerEx.Message, innerEx.InnerException);
                    }
                    else if (innerEx is XmlException)
                    {
                        throw new LoginException(Resources.LoginExceptionInvalidResponse);
                    }
                }
                throw new LoginException(Resources.LoginExceptionUnexpectedError);
            }
        }