HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/RMourik/bassol.nl/CMS/CMSFormControls/Captcha/LogicCaptcha.ascx.cs
using System;
using System.Collections;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;

using CMS.ExtendedControls;
using CMS.FormControls;
using CMS.Helpers;
using CMS.Globalization;
using CMS.Base;
using CMS.Localization;
using CMS.SiteProvider;

public partial class CMSFormControls_Captcha_LogicCaptcha : FormEngineUserControl
{
    #region "Constants"

    private const string CHOICE_MATH_OPERATION = "mathoperation";
    private const string CHOICE_EQUAL = "equal";
    private const string CHOICE_COMPARE = "compare";
    private const string CHOICE_GREATER = "greater";
    private const string CHOICE_SMALLER = "smaller";
    private const string CHOICE_PLUS = "plus";
    private const string CHOICE_MINUS = "minus";
    private const string CHOICE_MULT = "mult";
    private const string CHOICE_DIV = "div";
    private const string CHOICE_STATEMENT = "s";
    private const string CHOICE_IMAGE = "i";

    #endregion


    #region "Variables"

    private bool useRadioButtons = false;

    #endregion


    #region "Public properties"

    /// <summary>
    /// Indicates if should be used text or image CAPTCHA (False - Text, True - Image).
    /// </summary>
    public bool UseTextOrImageCaptcha
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("UseTextOrImageCaptcha"), false);
        }
        set
        {
            SetValue("UseTextOrImageCaptcha", value);
        }
    }


    /// <summary>
    /// Sets or gets whether math operations are used or not. 
    /// </summary>
    public bool UseMathOperations
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("UseMathOperations"), true);
        }
        set
        {
            SetValue("UseMathOperations", value);
        }
    }


    /// <summary>
    /// Sets or gets whether operations multiple and divide are allowed in math operations.
    /// </summary>
    public bool UseMultAndDiv
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("UseMultAndDiv"), false);
        }
        set
        {
            SetValue("UseMultAndDiv", value);
        }
    }


    /// <summary>
    /// Sets or gets whether compare operations are used or not.
    /// </summary>
    public bool UseCompareOperations
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("UseCompareOperations"), true);
        }
        set
        {
            SetValue("UseCompareOperations", value);
        }
    }


    /// <summary>
    /// Sets or gets whether statements are used or not.
    /// </summary>
    public bool UseStatements
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("UseStatements"), false);
        }
        set
        {
            SetValue("UseStatements", value);
        }
    }


    /// <summary>
    /// Gets or sets the enabled state of the control.
    /// </summary>
    public override bool Enabled
    {
        get
        {
            return base.Enabled;
        }
        set
        {
            base.Enabled = value;
            txtAnswer.Enabled = value;
        }
    }


    /// <summary>
    /// Sets or gets whether convert operands to text.
    /// </summary>
    public bool ConvertOperandsToText
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("ConvertOperandsToText"), true);
        }
        set
        {
            SetValue("ConvertOperandsToText", value);
        }
    }


    /// <summary>
    /// Sets or gets whether convert operators to text.
    /// </summary>
    public bool ConvertOperatorToText
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("ConvertOperatorToText"), false);
        }
        set
        {
            SetValue("ConvertOperatorToText", value);
        }
    }


    /// <summary>
    /// Gets or sets field value.
    /// </summary>
    public override object Value
    {
        get
        {
            return txtAnswer.Text;
        }
        set
        {
            txtAnswer.Text = ValidationHelper.GetString(value, string.Empty);
        }
    }


    /// <summary>
    /// Statement question.
    /// </summary>
    public string StatementQuestions
    {
        get
        {
            return ValidationHelper.GetString(GetValue("StatementQuestions"), string.Empty);
        }
        set
        {
            SetValue("StatementQuestions", value);
        }
    }


    /// <summary>
    /// Image question.
    /// </summary>
    public string ImageQuestions
    {
        get
        {
            return ValidationHelper.GetString(GetValue("ImageQuestions"), string.Empty);
        }
        set
        {
            SetValue("ImageQuestions", value);
        }
    }


    /// <summary>
    /// Indicates whether the info label should be displayed.
    /// </summary>
    public bool ShowInfoLabel
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("ShowInfoLabel"), false);
        }
        set
        {
            SetValue("ShowInfoLabel", value);
        }
    }


    /// <summary>
    /// Width of the CAPTCHA image.
    /// </summary>
    public int ImageWidth
    {
        get
        {
            return ValidationHelper.GetInteger(GetValue("ImageWidth"), 80);
        }
        set
        {
            SetValue("ImageWidth", value);
        }
    }


    /// <summary>
    /// Height of the CAPTCHA image.
    /// </summary>
    public int ImageHeight
    {
        get
        {
            return ValidationHelper.GetInteger(GetValue("ImageHeight"), 20);
        }
        set
        {
            SetValue("ImageHeight", value);
        }
    }


    /// <summary>
    /// Indicates whether the after text should be displayed.
    /// </summary>
    public bool ShowAfterText
    {
        get
        {
            return ValidationHelper.GetBoolean(GetValue("ShowAfterText"), false);
        }
        set
        {
            SetValue("ShowAfterText", value);
        }
    }

    #endregion


    #region "Events"

    /// <summary>
    /// Page load.
    /// </summary>    
    protected void Page_Load(object sender, EventArgs e)
    {
        // Show info label
        if (ShowInfoLabel)
        {
            // WAI validation
            lblSecurityCode.AssociatedControlClientID = txtAnswer.ClientID;
            lblSecurityCode.Text = GetString("SecurityCode.lblSecurityCodeLogic");
            lblSecurityCode.Visible = true;
        }

        // Show after text
        plcAfterText.Visible = true;// ShowAfterText;
        if (plcAfterText.Visible)
        {
            if (UseTextOrImageCaptcha)
            {
                lblAfterText.Text = GetString("SecurityCode.AfterText");
            }
            else
            {
                lblAfterText.Text = GetString("LogicCaptcha.Text.AfterText");
            }
        }

        useRadioButtons = (UseStatements && !string.IsNullOrEmpty(StatementQuestions) && !UseTextOrImageCaptcha && !UseMathOperations && !UseMultAndDiv);
    }


    /// <summary>
    ///  Page prerender.
    /// </summary>    
    protected void Page_PreRender(object sender, EventArgs e)
    {
        // Regenerate CAPTCHA if possible
        if (!RequestHelper.IsAsyncPostback() || ControlsHelper.IsInUpdatePanel(this))
        {
            // Regenerate security code
            GenerateNew();

            // Update update panel if needed
            if (ControlsHelper.IsInUpdatePanel(this))
            {
                ControlsHelper.UpdateCurrentPanel(this);
            }
        }

        txtAnswer.Visible = !useRadioButtons;
        rdAnswerNo.Visible = useRadioButtons;
        rdAnswerYes.Visible = useRadioButtons;

        // Hide image code if it is not generated
        imgSecurityCode.Visible = !string.IsNullOrEmpty(imgSecurityCode.ImageUrl);
    }

    #endregion


    #region "Methods"

    /// <summary>
    /// Returns true if user control is valid.
    /// </summary>
    public override bool IsValid()
    {
        bool isValid = false;
        string captcha = ValidationHelper.GetString(WindowHelper.GetItem("CaptchaImageText" + ClientID), string.Empty);

        if (!string.IsNullOrEmpty(captcha))
        {
            // Use radio buttons for answer
            if (useRadioButtons)
            {
                // Only bool answer (Yes/No)
                if (ValidationHelper.IsBoolean(captcha))
                {
                    // Captcha value from session
                    bool catpchaValue = ValidationHelper.GetBoolean(captcha, false);
                    // Compare answer
                    if ((catpchaValue && rdAnswerYes.Checked) || (!catpchaValue && rdAnswerNo.Checked))
                    {
                        return true;
                    }

                    return false;
                }
            }
            // User's value in textbox
            else
            {
                string value = txtAnswer.Text.Trim();

                isValid = (value == captcha);

                // Extension so user can write 1 or true for true and 0 or false for false.
                if (!isValid && ValidationHelper.IsBoolean(value) && ValidationHelper.IsBoolean(captcha)
                    && IsQuestionBoolean(ValidationHelper.GetString(SessionHelper.GetValue("CaptchaOperation" + ClientID), string.Empty)))
                {
                    isValid = (ValidationHelper.GetBoolean(value, false) == ValidationHelper.GetBoolean(captcha, false));
                }
            }
        }

        if (!isValid)
        {
            ValidationError = GetString("captcha.notcorrect");
        }

        return isValid;
    }


    /// <summary>
    /// Indicates if string is for boolean operation.
    /// </summary>
    /// <param name="choice">Boolean operation</param>
    private bool IsQuestionBoolean(string choice)
    {
        if (!string.IsNullOrEmpty(choice))
        {
            choice = choice.ToLowerCSafe();
            return ((choice == CHOICE_SMALLER) || (choice == CHOICE_GREATER) || (choice == CHOICE_EQUAL) || (choice == CHOICE_STATEMENT));
        }

        return false;
    }


    /// <summary>
    /// Returns a string of six random digits.
    /// </summary>    
    private string GenerateRandomCode()
    {
        Random random = new Random(ClientID.GetHashCode() + (int)DateTime.Now.Ticks);

        string s = string.Empty;

        for (int i = 0; i < 6; i++)
        {
            s = String.Concat(s, random.Next(10).ToString());
        }

        return s;
    }


    /// <summary>
    /// Generates new CAPTCHA.
    /// </summary>
    public void GenerateNew()
    {
        txtAnswer.Text = string.Empty;
        CreateQuestion();
    }


    /// <summary>
    /// Creates CAPTCHA question.
    /// </summary>   
    private void CreateQuestion()
    {
        // Possible operations: + - * / < > =, plus same number of statements, plus same number of text and image possibilities
        string[] questions = new string[28];
        int length = 0;

        // If use text CAPTCHA
        if (!UseTextOrImageCaptcha)
        {
            // Add basic math operations
            if (UseMathOperations)
            {
                questions[length] = CHOICE_PLUS;
                length++;
                questions[length] = CHOICE_MINUS;
                length++;
            }

            // Add multiplication and dividing
            if (UseMultAndDiv)
            {
                questions[length] = CHOICE_MULT;
                length++;
                questions[length] = CHOICE_DIV;
                length++;
            }

            // Add compare operations
            if (UseCompareOperations)
            {
                questions[length] = CHOICE_SMALLER;
                length++;
                questions[length] = CHOICE_GREATER;
                length++;
                questions[length] = CHOICE_EQUAL;
                length++;
            }

            // Add statements
            if (UseStatements)
            {
                if (length == 0)
                {
                    questions[0] = CHOICE_STATEMENT;
                    length++;
                }
                else
                {
                    int countStatements = length * 2;
                    // Add same number of statements as number of operations
                    for (int i = length; i != countStatements; i++)
                    {
                        questions[i] = CHOICE_STATEMENT;
                        length++;
                    }
                }
            }
        }
        // Use image CAPTCHA
        else
        {
            if (length == 0)
            {
                questions[0] = CHOICE_IMAGE;
                length++;
            }
            else
            {
                int countImages = length * 2;
                for (int i = length; i != countImages; i++)
                {
                    questions[i] = CHOICE_IMAGE;
                    length++;
                }
            }
        }

        // Choose captcha
        Random random = new Random(ClientID.GetHashCode() + (int)DateTime.Now.Ticks);
        int num = random.Next(length);

        string choice = questions[num];

        // Prepare operands
        int op1 = random.Next(1, 10);
        int op2 = random.Next(1, 10);
        int result = 0;
        string chosenOperator = string.Empty;
        string captchaQuestion = string.Empty;
        string catpchaChoiceString = "error";

        // Generate chosen CAPTCHA
        switch (choice)
        {
            // Statements
            case CHOICE_STATEMENT:
                result = GetStatement(out captchaQuestion, random);
                if (result == -1)
                {
                    return;
                }
                break;

            // Image CAPTCHA
            case CHOICE_IMAGE:
                result = GetImageQuestion(out captchaQuestion, random);
                break;

            // Math and compare operations
            case CHOICE_PLUS:
                result = op1 + op2;
                chosenOperator = "+";
                catpchaChoiceString = CHOICE_MATH_OPERATION;
                break;

            case CHOICE_MINUS:
                result = op1 - op2;
                chosenOperator = "-";
                catpchaChoiceString = CHOICE_MATH_OPERATION;
                break;

            case CHOICE_MULT:
                result = op1 * op2;
                chosenOperator = "*";
                catpchaChoiceString = CHOICE_MATH_OPERATION;
                break;

            case CHOICE_DIV:
                bool correct = true;
                while (correct)
                {
                    // Swap numbers
                    if (op1 < op2)
                    {
                        int swap = op1;
                        op1 = op2;
                        op2 = swap;
                    }
                    // Check rest of division
                    if ((op1 % op2) == 0)
                    {
                        result = op1 / op2;
                        correct = false;
                    }
                    // Generate new numbers
                    else
                    {
                        op1 = random.Next(1, 10);
                        op2 = random.Next(1, 10);
                    }
                }

                chosenOperator = "/";
                catpchaChoiceString = CHOICE_MATH_OPERATION;
                break;

            case CHOICE_EQUAL:
                result = (op1 == op2) ? 1 : 0;
                chosenOperator = "=";
                catpchaChoiceString = CHOICE_EQUAL;
                break;

            case CHOICE_SMALLER:
                result = (op1 < op2) ? 1 : 0;
                chosenOperator = "<";
                catpchaChoiceString = CHOICE_COMPARE;
                break;

            case CHOICE_GREATER:
                result = (op1 > op2) ? 1 : 0;
                chosenOperator = ">";
                catpchaChoiceString = CHOICE_COMPARE;
                break;

            default:
                break;
        }

        // Build CAPTCHA question
        if ((choice != CHOICE_STATEMENT) && (choice != CHOICE_IMAGE))
        {
            // Handle operands
            string strOp1 = op1.ToString();
            string strOp2 = op2.ToString();

            if (ConvertOperandsToText)
            {
                strOp1 = GetString("captcha." + strOp1);
                strOp2 = GetString("captcha." + strOp2);
            }

            // Handle operator
            if (ConvertOperatorToText)
            {
                chosenOperator = GetString("captcha." + choice);
            }

            captchaQuestion = String.Format(GetString("captcha.question." + catpchaChoiceString), chosenOperator, strOp1, strOp2);
        }

        // Store in session
        WindowHelper.Add("CaptchaImageText" + ClientID, result);
        SessionHelper.SetValue("CaptchaOperation" + ClientID, choice);

        lblQuestion.Text = GetString(captchaQuestion);

        // Image
        plcImage.Visible = true;// (choice == CHOICE_IMAGE);
    }


    /// <summary>
    /// Gets random statement.
    /// <param name="statement">Output statement</param>
    /// <param name="random">Random generator</param>    
    /// </summary>
    private int GetStatement(out string statement, Random random)
    {
        statement = string.Empty;

        // Get random question
        string[] line = SelectLine(random, StatementQuestions);
        if ((line != null) && (line.Length == 2))
        {
            statement = line[0] + " " + GetString("captcha.statement");
            return ValidationHelper.GetInteger(line[1].TrimEnd('\r'), 0);
        }

        return -1;
    }


    /// <summary>
    /// Generates OCR CAPTCHA and get some question.
    /// </summary>
    /// <param name="question">Image question</param>
    /// <param name="random">Random generator</param>
    private int GetImageQuestion(out string question, Random random)
    {
        question = string.Empty;

        // Get random line from statements
        string[] line = SelectLine(random, ImageQuestions);
        if (line == null)
        {
            return -1;
        }

        string result = "0";

        // Handle chosen line
        if (line.Length == 2)
        {
            question = line[0];
            string statement = ValidationHelper.GetString(line[1].TrimEnd('\r'), string.Empty);

            // Generate random code
            string code = GenerateRandomCode();

            // Generate image            
            imgSecurityCode.ImageUrl = ResolveUrl(string.Format("~/CMSPages/Dialogs/CaptchaImage.aspx?hash={0}&captcha={1}&width={2}&height={3}", Guid.NewGuid(), ClientID + "Code", ImageWidth, ImageHeight));
            WindowHelper.Add("CaptchaImageText" + ClientID + "Code", code);

            // Get result
            switch (statement)
            {
                case "first":
                    result = code[0].ToString();
                    break;

                case "last":
                    result = code[5].ToString();
                    break;

                case "number":
                    // There is allways 6 digits in security code
                    result = "6";
                    break;

                case "firstandlast":
                    result = code[0].ToString() + code[5].ToString();
                    break;

                case "second":
                    result = code[1].ToString();
                    break;

                case "third":
                    result = code[2].ToString();
                    break;

                case "fourth":
                    result = code[3].ToString();
                    break;

                case "fith":
                    result = code[4].ToString();
                    break;

                case "firstandsecond":
                    result = code[0].ToString() + code[1].ToString();
                    break;

                case "max":
                    int max = 0;
                    for (int i = 0; i != code.Length; i++)
                    {
                        int current = ValidationHelper.GetInteger(code[i].ToString(), 0);
                        if (current > max)
                        {
                            max = current;
                        }
                    }
                    result = max.ToString();
                    break;

                case "min":
                    int min = 9;
                    for (int i = 0; i != code.Length; i++)
                    {
                        int current = ValidationHelper.GetInteger(code[i].ToString(), 9);
                        if (current < min)
                        {
                            min = current;
                        }
                    }
                    result = min.ToString();
                    break;

                default:
                    break;
            }
        }

        return ValidationHelper.GetInteger(result, 0);
    }


    /// <summary>
    /// Selects line randomly.
    /// </summary>
    /// <param name="random">Random generator</param>
    /// <param name="questions">Questions</param>
    /// <returns>Lines</returns>
    private string[] SelectLine(Random random, string questions)
    {
        ArrayList lines = null;

        // Get current culture
        string culture = ValidationHelper.GetString(ViewState["CultureCode"], LocalizationContext.PreferredCultureCode);
        string sitename = SiteContext.CurrentSiteName;

        // Get or generate cache item name
        string useCacheItemName = CacheHelper.BaseCacheKey + "|" + RequestContext.CurrentURL + "|" + ClientID + "|" + culture + "|" + UseTextOrImageCaptcha;

        // Try to get data from cache 
        if (CacheHelper.CacheMinutes(sitename) == 0)
        {
            // No caching
            CacheHelper.Remove(useCacheItemName);
            lines = GetLines(random, culture, questions);
        }
        else
        {
            object value = null;

            // Try to retrieve data from the cache
            if (!CacheHelper.TryGetItem(useCacheItemName, out value))
            {
                lines = GetLines(random, culture, questions);
                if ((lines != null) && (lines.Count > 0))
                {
                    CacheHelper.Add(useCacheItemName, lines, null, DateTime.Now.AddMinutes(CacheHelper.CacheMinutes(sitename)), Cache.NoSlidingExpiration);
                }
            }
            else
            {
                lines = (ArrayList)CacheHelper.GetItem(useCacheItemName);
            }
        }

        if ((lines != null) && (lines.Count > 0))
        {
            // Split selected line a return result.
            int selectedLine = random.Next(lines.Count);
            return lines[selectedLine].ToString().Split(';');
        }

        return null;
    }


    /// <summary>
    /// Gets all lines from specified file.
    /// </summary>
    /// <param name="path">Path to file</param>
    /// <param name="random">Random generator</param>
    /// <param name="cultureCode">Culture code</param>
    /// <param name="questions">Questions</param>
    private ArrayList GetLines(Random random, string cultureCode, string questions)
    {
        ArrayList lines = new ArrayList();

        if (string.IsNullOrEmpty(questions))
        {
            return null;
        }

        // Select one line, split it and return result
        string[] fileLines = questions.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

        // Add all lines into array list
        foreach (string line in fileLines)
        {
            lines.Add(line);
        }

        return lines;
    }

    #endregion
}