PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 2.0.3
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v2.0.3
3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / assets / js / mailcheck / mailcheck.js
everest-forms / assets / js / mailcheck Last commit date
mailcheck.js 4 years ago mailcheck.min.js 6 years ago
mailcheck.js
325 lines
1 /* globals define, module, jQuery */
2
3 /*
4 * Mailcheck https://github.com/mailcheck/mailcheck
5 * Author
6 * Derrick Ko (@derrickko)
7 *
8 * Released under the MIT License.
9 *
10 * v 1.1.2
11 */
12
13 var Mailcheck = {
14 domainThreshold: 2,
15 secondLevelThreshold: 2,
16 topLevelThreshold: 2,
17
18 defaultDomains: ['msn.com', 'bellsouth.net',
19 'telus.net', 'comcast.net', 'optusnet.com.au',
20 'earthlink.net', 'qq.com', 'sky.com', 'icloud.com',
21 'mac.com', 'sympatico.ca', 'googlemail.com',
22 'att.net', 'xtra.co.nz', 'web.de',
23 'cox.net', 'gmail.com', 'ymail.com',
24 'aim.com', 'rogers.com', 'verizon.net',
25 'rocketmail.com', 'google.com', 'optonline.net',
26 'sbcglobal.net', 'aol.com', 'me.com', 'btinternet.com',
27 'charter.net', 'shaw.ca'],
28
29 defaultSecondLevelDomains: ["yahoo", "hotmail", "mail", "live", "outlook", "gmx"],
30
31 defaultTopLevelDomains: ["com", "edu.au", "com.au", "com.tw", "ca", "co.nz", "co.uk", "de",
32 "fr", "it", "ru", "net", "org", "edu", "gov", "jp", "nl", "kr", "se", "eu",
33 "ie", "co.il", "us", "at", "be", "dk", "hk", "es", "gr", "ch", "no", "cz",
34 "in", "net", "net.au", "info", "biz", "mil", "co.jp", "sg", "hu", "uk"],
35
36 run: function(opts) {
37 opts.domains = opts.domains || Mailcheck.defaultDomains;
38 opts.secondLevelDomains = opts.secondLevelDomains || Mailcheck.defaultSecondLevelDomains;
39 opts.topLevelDomains = opts.topLevelDomains || Mailcheck.defaultTopLevelDomains;
40 opts.distanceFunction = opts.distanceFunction || Mailcheck.sift4Distance;
41
42 var defaultCallback = function(result){ return result; };
43 var suggestedCallback = opts.suggested || defaultCallback;
44 var emptyCallback = opts.empty || defaultCallback;
45
46 var result = Mailcheck.suggest(Mailcheck.encodeEmail(opts.email), opts.domains, opts.secondLevelDomains, opts.topLevelDomains, opts.distanceFunction);
47
48 return result ? suggestedCallback(result) : emptyCallback();
49 },
50
51 suggest: function(email, domains, secondLevelDomains, topLevelDomains, distanceFunction) {
52 email = email.toLowerCase();
53
54 var emailParts = this.splitEmail(email);
55
56 if (secondLevelDomains && topLevelDomains) {
57 // If the email is a valid 2nd-level + top-level, do not suggest anything.
58 if (secondLevelDomains.indexOf(emailParts.secondLevelDomain) !== -1 && topLevelDomains.indexOf(emailParts.topLevelDomain) !== -1) {
59 return false;
60 }
61 }
62
63 var closestDomain = this.findClosestDomain(emailParts.domain, domains, distanceFunction, this.domainThreshold);
64
65 if (closestDomain) {
66 if (closestDomain == emailParts.domain) {
67 // The email address exactly matches one of the supplied domains; do not return a suggestion.
68 return false;
69 } else {
70 // The email address closely matches one of the supplied domains; return a suggestion
71 return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain };
72 }
73 }
74
75 // The email address does not closely match one of the supplied domains
76 var closestSecondLevelDomain = this.findClosestDomain(emailParts.secondLevelDomain, secondLevelDomains, distanceFunction, this.secondLevelThreshold);
77 var closestTopLevelDomain = this.findClosestDomain(emailParts.topLevelDomain, topLevelDomains, distanceFunction, this.topLevelThreshold);
78
79 if (emailParts.domain) {
80 closestDomain = emailParts.domain;
81 var rtrn = false;
82
83 if(closestSecondLevelDomain && closestSecondLevelDomain != emailParts.secondLevelDomain) {
84 // The email address may have a mispelled second-level domain; return a suggestion
85 closestDomain = closestDomain.replace(emailParts.secondLevelDomain, closestSecondLevelDomain);
86 rtrn = true;
87 }
88
89 if(closestTopLevelDomain && closestTopLevelDomain != emailParts.topLevelDomain && emailParts.secondLevelDomain !== '') {
90 // The email address may have a mispelled top-level domain; return a suggestion
91 closestDomain = closestDomain.replace(new RegExp(emailParts.topLevelDomain + "$"), closestTopLevelDomain);
92 rtrn = true;
93 }
94
95 if (rtrn) {
96 return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain };
97 }
98 }
99
100 /* The email address exactly matches one of the supplied domains, does not closely
101 * match any domain and does not appear to simply have a mispelled top-level domain,
102 * or is an invalid email address; do not return a suggestion.
103 */
104 return false;
105 },
106
107 findClosestDomain: function(domain, domains, distanceFunction, threshold) {
108 threshold = threshold || this.topLevelThreshold;
109 var dist;
110 var minDist = Infinity;
111 var closestDomain = null;
112
113 if (!domain || !domains) {
114 return false;
115 }
116 if(!distanceFunction) {
117 distanceFunction = this.sift4Distance;
118 }
119
120 for (var i = 0; i < domains.length; i++) {
121 if (domain === domains[i]) {
122 return domain;
123 }
124 dist = distanceFunction(domain, domains[i]);
125 if (dist < minDist) {
126 minDist = dist;
127 closestDomain = domains[i];
128 }
129 }
130
131 if (minDist <= threshold && closestDomain !== null) {
132 return closestDomain;
133 } else {
134 return false;
135 }
136 },
137
138 sift4Distance: function(s1, s2, maxOffset) {
139 // sift4: https://siderite.blogspot.com/2014/11/super-fast-and-accurate-string-distance.html
140 if (maxOffset === undefined) {
141 maxOffset = 5; //default
142 }
143
144 if (!s1||!s1.length) {
145 if (!s2) {
146 return 0;
147 }
148 return s2.length;
149 }
150
151 if (!s2||!s2.length) {
152 return s1.length;
153 }
154
155 var l1=s1.length;
156 var l2=s2.length;
157
158 var c1 = 0; //cursor for string 1
159 var c2 = 0; //cursor for string 2
160 var lcss = 0; //largest common subsequence
161 var local_cs = 0; //local common substring
162 var trans = 0; //number of transpositions ('ab' vs 'ba')
163 var offset_arr=[]; //offset pair array, for computing the transpositions
164
165 while ((c1 < l1) && (c2 < l2)) {
166 if (s1.charAt(c1) == s2.charAt(c2)) {
167 local_cs++;
168 var isTrans=false;
169 //see if current match is a transposition
170 var i=0;
171 while (i<offset_arr.length) {
172 var ofs=offset_arr[i];
173 if (c1<=ofs.c1 || c2 <= ofs.c2) {
174 // when two matches cross, the one considered a transposition is the one with the largest difference in offsets
175 isTrans=Math.abs(c2-c1)>=Math.abs(ofs.c2-ofs.c1);
176 if (isTrans)
177 {
178 trans++;
179 } else
180 {
181 if (!ofs.trans) {
182 ofs.trans=true;
183 trans++;
184 }
185 }
186 break;
187 } else {
188 if (c1>ofs.c2 && c2>ofs.c1) {
189 offset_arr.splice(i,1);
190 } else {
191 i++;
192 }
193 }
194 }
195 offset_arr.push({
196 c1:c1,
197 c2:c2,
198 trans:isTrans
199 });
200 } else {
201 lcss+=local_cs;
202 local_cs=0;
203 if (c1!=c2) {
204 c1=c2=Math.min(c1,c2); //using min allows the computation of transpositions
205 }
206 //if matching characters are found, remove 1 from both cursors (they get incremented at the end of the loop)
207 //so that we can have only one code block handling matches
208 for (var j = 0; j < maxOffset && (c1+j<l1 || c2+j<l2); j++) {
209 if ((c1 + j < l1) && (s1.charAt(c1 + j) == s2.charAt(c2))) {
210 c1+= j-1;
211 c2--;
212 break;
213 }
214 if ((c2 + j < l2) && (s1.charAt(c1) == s2.charAt(c2 + j))) {
215 c1--;
216 c2+= j-1;
217 break;
218 }
219 }
220 }
221 c1++;
222 c2++;
223 // this covers the case where the last match is on the last token in list, so that it can compute transpositions correctly
224 if ((c1 >= l1) || (c2 >= l2)) {
225 lcss+=local_cs;
226 local_cs=0;
227 c1=c2=Math.min(c1,c2);
228 }
229 }
230 lcss+=local_cs;
231 return Math.round(Math.max(l1,l2)- lcss +trans); //add the cost of transpositions to the final result
232 },
233
234 splitEmail: function(email) {
235 email = email !== null ? (email.replace(/^\s*/, '').replace(/\s*$/, '')) : null; // trim() not exist in old IE!
236 var parts = email.split('@');
237
238 if (parts.length < 2) {
239 return false;
240 }
241
242 for (var i = 0; i < parts.length; i++) {
243 if (parts[i] === '') {
244 return false;
245 }
246 }
247
248 var domain = parts.pop();
249 var domainParts = domain.split('.');
250 var sld = '';
251 var tld = '';
252
253 if (domainParts.length === 0) {
254 // The address does not have a top-level domain
255 return false;
256 } else if (domainParts.length == 1) {
257 // The address has only a top-level domain (valid under RFC)
258 tld = domainParts[0];
259 } else {
260 // The address has a domain and a top-level domain
261 sld = domainParts[0];
262 for (var j = 1; j < domainParts.length; j++) {
263 tld += domainParts[j] + '.';
264 }
265 tld = tld.substring(0, tld.length - 1);
266 }
267
268 return {
269 topLevelDomain: tld,
270 secondLevelDomain: sld,
271 domain: domain,
272 address: parts.join('@')
273 };
274 },
275
276 // Encode the email address to prevent XSS but leave in valid
277 // characters, following this official spec:
278 // http://en.wikipedia.org/wiki/Email_address#Syntax
279 encodeEmail: function(email) {
280 var result = encodeURI(email);
281 result = result.replace('%20', ' ').replace('%25', '%').replace('%5E', '^')
282 .replace('%60', '`').replace('%7B', '{').replace('%7C', '|')
283 .replace('%7D', '}');
284 return result;
285 }
286 };
287
288 // Export the mailcheck object if we're in a CommonJS env (e.g. Node).
289 // Modeled off of Underscore.js.
290 if (typeof module !== 'undefined' && module.exports) {
291 module.exports = Mailcheck;
292 }
293
294 // Support AMD style definitions
295 // Based on jQuery (see http://stackoverflow.com/a/17954882/1322410)
296 if (typeof define === "function" && define.amd) {
297 define("mailcheck", [], function() {
298 return Mailcheck;
299 });
300 }
301
302 if (typeof window !== 'undefined' && window.jQuery) {
303 (function($){
304 $.fn.mailcheck = function(opts) {
305 var self = this;
306 if (opts.suggested) {
307 var oldSuggested = opts.suggested;
308 opts.suggested = function(result) {
309 oldSuggested(self, result);
310 };
311 }
312
313 if (opts.empty) {
314 var oldEmpty = opts.empty;
315 opts.empty = function() {
316 oldEmpty.call(null, self);
317 };
318 }
319
320 opts.email = this.val();
321 Mailcheck.run(opts);
322 };
323 })(jQuery);
324 }
325