Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/format/emailaddress.js
2868 views
1
// Copyright 2010 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Provides functions to parse and manipulate email addresses.
17
*
18
*/
19
20
goog.provide('goog.format.EmailAddress');
21
22
goog.require('goog.string');
23
24
25
26
/**
27
* Formats an email address string for display, and allows for extraction of
28
* the individual components of the address.
29
* @param {string=} opt_address The email address.
30
* @param {string=} opt_name The name associated with the email address.
31
* @constructor
32
*/
33
goog.format.EmailAddress = function(opt_address, opt_name) {
34
/**
35
* The name or personal string associated with the address.
36
* @type {string}
37
* @private
38
*/
39
this.name_ = opt_name || '';
40
41
/**
42
* The email address.
43
* @type {string}
44
* @protected
45
*/
46
this.address = opt_address || '';
47
};
48
49
50
/**
51
* Match string for opening tokens.
52
* @type {string}
53
* @private
54
*/
55
goog.format.EmailAddress.OPENERS_ = '"<([';
56
57
58
/**
59
* Match string for closing tokens.
60
* @type {string}
61
* @private
62
*/
63
goog.format.EmailAddress.CLOSERS_ = '">)]';
64
65
66
/**
67
* Match string for characters that require display names to be quoted and are
68
* not address separators.
69
* @type {string}
70
* @const
71
* @package
72
*/
73
goog.format.EmailAddress.SPECIAL_CHARS = '()<>@:\\\".[]';
74
75
76
/**
77
* Match string for address separators.
78
* @type {string}
79
* @const
80
* @private
81
*/
82
goog.format.EmailAddress.ADDRESS_SEPARATORS_ = ',;';
83
84
85
/**
86
* Match string for characters that, when in a display name, require it to be
87
* quoted.
88
* @type {string}
89
* @const
90
* @private
91
*/
92
goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_ =
93
goog.format.EmailAddress.SPECIAL_CHARS +
94
goog.format.EmailAddress.ADDRESS_SEPARATORS_;
95
96
97
/**
98
* A RegExp to match all double quotes. Used in cleanAddress().
99
* @type {RegExp}
100
* @private
101
*/
102
goog.format.EmailAddress.ALL_DOUBLE_QUOTES_ = /\"/g;
103
104
105
/**
106
* A RegExp to match escaped double quotes. Used in parse().
107
* @type {RegExp}
108
* @private
109
*/
110
goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_ = /\\\"/g;
111
112
113
/**
114
* A RegExp to match all backslashes. Used in cleanAddress().
115
* @type {RegExp}
116
* @private
117
*/
118
goog.format.EmailAddress.ALL_BACKSLASHES_ = /\\/g;
119
120
121
/**
122
* A RegExp to match escaped backslashes. Used in parse().
123
* @type {RegExp}
124
* @private
125
*/
126
goog.format.EmailAddress.ESCAPED_BACKSLASHES_ = /\\\\/g;
127
128
129
/**
130
* A string representing the RegExp for the local part of an email address.
131
* @private {string}
132
*/
133
goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ =
134
'[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~-]+';
135
136
137
/**
138
* A string representing the RegExp for the domain part of an email address.
139
* @private {string}
140
*/
141
goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ =
142
'([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9]{2,63}';
143
144
145
/**
146
* A RegExp to match the local part of an email address.
147
* @private {!RegExp}
148
*/
149
goog.format.EmailAddress.LOCAL_PART_ =
150
new RegExp('^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '$');
151
152
153
/**
154
* A RegExp to match the domain part of an email address.
155
* @private {!RegExp}
156
*/
157
goog.format.EmailAddress.DOMAIN_PART_ =
158
new RegExp('^' + goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
159
160
161
/**
162
* A RegExp to match an email address.
163
* @private {!RegExp}
164
*/
165
goog.format.EmailAddress.EMAIL_ADDRESS_ = new RegExp(
166
'^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '@' +
167
goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
168
169
170
/**
171
* Get the name associated with the email address.
172
* @return {string} The name or personal portion of the address.
173
* @final
174
*/
175
goog.format.EmailAddress.prototype.getName = function() {
176
return this.name_;
177
};
178
179
180
/**
181
* Get the email address.
182
* @return {string} The email address.
183
* @final
184
*/
185
goog.format.EmailAddress.prototype.getAddress = function() {
186
return this.address;
187
};
188
189
190
/**
191
* Set the name associated with the email address.
192
* @param {string} name The name to associate.
193
* @final
194
*/
195
goog.format.EmailAddress.prototype.setName = function(name) {
196
this.name_ = name;
197
};
198
199
200
/**
201
* Set the email address.
202
* @param {string} address The email address.
203
* @final
204
*/
205
goog.format.EmailAddress.prototype.setAddress = function(address) {
206
this.address = address;
207
};
208
209
210
/**
211
* Return the address in a standard format:
212
* - remove extra spaces.
213
* - Surround name with quotes if it contains special characters.
214
* @return {string} The cleaned address.
215
* @override
216
*/
217
goog.format.EmailAddress.prototype.toString = function() {
218
return this.toStringInternal(goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_);
219
};
220
221
222
/**
223
* Check if a display name requires quoting.
224
* @param {string} name The display name
225
* @param {string} specialChars String that contains the characters that require
226
* the display name to be quoted. This may change based in whereas we are
227
* in EAI context or not.
228
* @return {boolean}
229
* @private
230
*/
231
goog.format.EmailAddress.isQuoteNeeded_ = function(name, specialChars) {
232
for (var i = 0; i < specialChars.length; i++) {
233
var specialChar = specialChars[i];
234
if (goog.string.contains(name, specialChar)) {
235
return true;
236
}
237
}
238
return false;
239
};
240
241
242
/**
243
* Return the address in a standard format:
244
* - remove extra spaces.
245
* - Surround name with quotes if it contains special characters.
246
* @param {string} specialChars String that contains the characters that require
247
* the display name to be quoted.
248
* @return {string} The cleaned address.
249
* @protected
250
*/
251
goog.format.EmailAddress.prototype.toStringInternal = function(specialChars) {
252
var name = this.getName();
253
254
// We intentionally remove double quotes in the name because escaping
255
// them to \" looks ugly.
256
name = name.replace(goog.format.EmailAddress.ALL_DOUBLE_QUOTES_, '');
257
258
// If the name has special characters, we need to quote it and escape \'s.
259
if (goog.format.EmailAddress.isQuoteNeeded_(name, specialChars)) {
260
name = '"' +
261
name.replace(goog.format.EmailAddress.ALL_BACKSLASHES_, '\\\\') + '"';
262
}
263
264
if (name == '') {
265
return this.address;
266
}
267
if (this.address == '') {
268
return name;
269
}
270
return name + ' <' + this.address + '>';
271
};
272
273
274
/**
275
* Determines if the current object is a valid email address.
276
* @return {boolean} Whether the email address is valid.
277
*/
278
goog.format.EmailAddress.prototype.isValid = function() {
279
return goog.format.EmailAddress.isValidAddrSpec(this.address);
280
};
281
282
283
/**
284
* Checks if the provided string is a valid email address. Supports both
285
* simple email addresses (address specs) and addresses that contain display
286
* names.
287
* @param {string} str The email address to check.
288
* @return {boolean} Whether the provided string is a valid address.
289
*/
290
goog.format.EmailAddress.isValidAddress = function(str) {
291
return goog.format.EmailAddress.parse(str).isValid();
292
};
293
294
295
/**
296
* Checks if the provided string is a valid address spec ([email protected]).
297
* @param {string} str The email address to check.
298
* @return {boolean} Whether the provided string is a valid address spec.
299
*/
300
goog.format.EmailAddress.isValidAddrSpec = function(str) {
301
// This is a fairly naive implementation, but it covers 99% of use cases.
302
// For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
303
return goog.format.EmailAddress.EMAIL_ADDRESS_.test(str);
304
};
305
306
307
/**
308
* Checks if the provided string is a valid local part (part before the '@') of
309
* an email address.
310
* @param {string} str The local part to check.
311
* @return {boolean} Whether the provided string is a valid local part.
312
*/
313
goog.format.EmailAddress.isValidLocalPartSpec = function(str) {
314
return goog.format.EmailAddress.LOCAL_PART_.test(str);
315
};
316
317
318
/**
319
* Checks if the provided string is a valid domain part (part after the '@') of
320
* an email address.
321
* @param {string} str The domain part to check.
322
* @return {boolean} Whether the provided string is a valid domain part.
323
*/
324
goog.format.EmailAddress.isValidDomainPartSpec = function(str) {
325
return goog.format.EmailAddress.DOMAIN_PART_.test(str);
326
};
327
328
329
/**
330
* Parses an email address of the form "name" &lt;address&gt; ("name" is
331
* optional) into an email address.
332
* @param {string} addr The address string.
333
* @param {function(new: goog.format.EmailAddress, string=,string=)} ctor
334
* EmailAddress constructor to instantiate the output address.
335
* @return {!goog.format.EmailAddress} The parsed address.
336
* @protected
337
*/
338
goog.format.EmailAddress.parseInternal = function(addr, ctor) {
339
// TODO(ecattell): Strip bidi markers.
340
var name = '';
341
var address = '';
342
for (var i = 0; i < addr.length;) {
343
var token = goog.format.EmailAddress.getToken_(addr, i);
344
if (token.charAt(0) == '<' && token.indexOf('>') != -1) {
345
var end = token.indexOf('>');
346
address = token.substring(1, end);
347
} else if (address == '') {
348
name += token;
349
}
350
i += token.length;
351
}
352
353
// Check if it's a simple email address of the form "[email protected]".
354
if (address == '' && name.indexOf('@') != -1) {
355
address = name;
356
name = '';
357
}
358
359
name = goog.string.collapseWhitespace(name);
360
name = goog.string.stripQuotes(name, '\'');
361
name = goog.string.stripQuotes(name, '"');
362
// Replace escaped quotes and slashes.
363
name = name.replace(goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_, '"');
364
name = name.replace(goog.format.EmailAddress.ESCAPED_BACKSLASHES_, '\\');
365
address = goog.string.collapseWhitespace(address);
366
return new ctor(address, name);
367
};
368
369
370
/**
371
* Parses an email address of the form "name" &lt;address&gt; into
372
* an email address.
373
* @param {string} addr The address string.
374
* @return {!goog.format.EmailAddress} The parsed address.
375
*/
376
goog.format.EmailAddress.parse = function(addr) {
377
return goog.format.EmailAddress.parseInternal(addr, goog.format.EmailAddress);
378
};
379
380
381
/**
382
* Parse a string containing email addresses of the form
383
* "name" &lt;address&gt; into an array of email addresses.
384
* @param {string} str The address list.
385
* @param {function(string)} parser The parser to employ.
386
* @param {function(string):boolean} separatorChecker Accepts a character and
387
* returns whether it should be considered an address separator.
388
* @return {!Array<!goog.format.EmailAddress>} The parsed emails.
389
* @protected
390
*/
391
goog.format.EmailAddress.parseListInternal = function(
392
str, parser, separatorChecker) {
393
var result = [];
394
var email = '';
395
var token;
396
397
// Remove non-UNIX-style newlines that would otherwise cause getToken_ to
398
// choke. Remove multiple consecutive whitespace characters for the same
399
// reason.
400
str = goog.string.collapseWhitespace(str);
401
402
for (var i = 0; i < str.length;) {
403
token = goog.format.EmailAddress.getToken_(str, i);
404
if (separatorChecker(token) || (token == ' ' && parser(email).isValid())) {
405
if (!goog.string.isEmptyOrWhitespace(email)) {
406
result.push(parser(email));
407
}
408
email = '';
409
i++;
410
continue;
411
}
412
email += token;
413
i += token.length;
414
}
415
416
// Add the final token.
417
if (!goog.string.isEmptyOrWhitespace(email)) {
418
result.push(parser(email));
419
}
420
return result;
421
};
422
423
424
/**
425
* Parses a string containing email addresses of the form
426
* "name" &lt;address&gt; into an array of email addresses.
427
* @param {string} str The address list.
428
* @return {!Array<!goog.format.EmailAddress>} The parsed emails.
429
*/
430
goog.format.EmailAddress.parseList = function(str) {
431
return goog.format.EmailAddress.parseListInternal(
432
str, goog.format.EmailAddress.parse,
433
goog.format.EmailAddress.isAddressSeparator);
434
};
435
436
437
/**
438
* Get the next token from a position in an address string.
439
* @param {string} str the string.
440
* @param {number} pos the position.
441
* @return {string} the token.
442
* @private
443
*/
444
goog.format.EmailAddress.getToken_ = function(str, pos) {
445
var ch = str.charAt(pos);
446
var p = goog.format.EmailAddress.OPENERS_.indexOf(ch);
447
if (p == -1) {
448
return ch;
449
}
450
if (goog.format.EmailAddress.isEscapedDlQuote_(str, pos)) {
451
// If an opener is an escaped quote we do not treat it as a real opener
452
// and keep accumulating the token.
453
return ch;
454
}
455
var closerChar = goog.format.EmailAddress.CLOSERS_.charAt(p);
456
var endPos = str.indexOf(closerChar, pos + 1);
457
458
// If the closer is a quote we go forward skipping escaped quotes until we
459
// hit the real closing one.
460
while (endPos >= 0 &&
461
goog.format.EmailAddress.isEscapedDlQuote_(str, endPos)) {
462
endPos = str.indexOf(closerChar, endPos + 1);
463
}
464
var token = (endPos >= 0) ? str.substring(pos, endPos + 1) : ch;
465
return token;
466
};
467
468
469
/**
470
* Checks if the character in the current position is an escaped double quote
471
* ( \" ).
472
* @param {string} str the string.
473
* @param {number} pos the position.
474
* @return {boolean} true if the char is escaped double quote.
475
* @private
476
*/
477
goog.format.EmailAddress.isEscapedDlQuote_ = function(str, pos) {
478
if (str.charAt(pos) != '"') {
479
return false;
480
}
481
var slashCount = 0;
482
for (var idx = pos - 1; idx >= 0 && str.charAt(idx) == '\\'; idx--) {
483
slashCount++;
484
}
485
return ((slashCount % 2) != 0);
486
};
487
488
489
/**
490
* @param {string} ch The character to test.
491
* @return {boolean} Whether the provided character is an address separator.
492
*/
493
goog.format.EmailAddress.isAddressSeparator = function(ch) {
494
return goog.string.contains(goog.format.EmailAddress.ADDRESS_SEPARATORS_, ch);
495
};
496
497