|
1 | 1 | {if $recaptchaLegacyMode|empty} |
2 | 2 | {include file='shared_captcha'} |
3 | 3 | {else} |
4 | | - {if RECAPTCHA_PUBLICKEY && RECAPTCHA_PRIVATEKEY} |
5 | | - {if $supportsAsyncCaptcha|isset && $supportsAsyncCaptcha && RECAPTCHA_PUBLICKEY_INVISIBLE && RECAPTCHA_PRIVATEKEY_INVISIBLE} |
6 | | - {assign var="recaptchaBucketID" value=true|microtime|sha1} |
7 | | - <dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}"> |
8 | | - <dt><label>{lang}wcf.recaptcha.title{/lang}</label></dt> |
9 | | - <dd> |
10 | | - <input type="hidden" name="recaptcha-type" value="invisible"> |
11 | | - <div id="recaptchaBucket{$recaptchaBucketID}"></div> |
12 | | - <noscript> |
13 | | - <div style="width: 302px; height: 473px;"> |
14 | | - <div style="width: 302px; height: 422px; position: relative;"> |
15 | | - <div style="width: 302px; height: 422px; position: relative;"> |
16 | | - <iframe src="https://www.google.com/recaptcha/api/fallback?k={RECAPTCHA_PUBLICKEY_INVISIBLE|encodeJS}" frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe> |
17 | | - </div> |
18 | | - <div style="width: 300px; height: 60px; position: relative; border-style: none; bottom: 12px; left: 0; margin: 0px; padding: 0px; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;"> |
19 | | - <textarea name="g-recaptcha-response" class="g-recaptcha-response" style="width: 290px; height: 50px; border: 1px solid #c1c1c1; margin: 5px; padding: 0px; resize: none;"></textarea> |
20 | | - </div> |
21 | | - </div> |
22 | | - </div> |
23 | | - </noscript> |
24 | | - {if (($errorType|isset && $errorType|is_array && $errorType[recaptchaString]|isset) || ($errorField|isset && $errorField == 'recaptchaString'))} |
25 | | - {if $errorType|is_array && $errorType[recaptchaString]|isset} |
26 | | - {assign var='__errorType' value=$errorType[recaptchaString]} |
27 | | - {else} |
28 | | - {assign var='__errorType' value=$errorType} |
29 | | - {/if} |
30 | | - <small class="innerError"> |
31 | | - {if $__errorType == 'empty'} |
32 | | - {lang}wcf.global.form.error.empty{/lang} |
33 | | - {else} |
34 | | - {lang}wcf.captcha.recaptchaInvisible.error.recaptchaString.{$__errorType}{/lang} |
35 | | - {/if} |
36 | | - </small> |
37 | | - {/if} |
38 | | - </dd> |
39 | | - </dl> |
40 | | - <script data-relocate="true"> |
41 | | - if (!WCF.recaptcha) { |
42 | | - WCF.recaptcha = { |
43 | | - queue: [], |
44 | | - callbackCalled: false, |
45 | | - mapping: { } |
46 | | - }; |
47 | | - |
48 | | - // this needs to be in global scope |
49 | | - function recaptchaCallback() { |
50 | | - var bucketId; |
51 | | - WCF.recaptcha.callbackCalled = true; |
52 | | - |
53 | | - // clear queue |
54 | | - while (config = WCF.recaptcha.queue.shift()) { |
55 | | - (function (config) { |
56 | | - var bucketId = config.bucket; |
57 | | - |
58 | | - require(['Dom/Traverse', 'Dom/Util'], function (DomTraverse, DomUtil) { |
59 | | - var bucket = elById(bucketId); |
60 | | - |
61 | | - var promise = new Promise(function (resolve, reject) { |
62 | | - WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}'] = grecaptcha.render(bucket, { |
63 | | - sitekey: '{RECAPTCHA_PUBLICKEY_INVISIBLE|encodeJS}', |
64 | | - size: 'invisible', |
65 | | - badge: 'inline', |
66 | | - callback: resolve, |
67 | | - theme: document.documentElement.dataset.colorScheme === "dark" ? "dark" : "light" |
68 | | - }); |
69 | | - }); |
70 | | - |
71 | | - if (config.ajaxCaptcha) { |
72 | | - WCF.System.Captcha.addCallback(config.ajaxCaptcha, function() { |
73 | | - grecaptcha.execute(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']); |
74 | | - return promise.then(function (token) { |
75 | | - return { |
76 | | - 'g-recaptcha-response': token, |
77 | | - 'recaptcha-type': 'invisible' |
78 | | - }; |
79 | | - }); |
80 | | - }); |
81 | | - } |
82 | | - else { |
83 | | - var form = DomTraverse.parentByTag(bucket, 'FORM'); |
84 | | - |
85 | | - var pressed = undefined; |
86 | | - elBySelAll('input[type=submit]', form, function (button) { |
87 | | - button.addEventListener('click', function (event) { |
88 | | - pressed = button; |
89 | | - }); |
90 | | - }); |
91 | | - |
92 | | - var listener = function (event) { |
93 | | - event.preventDefault(); |
94 | | - promise.then(function (token) { |
95 | | - form.removeEventListener('submit', listener); |
96 | | - pressed.disabled = false; |
97 | | - pressed.click(); |
98 | | - }); |
99 | | - grecaptcha.execute(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']); |
100 | | - } |
101 | | - form.addEventListener('submit', listener); |
102 | | - } |
103 | | - |
104 | | - }); |
105 | | - })(config); |
106 | | - } |
107 | | - } |
108 | | - } |
109 | | - |
110 | | - // add captcha to queue |
111 | | - WCF.recaptcha.queue.push({ |
112 | | - bucket: 'recaptchaBucket{$recaptchaBucketID}' |
113 | | - {if $ajaxCaptcha|isset && $ajaxCaptcha} |
114 | | - , ajaxCaptcha: '{$captchaID}' |
115 | | - {/if} |
116 | | - }); |
117 | | - |
118 | | - // trigger callback immediately, if API already is available |
119 | | - if (WCF.recaptcha.callbackCalled) setTimeout(recaptchaCallback, 1); |
120 | | - |
121 | | - // ensure recaptcha API is loaded at most once |
122 | | - if (!window.grecaptcha) $.getScript('https://www.google.com/recaptcha/api.js?render=explicit&onload=recaptchaCallback'); |
123 | | - </script> |
| 4 | + {if RECAPTCHA_PUBLICKEY_V3 && RECAPTCHA_PRIVATEKEY_V3} |
| 5 | + {assign var="recaptchaType" value="v3"} |
| 6 | + {assign var="recaptchaPublicKey" value=RECAPTCHA_PUBLICKEY_V3} |
| 7 | + {elseif RECAPTCHA_PUBLICKEY && RECAPTCHA_PRIVATEKEY} |
| 8 | + {if RECAPTCHA_PUBLICKEY_INVISIBLE && RECAPTCHA_PRIVATEKEY_INVISIBLE} |
| 9 | + {assign var="recaptchaType" value="invisible"} |
| 10 | + {assign var="recaptchaPublicKey" value=RECAPTCHA_PUBLICKEY_INVISIBLE} |
124 | 11 | {else} |
125 | | - {assign var="recaptchaBucketID" value=true|microtime|sha1} |
126 | | - <dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}"> |
127 | | - <dt><label>{lang}wcf.recaptcha.title{/lang}</label></dt> |
128 | | - <dd> |
129 | | - <input type="hidden" name="recaptcha-type" value="v2"> |
130 | | - <div id="recaptchaBucket{$recaptchaBucketID}"></div> |
131 | | - <noscript> |
132 | | - <div style="width: 302px; height: 473px;"> |
133 | | - <div style="width: 302px; height: 422px; position: relative;"> |
134 | | - <div style="width: 302px; height: 422px; position: relative;"> |
135 | | - <iframe src="https://www.google.com/recaptcha/api/fallback?k={RECAPTCHA_PUBLICKEY|encodeJS}" frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe> |
136 | | - </div> |
137 | | - <div style="width: 300px; height: 60px; position: relative; border-style: none; bottom: 12px; left: 0; margin: 0px; padding: 0px; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;"> |
138 | | - <textarea name="g-recaptcha-response" class="g-recaptcha-response" style="width: 290px; height: 50px; border: 1px solid #c1c1c1; margin: 5px; padding: 0px; resize: none;"></textarea> |
139 | | - </div> |
140 | | - </div> |
141 | | - </div> |
142 | | - </noscript> |
143 | | - {if (($errorType|isset && $errorType|is_array && $errorType[recaptchaString]|isset) || ($errorField|isset && $errorField == 'recaptchaString'))} |
144 | | - {if $errorType|is_array && $errorType[recaptchaString]|isset} |
145 | | - {assign var='__errorType' value=$errorType[recaptchaString]} |
| 12 | + {assign var="recaptchaType" value="v2"} |
| 13 | + {assign var="recaptchaPublicKey" value=RECAPTCHA_PUBLICKEY} |
| 14 | + {/if} |
| 15 | + {/if} |
| 16 | + {if !$ajaxCaptcha|isset} |
| 17 | + {assign var="ajaxCaptcha" value=false} |
| 18 | + {/if} |
| 19 | + |
| 20 | + {if $recaptchaType|isset && $recaptchaPublicKey|isset} |
| 21 | + {assign var="recaptchaBucketID" value=true|microtime|sha1} |
| 22 | + <dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}"> |
| 23 | + <dt>{if $recaptchaType !== "v3"}<label>{lang}wcf.recaptcha.title{/lang}</label>{/if}</dt> |
| 24 | + <dd> |
| 25 | + <input type="hidden" name="recaptcha-type" value="{$recaptchaType}"> |
| 26 | + <div id="recaptchaBucket{$recaptchaBucketID}"></div> |
| 27 | + {if (($errorType|isset && $errorType|is_array && $errorType[recaptchaString]|isset) || ($errorField|isset && $errorField == 'recaptchaString'))} |
| 28 | + {if $errorType|is_array && $errorType[recaptchaString]|isset} |
| 29 | + {assign var='__errorType' value=$errorType[recaptchaString]} |
| 30 | + {else} |
| 31 | + {assign var='__errorType' value=$errorType} |
| 32 | + {/if} |
| 33 | + <small class="innerError"> |
| 34 | + {if $__errorType == 'empty'} |
| 35 | + {lang}wcf.global.form.error.empty{/lang} |
146 | 36 | {else} |
147 | | - {assign var='__errorType' value=$errorType} |
| 37 | + {lang}wcf.captcha.recaptcha{$recaptchaType|ucfirst}.error.recaptchaString.{$__errorType}{/lang} |
148 | 38 | {/if} |
149 | | - <small class="innerError"> |
150 | | - {if $__errorType == 'empty'} |
151 | | - {lang}wcf.global.form.error.empty{/lang} |
152 | | - {else} |
153 | | - {lang}wcf.captcha.recaptchaV2.error.recaptchaString.{$__errorType}{/lang} |
154 | | - {/if} |
155 | | - </small> |
156 | | - {/if} |
157 | | - </dd> |
158 | | - </dl> |
159 | | - <script data-relocate="true"> |
160 | | - if (!WCF.recaptcha) { |
161 | | - WCF.recaptcha = { |
162 | | - queue: [], |
163 | | - callbackCalled: false, |
164 | | - mapping: { } |
165 | | - }; |
166 | | - |
167 | | - // this needs to be in global scope |
168 | | - function recaptchaCallback() { |
169 | | - var bucket; |
170 | | - WCF.recaptcha.callbackCalled = true; |
171 | | - |
172 | | - // clear queue |
173 | | - while (bucket = WCF.recaptcha.queue.shift()) { |
174 | | - WCF.recaptcha.mapping[bucket] = grecaptcha.render(bucket, { |
175 | | - 'sitekey' : '{RECAPTCHA_PUBLICKEY|encodeJS}', |
176 | | - theme: document.documentElement.dataset.colorScheme === "dark" ? "dark" : "light" |
177 | | - }); |
178 | | - } |
179 | | - } |
180 | | - } |
181 | | - |
182 | | - // add captcha to queue |
183 | | - WCF.recaptcha.queue.push('recaptchaBucket{$recaptchaBucketID}'); |
184 | | - |
185 | | - // trigger callback immediately, if API already is available |
186 | | - if (WCF.recaptcha.callbackCalled) setTimeout(recaptchaCallback, 1); |
187 | | - |
188 | | - {if $ajaxCaptcha|isset && $ajaxCaptcha} |
189 | | - WCF.System.Captcha.addCallback('{$captchaID}', function() { |
190 | | - return { |
191 | | - 'g-recaptcha-response': grecaptcha.getResponse(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']), |
192 | | - 'type': 'v2' |
193 | | - }; |
| 39 | + </small> |
| 40 | + {/if} |
| 41 | + </dd> |
| 42 | + </dl> |
| 43 | + <script data-relocate="true"> |
| 44 | + require(['WoltLabSuite/Core/Component/Captcha/Recaptcha'], ({ Recaptcha }) => { |
| 45 | + new Recaptcha('{$recaptchaType}', '{$recaptchaPublicKey|encodeJS}', 'recaptchaBucket{$recaptchaBucketID}'{if $ajaxCaptcha}, '{$captchaID|encodeJS}'{/if}); |
194 | 46 | }); |
195 | | - {/if} |
196 | | - |
197 | | - // ensure recaptcha API is loaded at most once |
198 | | - if (!window.grecaptcha) $.getScript('https://www.google.com/recaptcha/api.js?render=explicit&onload=recaptchaCallback'); |
199 | | - </script> |
200 | | - {/if} |
| 47 | + </script> |
201 | 48 | {/if} |
202 | 49 | {/if} |
0 commit comments