PageSourceSearch

https://tempr.email/js/app/user.js,thirdparty/captcha.js?v=179de

js tempr.email collected 2026-10-09 23:06:12 UTC 15,201 bytes, 404 lines download raw bytes

1
2
3
4var user = {
5
6    initialize: function() {
7        
8        user = this;
9
10        $(document).ready(function() {
11            user.initCaptcha();    
12        });
13        
14    },
15  
16
17    initCaptcha: function(form) {
18        main.showCaptcha('captcha', function() {
19        $.ajax({
20                url: '/api/verifyCaptcha.php',
21                method: 'POST',
22                dataType: 'json',
23                data: { 
24                    csrf_token: 'cbaad7f5f286da33429f2c3b52c391d371b231b23ddb65e2453dae9f886524fe', 
25                },
26                headers: {
27                    'X-Requested-With': 'XMLHttpRequest',
28                },
29                success: function(response) {
30                    if (typeof response.result !== 'undefined') {
31                        if (response.result !== false) {
32                            $('input#captcha_input').val(response.result);
33                        } else {
34                            $('input#captcha_input').val('');
35                        }
36                    }
37                }
38            });
39        });
40        $('#form-captcha').fadeIn('fast');
41        
42    },
43
44};
45
46user.initialize();
47
48
49
50
51(function () {
52    'use strict';
53
54    var extend = function () {
55        var length = arguments.length;
56        var target = arguments[0] || {};
57        if (typeof target != "object" && typeof target != "function") {
58            target = {};
59        }
60        if (length == 1) {
61            target = this;
62            i--;
63        }
64        for (var i = 1; i < length; i++) {
65            var source = arguments[i];
66            for (var key in source) {
67                // 使用for in会遍历数组所有的可枚举属性,包括原型。
68                if (Object.prototype.hasOwnProperty.call(source, key)) {
69                    target[key] = source[key];
70                }
71            }
72        }
73        return target;
74    }
75
76    var isFunction = function isFunction(obj) {
77        return typeof obj === "function" && typeof obj.nodeType !== "number";
78    };
79
80    var SliderCaptcha = function (element, options) {
81        this.$element = element;
82        this.options = extend({}, SliderCaptcha.DEFAULTS, options);
83        this.$element.style.position = 'relative';
84        this.$element.style.width = this.options.width + 'px';
85        this.$element.style.height = '200px';
86        if (!this.$element.style.margin) {
87            this.$element.style.margin = '0 auto';
88        }
89        this.init();
90    };
91
92    SliderCaptcha.VERSION = '1.0';
93    SliderCaptcha.Author = '[email protected]';
94    SliderCaptcha.DEFAULTS = {
95        width: 280,     // canvas宽度
96        height: 155,    // canvas高度
97        PI: Math.PI,
98        sliderL: 42,    // 滑块边长
99        sliderR: 9,     // 滑块半径
100        offset: 5,      // 容错偏差
101        loadingText: '正在加载中...',
102        failedText: '再试一次',
103        barText: '向右滑动填充拼图',
104        repeatIcon: 'fa fa-repeat',
105        maxLoadCount: 3,
106        localImages: function () {
107            return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';
108        },
109        verify: function (arr, url) {
110            var ret = false;
111            $.ajax({
112                url: url,
113                data: {
114                    "datas": JSON.stringify(arr),
115                },
116                dataType: "json",
117                type: "post",
118                async: false,
119                success: function (result) {
120                    ret = JSON.stringify(result);
121                    console.log("返回结果:" + ret)
122                }
123            });
124            return ret;
125        },
126        remoteUrl: null
127    };
128
129    function Plugin(option) {
130        var $this = document.getElementById(option.id);
131        var options = typeof option === 'object' && option;
132        return new SliderCaptcha($this, options);
133    }
134
135    window.sliderCaptcha = Plugin;
136    window.sliderCaptcha.Constructor = SliderCaptcha;
137
138    var _proto = SliderCaptcha.prototype;
139    _proto.init = function () {
140        this.initDOM();
141        this.initImg();
142        this.bindEvents();
143    };
144
145    _proto.initDOM = function () {
146        var createElement = function (tagName, className, html) {
147            var elment = document.createElement(tagName);
148            elment.className = className;
149            if (html) {
150                elment.innerHTML = html;
151            }
152            return elment;
153        };
154
155        var createCanvas = function (width, height) {
156            var canvas = document.createElement('canvas');
157            canvas.width = width;
158            canvas.height = height;
159            return canvas;
160        };
161
162        var canvas = createCanvas(this.options.width - 2, this.options.height); // 画布
163        var block = canvas.cloneNode(true); // 滑块
164        var sliderContainer = createElement('div', 'sliderContainer');
165        var refreshIcon = createElement('i', '', '');
166        var sliderMask = createElement('div', 'sliderMask');
167        var sliderbg = createElement('div', 'sliderbg');
168        var slider = createElement('div', 'slider');
169        var sliderIcon = createElement('span', '', '▶');
170        var text = createElement('span', 'sliderText');
171
172        block.className = 'block';
173        text.innerHTML = this.options.barText;
174
175        var el = this.$element;
176        el.appendChild(canvas);
177        el.appendChild(refreshIcon);
178        el.appendChild(block);
179        slider.appendChild(sliderIcon);
180        sliderMask.appendChild(slider);
181        sliderContainer.appendChild(sliderbg);
182        sliderContainer.appendChild(sliderMask);
183        sliderContainer.appendChild(text);
184        el.appendChild(sliderContainer);
185
186        var _canvas = {
187            canvas: canvas,
188            block: block,
189            sliderContainer: sliderContainer,
190            refreshIcon: refreshIcon,
191            slider: slider,
192            sliderMask: sliderMask,
193            sliderIcon: sliderIcon,
194            text: text,
195            canvasCtx: canvas.getContext('2d'),
196            blockCtx: block.getContext('2d')
197        };
198
199        if (isFunction(Object.assign)) {
200            Object.assign(this, _canvas);
201        }
202        else {
203            extend(this, _canvas);
204        }
205    };
206
207    _proto.initImg = function () {
208        var that = this;
209        var isIE = window.navigator.userAgent.indexOf('Trident') > -1;
210        var L = this.options.sliderL + this.options.sliderR * 2 + 3; 
211        var drawImg = function (ctx, operation) {
212            var l = that.options.sliderL;
213            var r = that.options.sliderR;
214            var PI = that.options.PI;
215            var x = that.x;
216            var y = that.y;
217            ctx.beginPath();
218            ctx.moveTo(x, y);
219            ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI);
220            ctx.lineTo(x + l, y);
221            ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI);
222            ctx.lineTo(x + l, y + l);
223            ctx.lineTo(x, y + l);
224            ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true);
225            ctx.lineTo(x, y);
226            ctx.lineWidth = 2;
227            ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
228            ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';
229            ctx.stroke();
230            ctx[operation]();
231            ctx.globalCompositeOperation = isIE ? 'xor' : 'destination-over';
232        };
233
234        var getRandomNumberByRange = function (start, end) {
235            return Math.round(Math.random() * (end - start) + start);
236        };
237        var img = new Image();
238        img.crossOrigin = "Anonymous";
239        var loadCount = 0;
240        img.onload = function () {
241            
242            that.x = getRandomNumberByRange(L + 10, that.options.width - (L + 10));
243            that.y = getRandomNumberByRange(10 + that.options.sliderR * 2, that.options.height - (L + 10));
244            drawImg(that.canvasCtx, 'fill');
245            drawImg(that.blockCtx, 'clip');
246
247            that.canvasCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
248            that.blockCtx.drawImage(img, 0, 0, that.options.width - 2, that.options.height);
249            var y = that.y - that.options.sliderR * 2 - 1;
250            var ImageData = that.blockCtx.getImageData(that.x - 3, y, L, L);
251            that.block.width = L;
252            that.blockCtx.putImageData(ImageData, 0, y + 1);
253            that.text.textContent = that.text.getAttribute('data-text');
254        };
255        img.onerror = function () {
256            loadCount++;
257            if (window.location.protocol === 'file:') {
258                loadCount = that.options.maxLoadCount;
259                console.error("can't load pic resource file from File protocal. Please try http or https");
260            }
261            if (loadCount >= that.options.maxLoadCount) {
262                that.text.textContent = '加载失败';
263                that.classList.add('text-danger');
264                return;
265            }
266            img.src = that.options.localImages();
267        };
268        img.setSrc = function () {
269            var src = '';
270            loadCount = 0;
271            that.text.classList.remove('text-danger');
272            if (isFunction(that.options.setSrc)) src = that.options.setSrc();
273            if (!src || src === '') src = 'https://picsum.photos/' + that.options.width + '/' + that.options.height + '/?image=' + Math.round(Math.random() * 20);
274            if (isIE) { 
275                var xhr = new XMLHttpRequest();
276                xhr.onloadend = function (e) {
277                    var file = new FileReader(); 
278                    file.readAsDataURL(e.target.response);
279                    file.onloadend = function (e) {
280                        img.src = e.target.result;
281                    };
282                };
283                xhr.open('GET', src);
284                xhr.responseType = 'blob';
285                xhr.send();
286            } else img.src = src;
287        };
288        img.setSrc();
289        this.text.setAttribute('data-text', this.options.barText);
290        this.text.textContent = this.options.loadingText;
291        this.img = img;
292    };
293
294    _proto.clean = function () {
295        this.canvasCtx.clearRect(0, 0, this.options.width, this.options.height);
296        this.blockCtx.clearRect(0, 0, this.options.width, this.options.height);
297        this.block.width = this.options.width;
298    };
299
300    _proto.bindEvents = function () {
301        var that = this;
302        this.$element.addEventListener('selectstart', function () {
303            return false;
304        });
305
306        this.refreshIcon.addEventListener('click', function () {
307            that.text.textContent = that.options.barText;
308            that.reset();
309            if (isFunction(that.options.onRefresh)) that.options.onRefresh.call(that.$element);
310        });
311
312        var originX, originY, trail = [],
313            isMouseDown = false;
314
315        var handleDragStart = function (e) {
316            if (that.text.classList.contains('text-danger')) return;
317            originX = e.clientX || e.touches[0].clientX;
318            originY = e.clientY || e.touches[0].clientY;
319            isMouseDown = true;
320        };
321
322        var handleDragMove = function (e) {
323            if (!isMouseDown) return false;
324            var eventX = e.clientX || e.touches[0].clientX;
325            var eventY = e.clientY || e.touches[0].clientY;
326            var moveX = eventX - originX;
327            var moveY = eventY - originY;
328            if (moveX < 0 || moveX + 40 > that.options.width) return false;
329            that.slider.style.left = (moveX - 1) + 'px';
330            var blockLeft = (that.options.width - 40 - 20) / (that.options.width - 40) * moveX;
331            that.block.style.left = blockLeft + 'px';
332
333            that.sliderContainer.classList.add('sliderContainer_active');
334            that.sliderMask.style.width = (moveX + 4) + 'px';
335            trail.push(Math.round(moveY));
336        };
337
338        var handleDragEnd = function (e) {
339            if (!isMouseDown) return false;
340            isMouseDown = false;
341            var eventX = e.clientX || e.changedTouches[0].clientX;
342            if (eventX === originX) return false;
343            that.sliderContainer.classList.remove('sliderContainer_active');
344            that.trail = trail;
345            var data = that.verify();
346            if (data.spliced && data.verified) {
347                that.sliderContainer.classList.add('sliderContainer_success');
348                if (isFunction(that.options.onSuccess)) that.options.onSuccess.call(that.$element);
349            } else {
350                that.sliderContainer.classList.add('sliderContainer_fail');
351                if (isFunction(that.options.onFail)) that.options.onFail.call(that.$element);
352                setTimeout(function () {
353                    that.text.innerHTML = that.options.failedText;
354                    that.reset();
355                }, 1000);
356            }
357        };
358
359        this.slider.addEventListener('mousedown', handleDragStart);
360        this.slider.addEventListener('touchstart', handleDragStart);
361        document.addEventListener('mousemove', handleDragMove);
362        document.addEventListener('touchmove', handleDragMove);
363        document.addEventListener('mouseup', handleDragEnd);
364        document.addEventListener('touchend', handleDragEnd);
365
366        document.addEventListener('mousedown', function () { return false; });
367        document.addEventListener('touchstart', function () { return false; });
368        document.addEventListener('swipe', function () { return false; });
369    };
370
371    _proto.verify = function () {
372        var arr = this.trail; 
373        var left = parseInt(this.block.style.left);
374        var verified = false;
375        if (this.options.remoteUrl !== null) {
376            verified = this.options.verify(arr, this.options.remoteUrl);
377        }
378        else {
379            var sum = function (x, y) { return x + y; };
380            var square = function (x) { return x * x; };
381            var average = arr.reduce(sum) / arr.length;
382            var deviations = arr.map(function (x) { return x - average; });
383            var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
384            verified = stddev !== 0;
385        }
386        return {
387            spliced: Math.abs(left - this.x) < this.options.offset,
388            verified: verified
389        };
390    };
391
392    _proto.reset = function () {
393        this.sliderContainer.classList.remove('sliderContainer_fail');
394        this.sliderContainer.classList.remove('sliderContainer_success');
395        this.slider.style.left = 0;
396        this.block.style.left = 0;
397        this.sliderMask.style.width = 0;
398        this.clean();
399        this.text.setAttribute('data-text', this.text.textContent);
400        this.text.textContent = this.options.loadingText;
401        this.img.setSrc();
402    };
403})();
404

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.