Try your search with a different keyword or use * as a wildcard.
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Nop.Core;
using Nop.Core.Domain.Security;
using Nop.Core.Infrastructure;
using Nop.Services.Localization;
using Nop.Services.Security;
using Nop.Web.Framework.Extensions;
namespace Nop.Web.Framework.Security.Captcha;
///
/// HTML extensions
///
public static class HtmlExtensions
{
#region Utilities
///
/// Get the reCAPTCHA language
///
/// Captcha settings
///
/// A task that represents the asynchronous operation
/// The task result contains the language code
///
private static async Task GetReCaptchaLanguageAsync(CaptchaSettings captchaSettings)
{
var language = (captchaSettings.ReCaptchaDefaultLanguage ?? string.Empty).ToLowerInvariant();
if (captchaSettings.AutomaticallyChooseLanguage)
{
//this list got from this site: https://developers.google.com/recaptcha/docs/language
//but we use languages only with two letters in the code
var supportedLanguageCodes = new List { "af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", "et", "eu", "fa", "fi", "fil", "fr", "gl", "gu", "hi", "hr", "hu", "hy", "id", "is", "it", "iw", "ja", "ka", "kn", "ko", "lo", "lt", "lv", "ml", "mn", "mr", "ms", "nl", "no", "pl", "pt", "ro", "ru", "si", "sk", "sl", "sr", "sv", "sw", "ta", "te", "th", "tr", "uk", "ur", "vi", "zu" };
var languageService = EngineContext.Current.Resolve();
var workContext = EngineContext.Current.Resolve();
var currentLanguage = await workContext.GetWorkingLanguageAsync();
var twoLetterIsoCode = currentLanguage != null
? languageService.GetTwoLetterIsoLanguageName(currentLanguage).ToLowerInvariant()
: string.Empty;
language = supportedLanguageCodes.Contains(twoLetterIsoCode) ? twoLetterIsoCode : language;
}
return language;
}
///
/// Generate API script tag
///
/// Captcha settings
/// Captcha ID
/// Render
/// Language
/// Script tag
private static TagBuilder GenerateLoadApiScriptTag(CaptchaSettings captchaSettings, string captchaId, string render, string language)
{
var hl = !string.IsNullOrEmpty(language)
? $"&hl={language}"
: string.Empty;
var url = string.Format($"{captchaSettings.ReCaptchaApiUrl}{NopSecurityDefaults.RecaptchaScriptPath}", captchaId, render, hl);
var scriptLoadApiTag = new TagBuilder("script") { TagRenderMode = TagRenderMode.Normal };
scriptLoadApiTag.Attributes.Add("src", url);
scriptLoadApiTag.Attributes.Add("async", null);
scriptLoadApiTag.Attributes.Add("defer", null);
return scriptLoadApiTag;
}
#endregion
#region Methods
///
/// Generate reCAPTCHA Control
///
/// HTML helper
/// Captcha settings
///
/// A task that represents the asynchronous operation
/// The task result contains the result
///
public static async Task GenerateCheckBoxReCaptchaV2Async(this IHtmlHelper helper, CaptchaSettings captchaSettings)
{
//prepare language
var language = await GetReCaptchaLanguageAsync(captchaSettings);
//prepare theme
var theme = (captchaSettings.ReCaptchaTheme ?? string.Empty).ToLowerInvariant();
theme = theme switch
{
"blackglass" or "dark" => "dark",
"clean" or "red" or "white" or "light" => "light",
_ => "light",
};
//prepare identifier
var id = $"captcha_{CommonHelper.GenerateRandomInteger()}";
//prepare public key
var publicKey = captchaSettings.ReCaptchaPublicKey ?? string.Empty;
//generate reCAPTCHA Control
var scriptCallbackTag = new TagBuilder("script") { TagRenderMode = TagRenderMode.Normal };
scriptCallbackTag.InnerHtml
.AppendHtml($"var onloadCallback{id} = function() {{grecaptcha.render('{id}', {{'sitekey' : '{publicKey}', 'theme' : '{theme}' }});}};");
var captchaTag = new TagBuilder("div") { TagRenderMode = TagRenderMode.Normal };
captchaTag.Attributes.Add("id", id);
var scriptLoadApiTag = GenerateLoadApiScriptTag(captchaSettings, id, "explicit", language);
return new HtmlString(await scriptCallbackTag.RenderHtmlContentAsync() + await captchaTag.RenderHtmlContentAsync() + await scriptLoadApiTag.RenderHtmlContentAsync());
}
///
/// Generate reCAPTCHA v3 Control
///
/// HTML helper
/// Captcha settings
/// Action name
///
/// A task that represents the asynchronous operation
/// The task result contains the result
///
public static async Task GenerateReCaptchaV3Async(this IHtmlHelper helper, CaptchaSettings captchaSettings, string actionName = null)
{
//prepare language
var language = await GetReCaptchaLanguageAsync(captchaSettings);
//prepare identifier
var id = $"captcha_{CommonHelper.GenerateRandomInteger()}";
//prepare public key
var publicKey = captchaSettings.ReCaptchaPublicKey ?? string.Empty;
//prepare reCAPTCHA script
if (string.IsNullOrEmpty(actionName))
actionName = helper.ViewContext.RouteData.Values["action"].ToString();
var scriptCallback = $@"
var onloadCallback{id} = function() {{
var form = $('input[id=""g-recaptcha-response_{id}""]').closest('form');
var btn = $(form.find(':submit')[0]);
var actionBtn = btn.data('action');
if (actionBtn == null) {{
actionBtn = '{actionName}';
}}
var loaded = false;
var isBusy = false;
btn.on('click', function (e) {{
if (!isBusy) {{
isBusy = true;
grecaptcha.execute('{publicKey}', {{ 'action': actionBtn }}).then(function(token) {{
$('#g-recaptcha-response_{id}', form).val(token);
loaded = true;
btn.trigger('click');
}});
}}
return loaded;
}});
}}
";
var scriptCallbackTag = new TagBuilder("script") { TagRenderMode = TagRenderMode.Normal };
scriptCallbackTag.InnerHtml.AppendHtml(scriptCallback);
//prepare reCAPTCHA token input
var captchaTokenInput = new TagBuilder("input") { TagRenderMode = TagRenderMode.Normal };
captchaTokenInput.Attributes.Add("type", "hidden");
captchaTokenInput.Attributes.Add("id", $"g-recaptcha-response_{id}");
captchaTokenInput.Attributes.Add("name", "g-recaptcha-response");
var scriptLoadApiTag = GenerateLoadApiScriptTag(captchaSettings, id, publicKey, language);
return new HtmlString(await captchaTokenInput.RenderHtmlContentAsync() + await scriptCallbackTag.RenderHtmlContentAsync() + await scriptLoadApiTag.RenderHtmlContentAsync());
}
#endregion
}